* [pve-devel] [PATCH v2 qemu-server 1/6] cloudinit: add cloudinit section for current generated config.
2021-04-01 0:21 [pve-devel] [PATCH v2 qemu-server 0/6] cloudinit pending behaviour change Alexandre Derumier
@ 2021-04-01 0:21 ` Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 2/6] generate cloudinit drive on offline plug Alexandre Derumier
` (4 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Alexandre Derumier @ 2021-04-01 0:21 UTC (permalink / raw)
To: pve-devel
Instead using vm pending options for pending cloudinit generated config,
write current generated cloudinit config in a new [special:cloudinit] SECTION.
Currently, some options like vm name, nic mac address can be hotplugged,
so they are not way to know if the cloud-init disk is already updated.
---
PVE/QemuServer.pm | 21 +++++++++++++++++----
PVE/QemuServer/Cloudinit.pm | 31 +++++++++++++++++++++++++++++++
2 files changed, 48 insertions(+), 4 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 57cfe62..9a7add5 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -1875,6 +1875,7 @@ sub vmconfig_register_unused_drive {
if (drive_is_cloudinit($drive)) {
eval { PVE::Storage::vdisk_free($storecfg, $drive->{file}) };
warn $@ if $@;
+ delete $conf->{cloudinit};
} elsif (!drive_is_cdrom($drive)) {
my $volid = $drive->{file};
if (vm_is_volid_owner($storecfg, $vmid, $volid)) {
@@ -2135,6 +2136,7 @@ sub parse_vm_config {
digest => Digest::SHA::sha1_hex($raw),
snapshots => {},
pending => {},
+ cloudinit => {},
};
$filename =~ m|/qemu-server/(\d+)\.conf$|
@@ -2159,6 +2161,11 @@ sub parse_vm_config {
$descr = undef;
$conf = $res->{$section} = {};
next;
+ } elsif ($line =~ m/^\[special:cloudinit\]\s*$/i) {
+ $section = 'cloudinit';
+ $descr = undef;
+ $conf = $res->{$section} = {};
+ next;
} elsif ($line =~ m/^\[([a-z][a-z0-9_\-]+)\]\s*$/i) {
$section = $1;
@@ -2219,7 +2226,6 @@ sub parse_vm_config {
warn "vm $vmid - unable to parse config: $line\n";
}
}
-
if (defined($descr)) {
$descr =~ s/\s+$//;
$conf->{description} = $descr;
@@ -2256,7 +2262,7 @@ sub write_vm_config {
foreach my $key (keys %$cref) {
next if $key eq 'digest' || $key eq 'description' || $key eq 'snapshots' ||
- $key eq 'snapstate' || $key eq 'pending';
+ $key eq 'snapstate' || $key eq 'pending' || $key eq 'cloudinit';
my $value = $cref->{$key};
if ($key eq 'delete') {
die "propertry 'delete' is only allowed in [PENDING]\n"
@@ -2280,6 +2286,8 @@ sub write_vm_config {
&$cleanup_config($conf->{pending}, 1);
+ &$cleanup_config($conf->{cloudinit}, 1);
+
foreach my $snapname (keys %{$conf->{snapshots}}) {
die "internal error: snapshot name '$snapname' is forbidden" if lc($snapname) eq 'pending';
&$cleanup_config($conf->{snapshots}->{$snapname}, undef, $snapname);
@@ -2310,7 +2318,7 @@ sub write_vm_config {
}
foreach my $key (sort keys %$conf) {
- next if $key =~ /^(digest|description|pending|snapshots)$/;
+ next if $key =~ /^(digest|description|pending|cloudinit|snapshots)$/;
$raw .= "$key: $conf->{$key}\n";
}
return $raw;
@@ -2323,6 +2331,11 @@ sub write_vm_config {
$raw .= &$generate_raw_config($conf->{pending}, 1);
}
+ if (scalar(keys %{$conf->{cloudinit}})){
+ $raw .= "\n[special:cloudinit]\n";
+ $raw .= &$generate_raw_config($conf->{cloudinit}, 1);
+ }
+
foreach my $snapname (sort keys %{$conf->{snapshots}}) {
$raw .= "\n[$snapname]\n";
$raw .= &$generate_raw_config($conf->{snapshots}->{$snapname});
@@ -4702,9 +4715,9 @@ sub vmconfig_apply_pending {
$conf->{$opt} = delete $conf->{pending}->{$opt};
}
}
-
# write all changes at once to avoid unnecessary i/o
PVE::QemuConfig->write_config($vmid, $conf);
+
}
sub vmconfig_update_net {
diff --git a/PVE/QemuServer/Cloudinit.pm b/PVE/QemuServer/Cloudinit.pm
index c464bf3..8da18b4 100644
--- a/PVE/QemuServer/Cloudinit.pm
+++ b/PVE/QemuServer/Cloudinit.pm
@@ -570,6 +570,37 @@ sub generate_cloudinitconfig {
$generator->($conf, $vmid, $drive, $volname, $storeid);
});
+
+ my $cloudinitconf = delete $conf->{cloudinit};
+ $cloudinitconf = {};
+
+ my @cloudinit_opts = keys %{PVE::QemuServer::cloudinit_config_properties()};
+ push @cloudinit_opts, 'name';
+
+ foreach my $opt (@cloudinit_opts) {
+
+ if ($opt =~ m/^ipconfig(\d+)/) {
+ my $netid = "net$1";
+ next if !defined($conf->{$netid});
+ $conf->{cloudinit}->{$netid} = $conf->{$netid};
+ }
+
+ $conf->{cloudinit}->{$opt} = $conf->{$opt} if $conf->{$opt};
+ }
+
+ $conf->{cloudinit}->{name} = "VM$vmid" if !$conf->{cloudinit}->{name};
+
+ foreach my $opt (keys %{$conf}) {
+ if (PVE::QemuServer::is_valid_drivename($opt)) {
+ my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
+ if (PVE::QemuServer::drive_is_cloudinit($drive)) {
+ $conf->{cloudinit}->{$opt} = $conf->{$opt};
+ }
+ }
+ }
+
+ PVE::QemuConfig->write_config($vmid, $conf);
+
}
sub dump_cloudinit_config {
--
2.20.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH v2 qemu-server 2/6] generate cloudinit drive on offline plug
2021-04-01 0:21 [pve-devel] [PATCH v2 qemu-server 0/6] cloudinit pending behaviour change Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 1/6] cloudinit: add cloudinit section for current generated config Alexandre Derumier
@ 2021-04-01 0:21 ` Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 3/6] cloudinit: make cloudnit options fastplug Alexandre Derumier
` (3 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Alexandre Derumier @ 2021-04-01 0:21 UTC (permalink / raw)
To: pve-devel
Currently when only generate it at vm start
---
PVE/QemuServer.pm | 10 ++++++++++
1 file changed, 10 insertions(+)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 9a7add5..5092b49 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -4702,6 +4702,8 @@ sub vmconfig_apply_pending {
PVE::QemuConfig->cleanup_pending($conf);
+ my $generate_cloudnit = undef;
+
foreach my $opt (keys %{$conf->{pending}}) { # add/change
next if $opt eq 'delete'; # just to be sure
eval {
@@ -4709,15 +4711,23 @@ sub vmconfig_apply_pending {
vmconfig_register_unused_drive($storecfg, $vmid, $conf, parse_drive($opt, $conf->{$opt}))
}
};
+
+ if (is_valid_drivename($opt)) {
+ my $drive = parse_drive($opt, $conf->{pending}->{$opt});
+ $generate_cloudnit = 1 if drive_is_cloudinit($drive);
+ }
+
if (my $err = $@) {
$add_apply_error->($opt, $err);
} else {
$conf->{$opt} = delete $conf->{pending}->{$opt};
}
}
+
# write all changes at once to avoid unnecessary i/o
PVE::QemuConfig->write_config($vmid, $conf);
+ PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid) if $generate_cloudnit;
}
sub vmconfig_update_net {
--
2.20.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH v2 qemu-server 3/6] cloudinit: make cloudnit options fastplug
2021-04-01 0:21 [pve-devel] [PATCH v2 qemu-server 0/6] cloudinit pending behaviour change Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 1/6] cloudinit: add cloudinit section for current generated config Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 2/6] generate cloudinit drive on offline plug Alexandre Derumier
@ 2021-04-01 0:21 ` Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 4/6] api2: add cloudinit config api Alexandre Derumier
` (2 subsequent siblings)
5 siblings, 0 replies; 7+ messages in thread
From: Alexandre Derumier @ 2021-04-01 0:21 UTC (permalink / raw)
To: pve-devel
---
PVE/QemuServer.pm | 30 +++---------------------------
1 file changed, 3 insertions(+), 27 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 5092b49..900e227 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -4456,9 +4456,10 @@ sub vmconfig_hotplug_pending {
$errors->{$opt} = "hotplug problem - $msg";
};
+ my @cloudinit_opts = keys %$confdesc_cloudinit;
my $changes = 0;
foreach my $opt (keys %{$conf->{pending}}) { # add/change
- if ($fast_plug_option->{$opt}) {
+ if ($fast_plug_option->{$opt} || grep { $_ eq $opt } @cloudinit_opts) {
$conf->{$opt} = $conf->{pending}->{$opt};
delete $conf->{pending}->{$opt};
$changes = 1;
@@ -4531,31 +4532,6 @@ sub vmconfig_hotplug_pending {
}
}
- my ($apply_pending_cloudinit, $apply_pending_cloudinit_done);
- $apply_pending_cloudinit = sub {
- return if $apply_pending_cloudinit_done; # once is enough
- $apply_pending_cloudinit_done = 1; # once is enough
-
- my ($key, $value) = @_;
-
- 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 $pending_delete_hash = PVE::QemuConfig->parse_pending_delete($conf->{pending}->{delete});
- foreach my $opt (sort keys %$pending_delete_hash) {
- next if !grep { $_ eq $opt } @cloudinit_opts;
- PVE::QemuConfig->remove_from_pending_delete($conf, $opt);
- delete $conf->{$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};
@@ -4602,7 +4578,7 @@ sub vmconfig_hotplug_pending {
# some changes can be done without hotplug
my $drive = parse_drive($opt, $value);
if (drive_is_cloudinit($drive)) {
- &$apply_pending_cloudinit($opt, $value);
+ PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid);
}
vmconfig_update_disk($storecfg, $conf, $hotplug_features->{disk},
$vmid, $opt, $value, $arch, $machine_type);
--
2.20.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH v2 qemu-server 4/6] api2: add cloudinit config api
2021-04-01 0:21 [pve-devel] [PATCH v2 qemu-server 0/6] cloudinit pending behaviour change Alexandre Derumier
` (2 preceding siblings ...)
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 3/6] cloudinit: make cloudnit options fastplug Alexandre Derumier
@ 2021-04-01 0:21 ` Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 5/6] api2: add cloudinit_update Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 6/6] add cloudinit hotplug Alexandre Derumier
5 siblings, 0 replies; 7+ messages in thread
From: Alexandre Derumier @ 2021-04-01 0:21 UTC (permalink / raw)
To: pve-devel
---
PVE/API2/Qemu.pm | 73 +++++++++++++++++++++++++++++++++++++
PVE/CLI/qm.pm | 1 +
PVE/QemuServer/Cloudinit.pm | 70 +++++++++++++++++++++++++++++++++++
3 files changed, 144 insertions(+)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index ea74c69..b6122fe 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -21,6 +21,7 @@ use PVE::ReplicationConfig;
use PVE::GuestHelpers;
use PVE::QemuConfig;
use PVE::QemuServer;
+use PVE::QemuServer::Cloudinit;
use PVE::QemuServer::Drive;
use PVE::QemuServer::CPUConfig;
use PVE::QemuServer::Monitor qw(mon_cmd);
@@ -1039,6 +1040,78 @@ __PACKAGE__->register_method({
return PVE::GuestHelpers::config_with_pending_array($conf, $pending_delete_hash);
}});
+__PACKAGE__->register_method({
+ name => 'cloudinit_pending',
+ path => '{vmid}/cloudinit',
+ method => 'GET',
+ proxyto => 'node',
+ description => "Get the cloudinit configuration with both current and pending values.",
+ permissions => {
+ check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ vmid => get_standard_option('pve-vmid', { completion => \&PVE::QemuServer::complete_vmid }),
+ },
+ },
+ returns => {
+ type => "array",
+ items => {
+ type => "object",
+ properties => {
+ key => {
+ description => "Configuration option name.",
+ type => 'string',
+ },
+ value => {
+ description => "Current value.",
+ type => 'string',
+ optional => 1,
+ },
+ pending => {
+ description => "Pending value.",
+ type => 'string',
+ optional => 1,
+ },
+ delete => {
+ description => "Indicates a pending delete request if present and not 0. " .
+ "The value 2 indicates a force-delete request.",
+ type => 'integer',
+ minimum => 0,
+ maximum => 2,
+ optional => 1,
+ },
+ },
+ },
+ },
+ code => sub {
+ my ($param) = @_;
+
+ my $vmid = $param->{vmid};
+ my $conf = PVE::QemuConfig->load_config($vmid);
+
+ if( defined($conf->{cipassword}) &&
+ defined($conf->{cloudinit}->{cipassword}) &&
+ $conf->{cipassword} ne $conf->{cloudinit}->{cipassword}) {
+ $conf->{cipassword} = '********** ';
+ } elsif (defined($conf->{cipassword})) {
+ $conf->{cipassword} = '**********';
+ }
+
+ $conf->{cloudinit}->{cipassword} = '**********' if defined($conf->{cloudinit}->{cipassword});
+
+ my $res = [];
+ my $pending = PVE::QemuServer::Cloudinit::get_pending_config($conf, $vmid);
+
+ foreach my $opt (keys %{$pending}) {
+ push @$res, $pending->{$opt};
+ }
+
+ return $res;
+ }});
+
# POST/PUT {vmid}/config implementation
#
# The original API used PUT (idempotent) an we assumed that all operations
diff --git a/PVE/CLI/qm.pm b/PVE/CLI/qm.pm
index f8972bd..e24b832 100755
--- a/PVE/CLI/qm.pm
+++ b/PVE/CLI/qm.pm
@@ -996,6 +996,7 @@ our $cmddef = {
my $data = shift;
print "$data\n";
}],
+ pending => [ "PVE::API2::Qemu", 'cloudinit_pending', ['vmid'], { node => $nodename }, \&PVE::GuestHelpers::format_pending ]
},
};
diff --git a/PVE/QemuServer/Cloudinit.pm b/PVE/QemuServer/Cloudinit.pm
index 8da18b4..99aba5c 100644
--- a/PVE/QemuServer/Cloudinit.pm
+++ b/PVE/QemuServer/Cloudinit.pm
@@ -628,4 +628,74 @@ sub dump_cloudinit_config {
}
}
+sub get_pending_config {
+ my ($conf, $vmid) = @_;
+
+ my $newconf = { %{$conf} };
+ my $cloudinit_current = $newconf->{cloudinit};
+ my @cloudinit_opts = keys %{PVE::QemuServer::cloudinit_config_properties()};
+ push @cloudinit_opts, 'name';
+
+ #add cloud-init drive
+ my $drives = {};
+ PVE::QemuConfig->foreach_volume($newconf, sub {
+ my ($ds, $drive) = @_;
+ $drives->{$ds} = 1 if PVE::QemuServer::drive_is_cloudinit($drive);
+ });
+
+ PVE::QemuConfig->foreach_volume($cloudinit_current, sub {
+ my ($ds, $drive) = @_;
+ $drives->{$ds} = 1 if PVE::QemuServer::drive_is_cloudinit($drive);
+ });
+ foreach my $ds (keys %{$drives}) {
+ push @cloudinit_opts, $ds;
+ }
+
+ $newconf->{name} = "VM$vmid" if !$newconf->{name};
+
+ my $print_net_addr = sub {
+ my ($conf, $opt, $netid) = @_;
+
+ if (defined($conf->{$netid})) {
+
+ my $net = PVE::QemuServer::parse_net($conf->{$netid});
+ if (defined($conf->{$opt})) {
+ $conf->{$opt} .= ",macaddr=".$net->{macaddr} if $net->{macaddr};
+ } else {
+ $conf->{$opt} = "";
+ }
+ }
+ };
+
+ my $res = {};
+ foreach my $opt (@cloudinit_opts) {
+
+ #add macaddr to ipconfig
+ if ($opt =~ m/^ipconfig(\d+)/) {
+ my $netid = "net$1";
+ next if !defined($newconf->{$netid}) && !defined($cloudinit_current->{$netid}) && !defined($newconf->{$opt}) && !defined($cloudinit_current->{$opt} );
+
+ &$print_net_addr($newconf, $opt, $netid);
+ &$print_net_addr($cloudinit_current, $opt, $netid);
+ }
+
+ my $item = {
+ key => $opt,
+ };
+ if ($cloudinit_current->{$opt}) {
+ $item->{value} = $cloudinit_current->{$opt};
+ if ($newconf->{$opt}) {
+ $item->{pending} = $newconf->{$opt} if $newconf->{$opt} ne $cloudinit_current->{$opt};
+ } else {
+ $item->{delete} = 1;
+ }
+ } else {
+ $item->{pending} = $newconf->{$opt} if $newconf->{$opt}
+ }
+
+ $res->{$opt} = $item;
+ }
+ return $res;
+}
+
1;
--
2.20.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH v2 qemu-server 5/6] api2: add cloudinit_update
2021-04-01 0:21 [pve-devel] [PATCH v2 qemu-server 0/6] cloudinit pending behaviour change Alexandre Derumier
` (3 preceding siblings ...)
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 4/6] api2: add cloudinit config api Alexandre Derumier
@ 2021-04-01 0:21 ` Alexandre Derumier
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 6/6] add cloudinit hotplug Alexandre Derumier
5 siblings, 0 replies; 7+ messages in thread
From: Alexandre Derumier @ 2021-04-01 0:21 UTC (permalink / raw)
To: pve-devel
This allow to regenerate the config drive with 1 api call.
This also avoid to delete drive first, and recreate it again.
As it's a readonly drive, we can simply live update it,
and eject/replace it with qemu monitor
---
PVE/API2/Qemu.pm | 44 ++++++++++++++++++++++++++++++++++++++++++++
PVE/CLI/qm.pm | 3 ++-
PVE/QemuServer.pm | 28 ++++++++++++++++++++++++++++
3 files changed, 74 insertions(+), 1 deletion(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index b6122fe..de2c378 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -1112,6 +1112,50 @@ __PACKAGE__->register_method({
return $res;
}});
+__PACKAGE__->register_method({
+ name => 'cloudinit_update',
+ path => '{vmid}/cloudinit',
+ method => 'PUT',
+ protected => 1,
+ proxyto => 'node',
+ description => "Regenerate and change cloudinit config drive.",
+ permissions => {
+ check => ['perm', '/vms/{vmid}', 'VM.Config.Cloudinit', any => 1],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ vmid => get_standard_option('pve-vmid'),
+ },
+ },
+ returns => { type => 'null' },
+ code => sub {
+ my ($param) = @_;
+
+ my $rpcenv = PVE::RPCEnvironment::get();
+
+ my $authuser = $rpcenv->get_user();
+
+ my $vmid = extract_param($param, 'vmid');
+
+ my $updatefn = sub {
+
+ my $conf = PVE::QemuConfig->load_config($vmid);
+
+ PVE::QemuConfig->check_lock($conf);
+
+ my $storecfg = PVE::Storage::config();
+
+ PVE::QemuServer::vmconfig_update_cloudinit_drive($storecfg, $conf, $vmid);
+
+ };
+
+ PVE::QemuConfig->lock_config($vmid, $updatefn);
+
+ return;
+ }});
+
# POST/PUT {vmid}/config implementation
#
# The original API used PUT (idempotent) an we assumed that all operations
diff --git a/PVE/CLI/qm.pm b/PVE/CLI/qm.pm
index e24b832..8d594c6 100755
--- a/PVE/CLI/qm.pm
+++ b/PVE/CLI/qm.pm
@@ -996,7 +996,8 @@ our $cmddef = {
my $data = shift;
print "$data\n";
}],
- pending => [ "PVE::API2::Qemu", 'cloudinit_pending', ['vmid'], { node => $nodename }, \&PVE::GuestHelpers::format_pending ]
+ pending => [ "PVE::API2::Qemu", 'cloudinit_pending', ['vmid'], { node => $nodename }, \&PVE::GuestHelpers::format_pending ],
+ update => [ "PVE::API2::Qemu", 'cloudinit_update', ['vmid'], { node => $nodename }],
},
};
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 900e227..59f90c9 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -4867,6 +4867,34 @@ sub vmconfig_update_disk {
vm_deviceplug($storecfg, $conf, $vmid, $opt, $drive, $arch, $machine_type);
}
+sub vmconfig_update_cloudinit_drive {
+ my ($storecfg, $conf, $vmid) = @_;
+
+ my $cloudinit_ds = undef;
+ my $cloudinit_drive = undef;
+
+ PVE::QemuConfig->foreach_volume($conf, sub {
+ my ($ds, $drive) = @_;
+ if (PVE::QemuServer::drive_is_cloudinit($drive)) {
+ $cloudinit_ds = $ds;
+ $cloudinit_drive = $drive;
+ }
+ });
+
+ return if !$cloudinit_drive;
+
+ PVE::QemuServer::Cloudinit::generate_cloudinitconfig($conf, $vmid);
+ my $running = PVE::QemuServer::check_running($vmid);
+
+ if ($running) {
+ my $path = PVE::Storage::path($storecfg, $cloudinit_drive->{file});
+ if ($path) {
+ mon_cmd($vmid, "eject", force => JSON::true, id => "$cloudinit_ds");
+ mon_cmd($vmid, "blockdev-change-medium", id => "$cloudinit_ds", filename => "$path");
+ }
+ }
+}
+
# called in locked context by incoming migration
sub vm_migrate_get_nbd_disks {
my ($storecfg, $conf, $replicated_volumes) = @_;
--
2.20.1
^ permalink raw reply [flat|nested] 7+ messages in thread
* [pve-devel] [PATCH v2 qemu-server 6/6] add cloudinit hotplug
2021-04-01 0:21 [pve-devel] [PATCH v2 qemu-server 0/6] cloudinit pending behaviour change Alexandre Derumier
` (4 preceding siblings ...)
2021-04-01 0:21 ` [pve-devel] [PATCH v2 qemu-server 5/6] api2: add cloudinit_update Alexandre Derumier
@ 2021-04-01 0:21 ` Alexandre Derumier
5 siblings, 0 replies; 7+ messages in thread
From: Alexandre Derumier @ 2021-04-01 0:21 UTC (permalink / raw)
To: pve-devel
This allow to regenerate config drive if pending values exist
when we change vm options.
---
PVE/QemuServer.pm | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/PVE/QemuServer.pm b/PVE/QemuServer.pm
index 59f90c9..eaad21a 100644
--- a/PVE/QemuServer.pm
+++ b/PVE/QemuServer.pm
@@ -287,7 +287,7 @@ my $confdesc = {
hotplug => {
optional => 1,
type => 'string', format => 'pve-hotplug-features',
- description => "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory' and 'usb'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
+ description => "Selectively enable hotplug features. This is a comma separated list of hotplug features: 'network', 'disk', 'cpu', 'memory', 'usb' and 'cloudinit'. Use '0' to disable hotplug completely. Value '1' is an alias for the default 'network,disk,usb'.",
default => 'network,disk,usb',
},
reboot => {
@@ -1298,7 +1298,7 @@ sub parse_hotplug_features {
$data = $confdesc->{hotplug}->{default} if $data eq '1';
foreach my $feature (PVE::Tools::split_list($data)) {
- if ($feature =~ m/^(network|disk|cpu|memory|usb)$/) {
+ if ($feature =~ m/^(network|disk|cpu|memory|usb|cloudinit)$/) {
$res->{$1} = 1;
} else {
die "invalid hotplug feature '$feature'\n";
@@ -4601,8 +4601,17 @@ sub vmconfig_hotplug_pending {
delete $conf->{pending}->{$opt};
}
}
-
PVE::QemuConfig->write_config($vmid, $conf);
+
+ if($hotplug_features->{cloudinit}) {
+ my $pending = PVE::QemuServer::Cloudinit::get_pending_config($conf, $vmid);
+ my $regenerate = undef;
+ foreach my $opt (keys %{$pending}) {
+ my $item = $pending->{$opt};
+ $regenerate = 1 if defined($item->{delete}) or defined($item->{pending});
+ }
+ PVE::QemuServer::vmconfig_update_cloudinit_drive($storecfg, $conf, $vmid) if $regenerate;
+ }
}
sub try_deallocate_drive {
--
2.20.1
^ permalink raw reply [flat|nested] 7+ messages in thread