X-Git-Url: https://git.proxmox.com/?p=qemu-server.git;a=blobdiff_plain;f=PVE%2FAPI2%2FQemu.pm;h=7f737bf8eaf3725ebde21290f52a7a10a28866f1;hp=b0af9d902bbdb4cf5681dcedf01dd3d5b4868887;hb=b14477e718969468a9a5ef639533b9ff620e84ec;hpb=ca6621315ebb908a713fcf7661991aa4cfbd9e05 diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index b0af9d9..7f737bf 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -130,7 +130,7 @@ my $check_storage_access_clone = sub { # Note: $pool is only needed when creating a VM, because pool permissions # are automatically inherited if VM already exists inside a pool. my $create_disks = sub { - my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $settings, $default_storage) = @_; + my ($rpcenv, $authuser, $conf, $arch, $storecfg, $vmid, $pool, $settings, $default_storage) = @_; my $vollist = []; @@ -175,7 +175,7 @@ my $create_disks = sub { my $volid; if ($ds eq 'efidisk0') { - ($volid, $size) = PVE::QemuServer::create_efidisk($storecfg, $storeid, $vmid, $fmt); + ($volid, $size) = PVE::QemuServer::create_efidisk($storecfg, $storeid, $vmid, $fmt, $arch); } else { $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $fmt, undef, $size); } @@ -585,9 +585,11 @@ __PACKAGE__->register_method({ my $conf = $param; + my ($arch, undef) = PVE::QemuServer::get_basic_machine_info($conf); + eval { - $vollist = &$create_disks($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $param, $storage); + $vollist = &$create_disks($rpcenv, $authuser, $conf, $arch, $storecfg, $vmid, $pool, $param, $storage); if (!$conf->{bootdisk}) { my $firstdisk = PVE::QemuServer::resolve_first_disk($conf); @@ -599,6 +601,10 @@ __PACKAGE__->register_method({ $conf->{smbios1} = PVE::QemuServer::generate_smbios1_uuid(); } + if ((!defined($conf->{vmgenid}) || $conf->{vmgenid} eq '1') && $arch ne 'aarch64') { + $conf->{vmgenid} = PVE::QemuServer::generate_uuid(); + } + PVE::QemuConfig->write_config($vmid, $conf); }; @@ -642,8 +648,7 @@ __PACKAGE__->register_method({ if (my $err = $@) { eval { my $conffile = PVE::QemuConfig->config_file($vmid); - unlink($conffile) - or die "failed to remove config file: $@\n"; + unlink($conffile) or die "failed to remove config file: $!\n"; }; warn $@ if $@; die $err; @@ -824,6 +829,14 @@ __PACKAGE__->register_method({ default => 0, type => 'boolean', }, + snapshot => get_standard_option('pve-snapshot-name', { + description => "Fetch config values from given snapshot.", + optional => 1, + completion => sub { + my ($cmd, $pname, $cur, $args) = @_; + PVE::QemuConfig->snapshot_list($args->[0]); + }, + }), }, }, returns => { @@ -841,6 +854,17 @@ __PACKAGE__->register_method({ my $conf = PVE::QemuConfig->load_config($param->{vmid}); + my $snapname = $param->{snapshot}; + if ($snapname) { + my $snapshot = $conf->{snapshots}->{$snapname}; + die "snapshot '$snapname' does not exist\n" + if !defined($snapshot); + + # we need the digest of the file + $snapshot->{digest} = $conf->{digest}; + $conf = $snapshot; + } + delete $conf->{snapshots}; if (!$param->{current}) { @@ -1091,6 +1115,10 @@ my $update_vm_api = sub { # add macaddr my $net = PVE::QemuServer::parse_net($param->{$opt}); $param->{$opt} = PVE::QemuServer::print_net($net); + } elsif ($opt eq 'vmgenid') { + if ($param->{$opt} eq '1') { + $param->{$opt} = PVE::QemuServer::generate_uuid(); + } } } @@ -1170,6 +1198,8 @@ my $update_vm_api = sub { $conf = PVE::QemuConfig->load_config($vmid); # update/reload next if defined($conf->{pending}->{$opt}) && ($param->{$opt} eq $conf->{pending}->{$opt}); # skip if nothing changed + my ($arch, undef) = PVE::QemuServer::get_basic_machine_info($conf); + if (PVE::QemuServer::is_valid_drivename($opt)) { my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt}); # FIXME: cloudinit: CDROM or Disk? @@ -1181,7 +1211,7 @@ my $update_vm_api = sub { PVE::QemuServer::vmconfig_register_unused_drive($storecfg, $vmid, $conf, PVE::QemuServer::parse_drive($opt, $conf->{pending}->{$opt})) if defined($conf->{pending}->{$opt}); - &$create_disks($rpcenv, $authuser, $conf->{pending}, $storecfg, $vmid, undef, {$opt => $param->{$opt}}); + &$create_disks($rpcenv, $authuser, $conf->{pending}, $arch, $storecfg, $vmid, undef, {$opt => $param->{$opt}}); } else { $conf->{pending}->{$opt} = $param->{$opt}; } @@ -1513,6 +1543,7 @@ __PACKAGE__->register_method({ my $websocket = $param->{websocket}; my $conf = PVE::QemuConfig->load_config($vmid, $node); # check if VM exists + my $use_serial = ($conf->{vga} && ($conf->{vga} =~ m/^serial\d+$/)); my $authpath = "/vms/$vmid"; @@ -1521,13 +1552,14 @@ __PACKAGE__->register_method({ $sslcert = PVE::Tools::file_get_contents("/etc/pve/pve-root-ca.pem", 8192) if !$sslcert; - my ($remip, $family); + my $family; my $remcmd = []; if ($node ne 'localhost' && $node ne PVE::INotify::nodename()) { - ($remip, $family) = PVE::Cluster::remote_node_ip($node); + (undef, $family) = PVE::Cluster::remote_node_ip($node); + my $sshinfo = PVE::Cluster::get_ssh_info($node); # NOTE: kvm VNC traffic is already TLS encrypted or is known unsecure - $remcmd = ['/usr/bin/ssh', '-e', 'none', '-T', '-o', 'BatchMode=yes', $remip]; + $remcmd = PVE::Cluster::ssh_info_to_command($sshinfo, $use_serial ? '-t' : '-T'); } else { $family = PVE::Tools::get_host_address_family($node); } @@ -1543,8 +1575,7 @@ __PACKAGE__->register_method({ my $cmd; - if ($conf->{vga} && ($conf->{vga} =~ m/^serial\d+$/)) { - + if ($use_serial) { my $termcmd = [ '/usr/sbin/qm', 'terminal', $vmid, '-iface', $conf->{vga}, '-escape', '0' ]; @@ -1661,19 +1692,20 @@ __PACKAGE__->register_method({ my $ticket = PVE::AccessControl::assemble_vnc_ticket($authuser, $authpath); - my ($remip, $family); + my $family; + my $remcmd = []; if ($node ne 'localhost' && $node ne PVE::INotify::nodename()) { - ($remip, $family) = PVE::Cluster::remote_node_ip($node); + (undef, $family) = PVE::Cluster::remote_node_ip($node); + my $sshinfo = PVE::Cluster::get_ssh_info($node); + $remcmd = PVE::Cluster::ssh_info_to_command($sshinfo, '-t'); + push @$remcmd, '--'; } else { $family = PVE::Tools::get_host_address_family($node); } my $port = PVE::Tools::next_vnc_port($family); - my $remcmd = $remip ? - ['/usr/bin/ssh', '-e', 'none', '-t', $remip, '--'] : []; - my $termcmd = [ '/usr/sbin/qm', 'terminal', $vmid, '-escape', '0']; push @$termcmd, '-iface', $serial if $serial; @@ -2725,13 +2757,15 @@ __PACKAGE__->register_method({ } # auto generate a new uuid - my ($uuid, $uuid_str); - UUID::generate($uuid); - UUID::unparse($uuid, $uuid_str); my $smbios1 = PVE::QemuServer::parse_smbios1($newconf->{smbios1} || ''); - $smbios1->{uuid} = $uuid_str; + $smbios1->{uuid} = PVE::QemuServer::generate_uuid(); $newconf->{smbios1} = PVE::QemuServer::print_smbios1($smbios1); + # auto generate a new vmgenid if the option was set + if ($newconf->{vmgenid}) { + $newconf->{vmgenid} = PVE::QemuServer::generate_uuid(); + } + delete $newconf->{template}; if ($param->{name}) { @@ -2785,8 +2819,9 @@ __PACKAGE__->register_method({ delete $newconf->{lock}; # do not write pending changes - if ($newconf->{pending}) { - warn "found pending changes, discarding for clone\n"; + if (my @changes = keys %{$newconf->{pending}}) { + my $pending = join(',', @changes); + warn "found pending changes for '$pending', discarding for clone\n"; delete $newconf->{pending}; }