From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from firstgate.proxmox.com (firstgate.proxmox.com [212.224.123.68]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits)) (No client certificate requested) by lists.proxmox.com (Postfix) with ESMTPS id A3AD49CA0E for ; Thu, 1 Jun 2023 00:29:10 +0200 (CEST) Received: from firstgate.proxmox.com (localhost [127.0.0.1]) by firstgate.proxmox.com (Proxmox) with ESMTP id 81D37FBB7 for ; Thu, 1 Jun 2023 00:28:40 +0200 (CEST) Received: from bastionodiso.odiso.net (bastionodiso.odiso.net [IPv6:2a0a:1580:2000::2d]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (2048 bits) server-digest SHA256) (No client certificate requested) by firstgate.proxmox.com (Proxmox) with ESMTPS for ; Thu, 1 Jun 2023 00:28:37 +0200 (CEST) Received: from kvmformation3.odiso.net (formationkvm3.odiso.net [10.3.94.12]) by bastionodiso.odiso.net (Postfix) with ESMTP id 3FC7E80AD; Thu, 1 Jun 2023 00:28:36 +0200 (CEST) Received: by kvmformation3.odiso.net (Postfix, from userid 0) id 316D12D17C9; Thu, 1 Jun 2023 00:28:36 +0200 (CEST) From: Alexandre Derumier To: pve-devel@lists.proxmox.com Date: Thu, 1 Jun 2023 00:28:34 +0200 Message-Id: <20230531222834.1915972-3-aderumier@odiso.com> X-Mailer: git-send-email 2.30.2 In-Reply-To: <20230531222834.1915972-1-aderumier@odiso.com> References: <20230531222834.1915972-1-aderumier@odiso.com> MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-SPAM-LEVEL: Spam detection results: 0 AWL -0.001 Adjusted score from AWL reputation of From: address BAYES_00 -1.9 Bayes spam probability is 0 to 1% DMARC_MISSING 0.1 Missing DMARC policy HEADER_FROM_DIFFERENT_DOMAINS 0.249 From and EnvelopeFrom 2nd level mail domains are different KAM_DMARC_STATUS 0.01 Test Rule for DKIM or SPF Failure with Strict Alignment KAM_LAZY_DOMAIN_SECURITY 1 Sending domain does not have any anti-forgery methods SPF_HELO_NONE 0.001 SPF: HELO does not publish an SPF Record SPF_NONE 0.001 SPF: sender does not publish an SPF Record T_SCC_BODY_TEXT_LINE -0.01 - Subject: [pve-devel] [PATCH qemu-server 1/1] api2: qemu: add proxyto_callback to find node if not defined X-BeenThere: pve-devel@lists.proxmox.com X-Mailman-Version: 2.1.29 Precedence: list List-Id: Proxmox VE development discussion List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 31 May 2023 22:29:10 -0000 Signed-off-by: Alexandre Derumier --- PVE/API2/Qemu.pm | 157 ++++++++++++++++++++++++++++++++--------------- 1 file changed, 109 insertions(+), 48 deletions(-) diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index 587bb22..52daf5a 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -59,6 +59,19 @@ use base qw(PVE::RESTHandler); my $opt_force_description = "Force physical removal. Without this, we simple remove the disk from the config file and create an additional configuration entry called 'unused[n]', which contains the volume ID. Unlink of unused[n] always cause physical removal."; +my $find_vm_node = sub { + my ($rpcenv, $proxyto, $param) = @_; + return $param->{node} if $param->{node}; + # proxy to the node where the guest resides + my $vmid = $param->{vmid}; + return 'localhost' if !$vmid; + + my $vms = PVE::Cluster::get_vmlist(); + + return 'localhost' if !$vms->{ids}->{$vmid}; + return $vms->{ids}->{$vmid}->{node}; +}; + my $resolve_cdrom_alias = sub { my $param = shift; @@ -659,11 +672,12 @@ __PACKAGE__->register_method({ user => 'all', }, proxyto => 'node', + proxyto_callback => \&$find_vm_node, protected => 1, # qemu pid files are only readable by root parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), full => { type => 'boolean', optional => 1, @@ -684,8 +698,20 @@ __PACKAGE__->register_method({ my $rpcenv = PVE::RPCEnvironment::get(); my $authuser = $rpcenv->get_user(); + my $vmstatus = undef; - my $vmstatus = PVE::QemuServer::vmstatus(undef, $param->{full}); + if (!$param->{node}) { + my $vmlist = PVE::Cluster::get_vmlist()->{ids}; + my $rrd = PVE::Cluster::rrd_dump(); + for my $vmid (sort keys %$vmlist) { + my $data = $vmlist->{$vmid}; + next if $data->{type} ne 'qemu'; + my $entry = PVE::API2Tools::extract_vm_stats($vmid, $data, $rrd); + $vmstatus->{$vmid} = $entry; + } + } else { + $vmstatus = PVE::QemuServer::vmstatus(undef, $param->{full}); + } my $res = []; foreach my $vmid (keys %$vmstatus) { @@ -733,11 +759,12 @@ __PACKAGE__->register_method({ }, protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, parameters => { additionalProperties => 0, properties => PVE::QemuServer::json_config_properties( { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::Cluster::complete_next_vmid }), archive => { description => "The backup archive. Either the file system path to a .tar or .vma file (use '-' to pipe data from stdin) or a proxmox storage backup volume identifier.", @@ -878,7 +905,6 @@ __PACKAGE__->register_method({ &$check_vm_create_serial_perm($rpcenv, $authuser, $vmid, $pool, $param); &$check_vm_create_usb_perm($rpcenv, $authuser, $vmid, $pool, $param); - &$check_cpu_model_access($rpcenv, $authuser, $param); $check_drive_param->($param, $storecfg); @@ -1053,6 +1079,7 @@ __PACKAGE__->register_method({ path => '{vmid}', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Directory index", permissions => { user => 'all', @@ -1060,7 +1087,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), }, }, @@ -1125,7 +1152,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), timeframe => { description => "Specify the time frame you are interested in.", @@ -1171,7 +1198,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), timeframe => { description => "Specify the time frame you are interested in.", @@ -1200,12 +1227,12 @@ __PACKAGE__->register_method({ "pve2-vm/$param->{vmid}", $param->{timeframe}, $param->{cf}); }}); - __PACKAGE__->register_method({ name => 'vm_config', path => '{vmid}/config', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Get the virtual machine configuration with pending configuration " . "changes applied. Set the 'current' parameter to get the current configuration instead.", permissions => { @@ -1214,7 +1241,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), current => { description => "Get current values (instead of pending values).", @@ -1265,6 +1292,7 @@ __PACKAGE__->register_method({ path => '{vmid}/pending', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Get the virtual machine configuration with both current and pending values.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]], @@ -1272,7 +1300,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), }, }, @@ -1324,6 +1352,7 @@ __PACKAGE__->register_method({ path => '{vmid}/cloudinit', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Get the cloudinit configuration with both current and pending values.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]], @@ -1331,7 +1360,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), }, }, @@ -1396,6 +1425,7 @@ __PACKAGE__->register_method({ method => 'PUT', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Regenerate and change cloudinit config drive.", permissions => { check => ['perm', '/vms/{vmid}', 'VM.Config.Cloudinit'], @@ -1403,7 +1433,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), }, }, @@ -1873,6 +1903,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Set virtual machine options (asynchrounous API).", permissions => { check => ['perm', '/vms/{vmid}', $vm_config_perm_list, any => 1], @@ -1881,7 +1912,7 @@ __PACKAGE__->register_method({ additionalProperties => 0, properties => PVE::QemuServer::json_config_properties( { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), skiplock => get_standard_option('skiplock'), delete => { @@ -1930,6 +1961,7 @@ __PACKAGE__->register_method({ method => 'PUT', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Set virtual machine options (synchrounous API) - You should consider using the POST method instead for any actions involving hotplug or storage allocation.", permissions => { check => ['perm', '/vms/{vmid}', $vm_config_perm_list, any => 1], @@ -1938,7 +1970,7 @@ __PACKAGE__->register_method({ additionalProperties => 0, properties => PVE::QemuServer::json_config_properties( { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), skiplock => get_standard_option('skiplock'), delete => { @@ -1981,6 +2013,7 @@ __PACKAGE__->register_method({ method => 'DELETE', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Destroy the VM and all used/owned volumes. Removes any VM specific permissions" ." and firewall rules", permissions => { @@ -1989,7 +2022,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_stopped }), skiplock => get_standard_option('skiplock'), purge => { @@ -2089,6 +2122,7 @@ __PACKAGE__->register_method({ method => 'PUT', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Unlink/delete disk images.", permissions => { check => [ 'perm', '/vms/{vmid}', ['VM.Config.Disk']], @@ -2096,7 +2130,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), idlist => { type => 'string', format => 'pve-configid-list', @@ -2151,7 +2185,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), websocket => { optional => 1, @@ -2313,7 +2347,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), serial=> { optional => 1, @@ -2409,7 +2443,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), vncticket => { description => "Ticket from previous call to vncproxy.", @@ -2461,6 +2495,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Console' ]], }, @@ -2468,7 +2503,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), proxy => get_standard_option('spice-proxy', { optional => 1 }), }, @@ -2505,6 +2540,7 @@ __PACKAGE__->register_method({ path => '{vmid}/status', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Directory index", permissions => { user => 'all', @@ -2512,7 +2548,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), }, }, @@ -2550,6 +2586,7 @@ __PACKAGE__->register_method({ path => '{vmid}/status/current', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, protected => 1, # qemu pid files are only readable by root description => "Get virtual machine status.", permissions => { @@ -2558,7 +2595,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), }, }, @@ -2610,6 +2647,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Start virtual machine.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]], @@ -2617,7 +2655,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_stopped }), skiplock => get_standard_option('skiplock'), @@ -2775,6 +2813,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Stop virtual machine. The qemu process will exit immediately. This" . "is akin to pulling the power plug of a running computer and may damage the VM data", permissions => { @@ -2783,7 +2822,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_running }), skiplock => get_standard_option('skiplock'), @@ -2864,6 +2903,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Reset virtual machine.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]], @@ -2871,7 +2911,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_running }), skiplock => get_standard_option('skiplock'), @@ -2914,6 +2954,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Shutdown virtual machine. This is similar to pressing the power button on a physical machine." . "This will send an ACPI event for the guest OS, which should then proceed to a clean shutdown.", permissions => { @@ -2922,7 +2963,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_running }), skiplock => get_standard_option('skiplock'), @@ -3022,6 +3063,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Reboot the VM by shutting it down, and starting it again. Applies pending changes.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]], @@ -3029,7 +3071,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_running }), timeout => { @@ -3073,6 +3115,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Suspend virtual machine.", permissions => { description => "You need 'VM.PowerMgmt' on /vms/{vmid}, and if you have set 'todisk',". @@ -3083,7 +3126,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_running }), skiplock => get_standard_option('skiplock'), @@ -3167,6 +3210,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Resume virtual machine.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]], @@ -3174,7 +3218,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_running }), skiplock => get_standard_option('skiplock'), @@ -3241,6 +3285,7 @@ __PACKAGE__->register_method({ method => 'PUT', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Send key event to virtual machine.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Console' ]], @@ -3248,7 +3293,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_running }), skiplock => get_standard_option('skiplock'), @@ -3284,6 +3329,7 @@ __PACKAGE__->register_method({ path => '{vmid}/feature', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, protected => 1, description => "Check if feature for virtual machine is available.", permissions => { @@ -3292,7 +3338,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), feature => { description => "Feature to check.", @@ -3351,6 +3397,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Create a copy of virtual machine/template.", permissions => { description => "You need 'VM.Clone' permissions on /vms/{vmid}, and 'VM.Allocate' permissions " . @@ -3368,7 +3415,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), newid => get_standard_option('pve-vmid', { completion => \&PVE::Cluster::complete_next_vmid, @@ -3708,6 +3755,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Move volume to different storage or to a different VM.", permissions => { description => "You need 'VM.Config.Disk' permissions on /vms/{vmid}, " . @@ -3718,7 +3766,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), 'target-vmid' => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid, @@ -4170,6 +4218,7 @@ __PACKAGE__->register_method({ method => 'GET', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Get preconditions for migration.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Migrate' ]], @@ -4177,7 +4226,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), target => get_standard_option('pve-node', { description => "Target node.", @@ -4271,6 +4320,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Migrate virtual machine. Creates a new migration task.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Migrate' ]], @@ -4278,7 +4328,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), target => get_standard_option('pve-node', { description => "Target node.", @@ -4436,6 +4486,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Migrate virtual machine to a remote cluster. Creates a new migration task. EXPERIMENTAL feature!", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Migrate' ]], @@ -4443,7 +4494,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), 'target-vmid' => get_standard_option('pve-vmid', { optional => 1 }), 'target-endpoint' => get_standard_option('proxmox-remote', { @@ -4601,6 +4652,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Execute QEMU monitor commands.", permissions => { description => "Sys.Modify is required for (sub)commands which are not read-only ('info *' and 'help')", @@ -4609,7 +4661,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), command => { type => 'string', @@ -4652,6 +4704,7 @@ __PACKAGE__->register_method({ method => 'PUT', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Extend volume size.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Config.Disk' ]], @@ -4659,7 +4712,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), skiplock => get_standard_option('skiplock'), disk => { @@ -4780,12 +4833,13 @@ __PACKAGE__->register_method({ check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]], }, proxyto => 'node', + proxyto_callback => \&$find_vm_node, protected => 1, # qemu pid files are only readable by root parameters => { additionalProperties => 0, properties => { vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), }, }, returns => { @@ -4864,6 +4918,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Snapshot a VM.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot' ]], @@ -4871,7 +4926,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), snapname => get_standard_option('pve-snapshot-name'), vmstate => { @@ -4930,7 +4985,7 @@ __PACKAGE__->register_method({ additionalProperties => 0, properties => { vmid => get_standard_option('pve-vmid'), - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), snapname => get_standard_option('pve-snapshot-name'), }, }, @@ -4959,6 +5014,7 @@ __PACKAGE__->register_method({ method => 'PUT', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Update snapshot metadata.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot' ]], @@ -4966,7 +5022,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), snapname => get_standard_option('pve-snapshot-name'), description => { @@ -5015,6 +5071,7 @@ __PACKAGE__->register_method({ path => '{vmid}/snapshot/{snapname}/config', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Get snapshot configuration", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot', 'VM.Snapshot.Rollback', 'VM.Audit' ], any => 1], @@ -5022,7 +5079,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), snapname => get_standard_option('pve-snapshot-name'), }, @@ -5054,6 +5111,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Rollback VM state to specified snapshot.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot', 'VM.Snapshot.Rollback' ], any => 1], @@ -5061,7 +5119,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), snapname => get_standard_option('pve-snapshot-name'), start => { @@ -5113,6 +5171,7 @@ __PACKAGE__->register_method({ method => 'DELETE', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Delete a VM snapshot.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot' ]], @@ -5120,7 +5179,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), snapname => get_standard_option('pve-snapshot-name'), force => { @@ -5175,6 +5234,7 @@ __PACKAGE__->register_method({ method => 'POST', protected => 1, proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Create a Template.", permissions => { description => "You need 'VM.Allocate' permissions on /vms/{vmid}", @@ -5183,7 +5243,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid_stopped }), disk => { optional => 1, @@ -5249,6 +5309,7 @@ __PACKAGE__->register_method({ path => '{vmid}/cloudinit/dump', method => 'GET', proxyto => 'node', + proxyto_callback => \&$find_vm_node, description => "Get automatically generated cloudinit config.", permissions => { check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]], @@ -5256,7 +5317,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }), type => { description => 'Config type.', @@ -5294,7 +5355,7 @@ __PACKAGE__->register_method({ parameters => { additionalProperties => 0, properties => { - node => get_standard_option('pve-node'), + node => get_standard_option('pve-node', { optional => 1}), vmid => get_standard_option('pve-vmid'), storages => { type => 'string', -- 2.30.2