X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=PVE%2FQemuServer.pm;h=bfab406067e1d3ed77ab6b84861de07b76a18586;hb=931432bd2d31a3203b309235768aa626bc1f482d;hp=8fab6b85e68caf651170426250b7f723c565944f;hpb=0c9a7596f6b686ead232927851200554c997fa44;p=qemu-server.git diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm index 8fab6b8..bfab406 100644 --- a/PVE/QemuServer.pm +++ b/PVE/QemuServer.pm @@ -45,6 +45,8 @@ my $qemu_snap_storage = {rbd => 1, sheepdog => 1}; my $cpuinfo = PVE::ProcFSTools::read_cpuinfo(); +my $QEMU_FORMAT_RE = qr/raw|cow|qcow|qcow2|qed|vmdk|cloop/; + # Note about locking: we use flock on the config file protect # against concurent actions. # Aditionaly, we have a 'lock' setting in the config file. This @@ -535,6 +537,9 @@ EODESCR description => "Select BIOS implementation.", default => 'seabios', }, +}; + +my $confdesc_cloudinit = { searchdomain => { optional => 1, type => 'string', @@ -770,7 +775,11 @@ PVE::JSONSchema::register_standard_option("pve-qm-ipconfig", $netdesc); for (my $i = 0; $i < $MAX_NETS; $i++) { $confdesc->{"net$i"} = $netdesc; - $confdesc->{"ipconfig$i"} = $ipconfigdesc; + $confdesc_cloudinit->{"ipconfig$i"} = $ipconfigdesc; +} + +foreach my $key (keys %$confdesc_cloudinit) { + $confdesc->{$key} = $confdesc_cloudinit->{$key}; } PVE::JSONSchema::register_format('pve-volume-id-or-qm-path', \&verify_volume_id_or_qm_path); @@ -1878,8 +1887,15 @@ sub print_cpu_device { return "$cpu-x86_64-cpu,id=cpu$id,socket-id=$current_socket,core-id=$current_core,thread-id=0"; } -sub drive_is_cdrom { +sub drive_is_cloudinit { my ($drive) = @_; + return $drive->{file} =~ m@[:/]vm-\d+-cloudinit(?:\.$QEMU_FORMAT_RE)?$@; +} + +sub drive_is_cdrom { + my ($drive, $exclude_cloudinit) = @_; + + return 0 if $exclude_cloudinit && drive_is_cloudinit($drive); return $drive && $drive->{media} && ($drive->{media} eq 'cdrom'); @@ -2053,7 +2069,10 @@ sub vmconfig_undelete_pending_option { sub vmconfig_register_unused_drive { my ($storecfg, $vmid, $conf, $drive) = @_; - if (!drive_is_cdrom($drive)) { + if (drive_is_cloudinit($drive)) { + eval { PVE::Storage::vdisk_free($storecfg, $drive->{file}) }; + warn $@ if $@; + } elsif (!drive_is_cdrom($drive)) { my $volid = $drive->{file}; if (vm_is_volid_owner($storecfg, $vmid, $volid)) { PVE::QemuConfig->add_unused_volume($conf, $volid, $vmid); @@ -2287,7 +2306,7 @@ sub destroy_vm { foreach_drive($conf, sub { my ($ds, $drive) = @_; - return if drive_is_cdrom($drive); + return if drive_is_cdrom($drive, 1); my $volid = $drive->{file}; @@ -4372,6 +4391,22 @@ sub vmconfig_hotplug_pending { } } + my $apply_pending_cloudinit; + $apply_pending_cloudinit = sub { + my ($key, $value) = @_; + $apply_pending_cloudinit = sub {}; # once is enough + + my @cloudinit_opts = keys %$confdesc_cloudinit; + foreach my $opt (keys %{$conf->{pending}}) { + next if !grep { $_ eq $opt } @cloudinit_opts; + $conf->{$opt} = delete $conf->{pending}->{$opt}; + } + + my $new_conf = { %$conf }; + $new_conf->{$key} = $value; + PVE::QemuServer::Cloudinit::generate_cloudinitconfig($new_conf, $vmid); + }; + foreach my $opt (keys %{$conf->{pending}}) { next if $selection && !$selection->{$opt}; my $value = $conf->{pending}->{$opt}; @@ -4413,6 +4448,10 @@ sub vmconfig_hotplug_pending { $vmid, $opt, $value); } elsif (is_valid_drivename($opt)) { # some changes can be done without hotplug + my $drive = parse_drive($opt, $value); + if (drive_is_cloudinit($drive)) { + &$apply_pending_cloudinit($opt, $value); + } vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk}, $vmid, $opt, $value, 1); } elsif ($opt =~ m/^memory$/) { #dimms @@ -4675,6 +4714,9 @@ sub vmconfig_update_disk { if ($drive->{file} eq 'none') { vm_mon_cmd($vmid, "eject",force => JSON::true,device => "drive-$opt"); + if (drive_is_cloudinit($old_drive)) { + vmconfig_register_unused_drive($storecfg, $vmid, $conf, $old_drive); + } } else { my $path = get_iso_path($storecfg, $vmid, $drive->{file}); vm_mon_cmd($vmid, "eject", force => JSON::true,device => "drive-$opt"); # force eject if locked @@ -6157,7 +6199,7 @@ sub qemu_img_convert { sub qemu_img_format { my ($scfg, $volname) = @_; - if ($scfg->{path} && $volname =~ m/\.(raw|cow|qcow|qcow2|qed|vmdk|cloop)$/) { + if ($scfg->{path} && $volname =~ m/\.($QEMU_FORMAT_RE)$/) { return $1; } else { return "raw"; @@ -6353,7 +6395,17 @@ sub clone_disk { my ($size) = PVE::Storage::volume_size_info($storecfg, $drive->{file}, 3); print "create full clone of drive $drivename ($drive->{file})\n"; - $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $dst_format, undef, ($size/1024)); + my $name = undef; + if (drive_is_cloudinit($drive)) { + $name = "vm-$newvmid-cloudinit"; + # cloudinit only supports raw and qcow2 atm: + if ($dst_format eq 'qcow2') { + $name .= '.qcow2'; + } elsif ($dst_format ne 'raw') { + die "clone: unhandled format for cloudinit image\n"; + } + } + $newvolid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $newvmid, $dst_format, $name, ($size/1024)); push @$newvollist, $newvolid; PVE::Storage::activate_volumes($storecfg, [$newvolid]);