@@ -123,7 +123,6 @@ def read_utf8(filepath: str) -> str:
123123 with open (filepath , 'rb' ) as f :
124124 return f .read ().decode ('utf-8' )
125125
126-
127126class UnixSocketHTTPConnection (http .client .HTTPConnection ):
128127 """HTTPConnection that connects to a Unix domain socket."""
129128
@@ -332,6 +331,33 @@ def remove_vm(self, vm_id: str) -> None:
332331 self .rpc_call ('RemoveVm' , {'id' : vm_id })
333332 print (f"Removed VM { vm_id } " )
334333
334+ def resize_vm (
335+ self ,
336+ vm_id : str ,
337+ vcpu : Optional [int ] = None ,
338+ memory : Optional [int ] = None ,
339+ disk_size : Optional [int ] = None ,
340+ image : Optional [str ] = None ,
341+ ) -> None :
342+ """Resize a VM"""
343+ params = {"id" : vm_id }
344+ if vcpu is not None :
345+ params ["vcpu" ] = vcpu
346+ if memory is not None :
347+ params ["memory" ] = memory
348+ if disk_size is not None :
349+ params ["disk_size" ] = disk_size
350+ if image is not None :
351+ params ["image" ] = image
352+
353+ if len (params ) == 1 :
354+ raise Exception (
355+ "at least one parameter must be specified for resize: --vcpu, --memory, --disk, or --image"
356+ )
357+
358+ self .rpc_call ("ResizeVm" , params )
359+ print (f"Resized VM { vm_id } " )
360+
335361 def show_logs (self , vm_id : str , lines : int = 20 , follow : bool = False ) -> None :
336362 """Show VM logs"""
337363 path = f"/logs?id={ vm_id } &follow={ str (follow ).lower ()} &ansi=false&lines={ lines } "
@@ -609,6 +635,15 @@ def update_vm_app_compose(self, vm_id: str, app_compose: str) -> None:
609635 self .rpc_call ('UpgradeApp' , {'id' : vm_id ,
610636 'compose_file' : app_compose })
611637 print (f"App compose updated for VM { vm_id } " )
638+
639+ def update_vm_ports (self , vm_id : str , ports : List [str ]) -> None :
640+ """Update port mapping for a VM"""
641+ port_mappings = [parse_port_mapping (port ) for port in ports ]
642+ self .rpc_call (
643+ "UpgradeApp" , {"id" : vm_id ,
644+ "update_ports" : True , "ports" : port_mappings }
645+ )
646+ print (f"Port mapping updated for VM { vm_id } " )
612647
613648 def list_gpus (self , json_output : bool = False ) -> None :
614649 """List all available GPUs"""
@@ -884,6 +919,18 @@ def main():
884919 remove_parser = subparsers .add_parser ('remove' , help = 'Remove a VM' )
885920 remove_parser .add_argument ('vm_id' , help = 'VM ID to remove' )
886921
922+ # Resize command
923+ resize_parser = subparsers .add_parser ("resize" , help = "Resize a VM" )
924+ resize_parser .add_argument ("vm_id" , help = "VM ID to resize" )
925+ resize_parser .add_argument ("--vcpu" , type = int , help = "Number of vCPUs" )
926+ resize_parser .add_argument (
927+ "--memory" , type = parse_memory_size , help = "Memory size (e.g. 1G, 100M)"
928+ )
929+ resize_parser .add_argument (
930+ "--disk" , type = parse_disk_size , help = "Disk size (e.g. 20G, 1T)"
931+ )
932+ resize_parser .add_argument ("--image" , type = str , help = "Image name" )
933+
887934 # Logs command
888935 logs_parser = subparsers .add_parser ('logs' , help = 'Show VM logs' )
889936 logs_parser .add_argument ('vm_id' , help = 'VM ID to show logs for' )
@@ -1016,6 +1063,19 @@ def main():
10161063 update_user_config_parser .add_argument (
10171064 'user_config' , help = 'Path to user config file' )
10181065
1066+ # Update port mapping
1067+ update_ports_parser = subparsers .add_parser (
1068+ "update-ports" , help = "Update port mapping for a VM"
1069+ )
1070+ update_ports_parser .add_argument ("vm_id" , help = "VM ID to update" )
1071+ update_ports_parser .add_argument (
1072+ "--port" ,
1073+ action = "append" ,
1074+ type = str ,
1075+ required = True ,
1076+ help = "Port mapping in format: protocol[:address]:from:to (can be used multiple times)" ,
1077+ )
1078+
10191079 args = parser .parse_args ()
10201080
10211081 cli = VmmCLI (args .url , args .auth_user , args .auth_password )
@@ -1028,6 +1088,14 @@ def main():
10281088 cli .stop_vm (args .vm_id , args .force )
10291089 elif args .command == 'remove' :
10301090 cli .remove_vm (args .vm_id )
1091+ elif args .command == 'resize' :
1092+ cli .resize_vm (
1093+ args .vm_id ,
1094+ vcpu = args .vcpu ,
1095+ memory = args .memory ,
1096+ disk_size = args .disk ,
1097+ image = args .image ,
1098+ )
10311099 elif args .command == 'logs' :
10321100 cli .show_logs (args .vm_id , args .lines , args .follow )
10331101 elif args .command == 'compose' :
@@ -1046,6 +1114,8 @@ def main():
10461114 args .vm_id , open (args .user_config , 'r' ).read ())
10471115 elif args .command == 'update-app-compose' :
10481116 cli .update_vm_app_compose (args .vm_id , open (args .compose , 'r' ).read ())
1117+ elif args .command == "update-ports" :
1118+ cli .update_vm_ports (args .vm_id , args .port )
10491119 elif args .command == 'kms' :
10501120 if not args .kms_action :
10511121 kms_parser .print_help ()
0 commit comments