]> git.proxmox.com Git - qemu-server.git/commitdiff
cloud-init: hotplug support
authorWolfgang Bumiller <w.bumiller@proxmox.com>
Mon, 17 Aug 2015 13:46:07 +0000 (15:46 +0200)
committerWolfgang Bumiller <w.bumiller@proxmox.com>
Wed, 7 Mar 2018 08:11:31 +0000 (09:11 +0100)
*) always replace old cloudinit images
*) apply pending cloudinit changes when generating a new
image

For cloudinit we now always use vdisk_free before
vdisk_alloc in order to always replace old images, this
allows us to hotplug a new drive by setting it to
`none,media=cdrom` first (to eject the disk), then setting
it back to 'storage:cloudinit' to have a new image generated
after applying the currently pending changes.

PVE/API2/Qemu.pm
PVE/QemuServer.pm

index 8dea72cb23a806c88391a897a348a4691ae733c4..c39fc83c09a911c83c84a541fa0232b9f620dda8 100644 (file)
@@ -1098,6 +1098,7 @@ my $update_vm_api  = sub {
 
                if (PVE::QemuServer::is_valid_drivename($opt)) {
                    my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt});
+                   # FIXME: cloudinit: CDROM or Disk?
                    if (PVE::QemuServer::drive_is_cdrom($drive)) { # CDROM
                        $rpcenv->check_vm_perm($authuser, $vmid, undef, ['VM.Config.CDROM']);
                    } else {
index 7361a13999bdd0763e14029534a4711b92c0f773..7dfd4a30bed706a637b4f44b662df2b52b99e9e4 100644 (file)
@@ -537,6 +537,9 @@ EODESCR
        description => "Select BIOS implementation.",
        default => 'seabios',
     },
+};
+
+my $confdesc_cloudinit = {
     searchdomain => {
        optional => 1,
        type => 'string',
@@ -772,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);
@@ -1880,10 +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_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->{file} =~ m@[:/]vm-\d+-cloudinit(?:\.$QEMU_FORMAT_RE)?$@;
+    return 0 if $exclude_cloudinit && drive_is_cloudinit($drive);
 
     return $drive && $drive->{media} && ($drive->{media} eq 'cdrom');
 
@@ -4379,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};
@@ -4420,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