use PVE::QemuServer;
sub commit_cloudinit_disk {
- my ($conf, $drive, $volname, $storeid, $file_path, $label) = @_;
+ my ($vmid, $conf, $drive, $volname, $storeid, $files, $label) = @_;
+
+ my $path = "/run/pve/cloudinit/$vmid/";
+ mkpath $path;
+ foreach my $filepath (keys %$files) {
+ if ($filepath !~ m@^(.*)\/[^/]+$@) {
+ die "internal error: bad file name in cloud-init image: $filepath\n";
+ }
+ my $dirname = $1;
+ mkpath "$path/$dirname";
+
+ my $contents = $files->{$filepath};
+ file_set_contents("$path/$filepath", $contents);
+ }
my $storecfg = PVE::Storage::config();
my $iso_path = PVE::Storage::path($storecfg, $drive->{file});
my $size = PVE::Storage::file_size_info($iso_path);
- run_command([['genisoimage', '-R', '-V', $label, $file_path],
- ['qemu-img', 'dd', '-f', 'raw', '-O', $format,
- 'isize=0', "osize=$size", "of=$iso_path"]]);
+ eval {
+ run_command([['genisoimage', '-R', '-V', $label, $path],
+ ['qemu-img', 'dd', '-f', 'raw', '-O', $format,
+ 'isize=0', "osize=$size", "of=$iso_path"]]);
+ };
+ my $err = $@;
+ rmtree($path);
+ die $err if $err;
}
sub get_cloudinit_format {
return 'nocloud';
}
-sub get_fqdn {
+sub get_hostname_fqdn {
my ($conf) = @_;
- my $fqdn = $conf->{hostname};
- if (!defined($fqdn)) {
- $fqdn = $conf->{name};
- if (my $search = $conf->{searchdomain}) {
- $fqdn .= ".$search";
- }
+ my $hostname = $conf->{name};
+ my $fqdn;
+ if ($hostname =~ /\./) {
+ $fqdn = $hostname;
+ $hostname =~ s/\..*$//;
+ } elsif (my $search = $conf->{searchdomain}) {
+ $fqdn = "$hostname.$search";
}
- return $fqdn;
+ return ($hostname, $fqdn);
}
sub cloudinit_userdata {
my ($conf) = @_;
- my $fqdn = get_fqdn($conf);
+ my ($hostname, $fqdn) = get_hostname_fqdn($conf);
my $content = "#cloud-config\n";
$content .= "manage_resolv_conf: true\n";
+ $content .= "hostname: $hostname\n";
+ $content .= "fqdn: $fqdn\n" if defined($fqdn);
+
my $username = $conf->{ciuser};
my $password = $conf->{cipassword};
my $meta_data = configdrive2_metadata($uuid_str);
- mkdir "/tmp/cloudinit";
- my $path = "/tmp/cloudinit/$vmid";
- mkdir $path;
- mkdir "$path/drive";
- mkdir "$path/drive/openstack";
- mkdir "$path/drive/openstack/latest";
- mkdir "$path/drive/openstack/content";
- file_set_contents("$path/drive/openstack/latest/user_data", $user_data);
- file_set_contents("$path/drive/openstack/content/0000", $network_data);
- file_set_contents("$path/drive/openstack/latest/meta_data.json", $meta_data);
-
- commit_cloudinit_disk($conf, $drive, $volname, $storeid, "$path/drive", 'config-2');
-
- rmtree("$path/drive");
+ my $files = {
+ '/openstack/latest/user_data' => $user_data,
+ '/openstack/content/0000' => $network_data,
+ '/openstack/latest/meta_data.json' => $meta_data
+ };
+ commit_cloudinit_disk($vmid, $conf, $drive, $volname, $storeid, $files, 'config-2');
}
sub nocloud_network_v2 {
}
sub nocloud_metadata {
- my ($uuid, $hostname) = @_;
- return <<"EOF";
-instance-id: $uuid
-local-hostname: $hostname
-EOF
+ my ($uuid) = @_;
+ return "instance-id: $uuid\n";
}
sub generate_nocloud {
my ($conf, $vmid, $drive, $volname, $storeid) = @_;
- my $hostname = $conf->{hostname} // '';
my $user_data = cloudinit_userdata($conf);
my $network_data = nocloud_network($conf);
- my $digest_data = $user_data . $network_data . "local-hostname: $hostname\n";
+ my $digest_data = $user_data . $network_data;
my $uuid_str = Digest::SHA::sha1_hex($digest_data);
- my $meta_data = nocloud_metadata($uuid_str, $hostname);
-
- mkdir "/tmp/cloudinit";
- my $path = "/tmp/cloudinit/$vmid";
- mkdir $path;
- rmtree("$path/drive");
- mkdir "$path/drive";
- file_set_contents("$path/drive/user-data", $user_data);
- file_set_contents("$path/drive/network-config", $network_data);
- file_set_contents("$path/drive/meta-data", $meta_data);
-
- commit_cloudinit_disk($conf, $drive, $volname, $storeid, "$path/drive", 'cidata');
+ my $meta_data = nocloud_metadata($uuid_str);
+ my $files = {
+ '/user-data' => $user_data,
+ '/network-config' => $network_data,
+ '/meta-data' => $meta_data
+ };
+ commit_cloudinit_disk($vmid, $conf, $drive, $volname, $storeid, $files, 'cidata');
}
my $cloudinit_methods = {