[pve-devel] [PATCH qemu-server 4/6] api2: add cloudinit config api

Mira Limbeck m.limbeck at proxmox.com
Wed Mar 31 16:13:20 CEST 2021


Why do you add the macaddress here? I couldn't find anything in this nor 
in the previous patch series explaining why this is done.

On 3/28/21 5:12 PM, Alexandre Derumier wrote:
> ---
>   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 f4bf925..20cf583 100644
> --- a/PVE/QemuServer/Cloudinit.pm
> +++ b/PVE/QemuServer/Cloudinit.pm
> @@ -629,4 +629,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;





More information about the pve-devel mailing list