@@ -287,7 +287,7 @@ def list_vms(self, verbose: bool = False, json_output: bool = False) -> None:
287287
288288 headers = ['VM ID' , 'App ID' , 'Name' , 'Status' , 'Uptime' ]
289289 if verbose :
290- headers .extend (['vCPU' , 'Memory' , 'Disk' , 'Image' , 'GPUs' ])
290+ headers .extend (['Instance ID' , ' vCPU' , 'Memory' , 'Disk' , 'Image' , 'GPUs' ])
291291
292292 rows = []
293293 for vm in vms :
@@ -303,6 +303,7 @@ def list_vms(self, verbose: bool = False, json_output: bool = False) -> None:
303303 config = vm .get ('configuration' , {})
304304 gpu_info = self ._format_gpu_info (config .get ('gpus' ))
305305 row .extend ([
306+ vm .get ('instance_id' , '-' ) or '-' ,
306307 config .get ('vcpu' , '-' ),
307308 f"{ config .get ('memory' , '-' )} MB" ,
308309 f"{ config .get ('disk_size' , '-' )} GB" ,
@@ -911,6 +912,50 @@ def update_vm(
911912 else :
912913 print (f"No updates specified for VM { vm_id } " )
913914
915+ def show_info (self , vm_id : str , json_output : bool = False ) -> None :
916+ """Show detailed information about a VM"""
917+ response = self .rpc_call ('GetInfo' , {'id' : vm_id })
918+
919+ if not response .get ('found' , False ) or 'info' not in response :
920+ print (f"VM with ID { vm_id } not found" )
921+ return
922+
923+ info = response ['info' ]
924+
925+ if json_output :
926+ print (json .dumps (info , indent = 2 ))
927+ return
928+
929+ config = info .get ('configuration' , {})
930+
931+ print (f"VM ID: { info .get ('id' , '-' )} " )
932+ print (f"Name: { info .get ('name' , '-' )} " )
933+ print (f"Status: { info .get ('status' , '-' )} " )
934+ print (f"Uptime: { info .get ('uptime' , '-' )} " )
935+ print (f"App ID: { info .get ('app_id' , '-' )} " )
936+ print (f"Instance ID: { info .get ('instance_id' , '-' ) or '-' } " )
937+ print (f"App URL: { info .get ('app_url' , '-' ) or '-' } " )
938+ print (f"Image: { config .get ('image' , '-' )} " )
939+ print (f"Image Version: { info .get ('image_version' , '-' )} " )
940+ print (f"vCPU: { config .get ('vcpu' , '-' )} " )
941+ print (f"Memory: { config .get ('memory' , '-' )} MB" )
942+ print (f"Disk: { config .get ('disk_size' , '-' )} GB" )
943+ print (f"GPUs: { self ._format_gpu_info (config .get ('gpus' ))} " )
944+ print (f"Boot Progress: { info .get ('boot_progress' , '-' )} " )
945+ if info .get ('boot_error' ):
946+ print (f"Boot Error: { info ['boot_error' ]} " )
947+ if info .get ('exited_at' ):
948+ print (f"Exited At: { info ['exited_at' ]} " )
949+ if info .get ('shutdown_progress' ):
950+ print (f"Shutdown: { info ['shutdown_progress' ]} " )
951+
952+ events = info .get ('events' , [])
953+ if events :
954+ print (f"\n Recent Events:" )
955+ for event in events [- 10 :]:
956+ ts = event .get ('timestamp' , 0 )
957+ print (f" [{ event .get ('event' , '' )} ] { event .get ('body' , '' )} (ts: { ts } )" )
958+
914959 def list_gpus (self , json_output : bool = False ) -> None :
915960 """List all available GPUs"""
916961 response = self .rpc_call ('ListGpus' )
@@ -1227,6 +1272,12 @@ def main():
12271272 lsvm_parser .add_argument (
12281273 '--json' , action = 'store_true' , help = 'Output in JSON format for automation' )
12291274
1275+ # Info command
1276+ info_parser = subparsers .add_parser ('info' , help = 'Show detailed VM information' )
1277+ info_parser .add_argument ('vm_id' , help = 'VM ID to show info for' )
1278+ info_parser .add_argument (
1279+ '--json' , action = 'store_true' , help = 'Output in JSON format for automation' )
1280+
12301281 # Start command
12311282 start_parser = subparsers .add_parser ('start' , help = 'Start a VM' )
12321283 start_parser .add_argument ('vm_id' , help = 'VM ID to start' )
@@ -1502,6 +1553,8 @@ def main():
15021553
15031554 if args .command == 'lsvm' :
15041555 cli .list_vms (args .verbose , args .json )
1556+ elif args .command == 'info' :
1557+ cli .show_info (args .vm_id , args .json )
15051558 elif args .command == 'start' :
15061559 cli .start_vm (args .vm_id )
15071560 elif args .command == 'stop' :
0 commit comments