--- /usr/share/perl5/PVE/QemuServer/Cloudinit.pm.orig 2021-11-22 17:07:13.000000000 +0100 +++ /usr/share/perl5/PVE/QemuServer/Cloudinit.pm 2022-01-18 11:18:40.902886004 +0100 @@ -163,13 +163,23 @@ $content .= "iface lo inet loopback\n\n"; my ($searchdomains, $nameservers) = get_dns_conf($conf); + + ## support windows + my $ostype = $conf->{"ostype"}; + my $default_dns = ''; + my $default_search = ''; + ## + my $dnsinserted = 0; # insert dns just once for the machine + if ($nameservers && @$nameservers) { $nameservers = join(' ', @$nameservers); $content .= " dns_nameservers $nameservers\n"; + $default_dns = $nameservers; # Support windows } if ($searchdomains && @$searchdomains) { $searchdomains = join(' ', @$searchdomains); $content .= " dns_search $searchdomains\n"; + $default_search = $searchdomains; # Support Windows } my @ifaces = grep { /^net(\d+)$/ } keys %$conf; @@ -189,6 +199,13 @@ $content .= " address $addr\n"; $content .= " netmask $mask\n"; $content .= " gateway $net->{gw}\n" if $net->{gw}; + ## Support Windows + if(PVE::QemuServer::windows_version($ostype) && not($dnsinserted)) { + $content .= " dns-nameservers $default_dns\n"; + $content .= " dns-search $default_search\n"; + $dnsinserted++; + } + ## } } if ($net->{ip6}) { @@ -207,23 +224,102 @@ return $content; } +# Get mac addresses of dhcp nics from conf file +sub get_mac_addresses { + my ($conf) = @_; + + my $dhcpstring = undef; + my @dhcpmacs = (); + my @ifaces = grep { /^net(\d+)$/ } keys %$conf; + + foreach my $iface (sort @ifaces) { + (my $id = $iface) =~ s/^net//; + my $net = PVE::QemuServer::parse_net($conf->{$iface}); + next if !$conf->{"ipconfig$id"}; + my $ipconfig = PVE::QemuServer::parse_ipconfig($conf->{"ipconfig$id"}); + + my $mac = lc $net->{macaddr}; + + if (($ipconfig->{ip}) and ($ipconfig->{ip} eq 'dhcp')){ + push @dhcpmacs, $mac; + } + } + + if (@dhcpmacs){ + $dhcpstring = ",\n \"dhcp\":["; + foreach my $mac (@dhcpmacs){ + if ($mac != $dhcpmacs[-1]){ + $dhcpstring .= "\"$mac\","; + } + else{ + $dhcpstring .= "\"$mac\"]"; + } + } + } + return ($dhcpstring); +} + sub configdrive2_gen_metadata { - my ($user, $network) = @_; + my ($conf, $vmid, $user, $network) = @_; + + # Get mac addresses of dhcp nics from conf file + my $dhcpmacs = undef; + $dhcpmacs = get_mac_addresses($conf); + # Get UUID my $uuid_str = Digest::SHA::sha1_hex($user.$network); - return configdrive2_metadata($uuid_str); + + # Get hostname + my ($hostname, $fqdn) = get_hostname_fqdn($conf, $vmid); + + # Get username, default to Administrator if none + my $username = undef; + if (defined($conf->{ciuser})){ + my $name = $conf->{ciuser}; + $username = ",\n \"admin_username\": \"$name\"" + } + + # Get user password + my $password = $conf->{cipassword}; + + # Get ssh keys and make a list out of it in json format + my $keystring = undef; + my $pubkeys = $conf->{sshkeys}; + $pubkeys = URI::Escape::uri_unescape($pubkeys); + my @pubkeysarray = split "\n", $pubkeys; + if (@pubkeysarray) { + my $arraylength = @pubkeysarray; + my $incrementer = 1; + $keystring =",\n \"public_keys\": {\n"; + for my $key (@pubkeysarray){ + $keystring .= " \"SSH${incrementer}\" : \"${key}\""; + if ($arraylength != $incrementer){ + $keystring .= ",\n"; + }else{ + $keystring .= "\n }"; + } + $incrementer++; + } + } + + return configdrive2_metadata($password, $uuid_str, $hostname, $username, $keystring, $network, $dhcpmacs); } sub configdrive2_metadata { - my ($uuid) = @_; + my ($password, $uuid, $hostname, $username, $pubkeys, $network, $dhcpmacs) = @_; return <<"EOF"; { - "uuid": "$uuid", - "network_config": { "content_path": "/content/0000" } + "meta":{ + "admin_pass": "$password"$username + }, + "uuid":"$uuid", + "hostname":"$hostname", + "network_config":{"content_path":"/content/0000"}$pubkeys$dhcpmacs } EOF } + sub generate_configdrive2 { my ($conf, $vmid, $drive, $volname, $storeid) = @_; @@ -232,7 +328,7 @@ $network_data = configdrive2_network($conf) if !defined($network_data); if (!defined($meta_data)) { - $meta_data = configdrive2_gen_metadata($user_data, $network_data); + $meta_data = configdrive2_gen_metadata($conf, $vmid, $user_data, $network_data); } # we always allocate a 4MiB disk for cloudinit and with the overhead of the ISO