]> git.proxmox.com Git - qemu-server.git/blobdiff - PVE/QemuServer/Cloudinit.pm
cloudinit: use detected format in volname parsing
[qemu-server.git] / PVE / QemuServer / Cloudinit.pm
index 4dc4a14bf646a0c8b21fb36a96a7fffc16490cd7..f46f7fdec65271fcc141dcb08c41545075223dc9 100644 (file)
@@ -30,11 +30,19 @@ sub commit_cloudinit_disk {
     my $storecfg = PVE::Storage::config();
     my $iso_path = PVE::Storage::path($storecfg, $drive->{file});
     my $scfg = PVE::Storage::storage_config($storecfg, $storeid);
-    my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
-    $plugin->activate_volume($storeid, $scfg, $volname);
     my $format = PVE::QemuServer::qemu_img_format($scfg, $volname);
 
-    my $size = PVE::Storage::file_size_info($iso_path);
+    my $size = eval { PVE::Storage::file_size_info($iso_path) };
+    if ($size <= 0) {
+       $volname =~ m/(vm-$vmid-cloudinit(.\Q$format\E)?)/;
+       my $name = $1;
+       $size = 4 * 1024;
+       PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $format, $name, $size);
+       $size *= 1024; # vdisk alloc takes KB, qemu-img dd's osize takes byte
+    }
+
+    my $plugin = PVE::Storage::Plugin->lookup($scfg->{type});
+    $plugin->activate_volume($storeid, $scfg, $volname);
 
     eval {
        run_command([['genisoimage', '-R', '-V', $label, $path],
@@ -174,9 +182,9 @@ sub configdrive2_network {
            } else {
                my ($addr, $mask) = split_ip4($net->{ip});
                $content .= "iface $id inet static\n";
-               $content .= "        address '$addr'\n";
-               $content .= "        netmask '$mask'\n";
-               $content .= "        gateway '$net->{gw}'\n" if $net->{gw};
+               $content .= "        address $addr\n";
+               $content .= "        netmask $mask\n";
+               $content .= "        gateway $net->{gw}\n" if $net->{gw};
            }
        }
        if ($net->{ip6}) {
@@ -185,9 +193,9 @@ sub configdrive2_network {
            } else {
                my ($addr, $mask) = split('/', $net->{ip6});
                $content .= "iface $id inet6 static\n";
-               $content .= "        address '$addr'\n";
-               $content .= "        netmask '$mask'\n";
-               $content .= "        gateway '$net->{gw6}'\n" if $net->{gw6};
+               $content .= "        address $addr\n";
+               $content .= "        netmask $mask\n";
+               $content .= "        gateway $net->{gw6}\n" if $net->{gw6};
            }
        }
     }
@@ -208,14 +216,16 @@ EOF
 sub generate_configdrive2 {
     my ($conf, $vmid, $drive, $volname, $storeid) = @_;
 
-    my $user_data = cloudinit_userdata($conf, $vmid);
-    my $network_data = configdrive2_network($conf);
-
-    my $digest_data = $user_data . $network_data;
-    my $uuid_str = Digest::SHA::sha1_hex($digest_data);
+    my ($user_data, $network_data, $meta_data) = get_custom_cloudinit_files($conf);
+    $user_data = cloudinit_userdata($conf, $vmid) if !defined($user_data);
+    $network_data = configdrive2_network($conf) if !defined($network_data);
 
-    my $meta_data = configdrive2_metadata($uuid_str);
+    if (!defined($meta_data)) {
+       my $digest_data = $user_data . $network_data;
+       my $uuid_str = Digest::SHA::sha1_hex($digest_data);
 
+       $meta_data = configdrive2_metadata($uuid_str);
+    }
     my $files = {
        '/openstack/latest/user_data' => $user_data,
        '/openstack/content/0000' => $network_data,
@@ -378,13 +388,16 @@ sub nocloud_metadata {
 sub generate_nocloud {
     my ($conf, $vmid, $drive, $volname, $storeid) = @_;
 
-    my $user_data = cloudinit_userdata($conf, $vmid);
-    my $network_data = nocloud_network($conf);
+    my ($user_data, $network_data, $meta_data) = get_custom_cloudinit_files($conf);
+    $user_data = cloudinit_userdata($conf, $vmid) if !defined($user_data);
+    $network_data = nocloud_network($conf) if !defined($network_data);
 
-    my $digest_data = $user_data . $network_data;
-    my $uuid_str = Digest::SHA::sha1_hex($digest_data);
+    if (!defined($meta_data)) {
+       my $digest_data = $user_data . $network_data;
+       my $uuid_str = Digest::SHA::sha1_hex($digest_data);
 
-    my $meta_data = nocloud_metadata($uuid_str);
+       $meta_data = nocloud_metadata($uuid_str);
+    }
 
     my $files = {
        '/user-data' => $user_data,
@@ -394,6 +407,44 @@ sub generate_nocloud {
     commit_cloudinit_disk($conf, $vmid, $drive, $volname, $storeid, $files, 'cidata');
 }
 
+sub get_custom_cloudinit_files {
+    my ($conf) = @_;
+
+    my $cicustom = $conf->{cicustom};
+    my $files = $cicustom ? PVE::JSONSchema::parse_property_string('pve-qm-cicustom', $cicustom) : {};
+
+    my $network_volid = $files->{network};
+    my $user_volid = $files->{user};
+    my $meta_volid = $files->{meta};
+
+    my $storage_conf = PVE::Storage::config();
+
+    my $network_data;
+    if ($network_volid) {
+       $network_data = read_cloudinit_snippets_file($storage_conf, $network_volid);
+    }
+
+    my $user_data;
+    if ($user_volid) {
+       $user_data = read_cloudinit_snippets_file($storage_conf, $user_volid);
+    }
+
+    my $meta_data;
+    if ($meta_volid) {
+       $meta_data = read_cloudinit_snippets_file($storage_conf, $meta_volid);
+    }
+
+    return ($user_data, $network_data, $meta_data);
+}
+
+sub read_cloudinit_snippets_file {
+    my ($storage_conf, $volid) = @_;
+
+    my ($full_path, undef, $type) = PVE::Storage::path($storage_conf, $volid);
+    die "$volid is not in the snippets directory\n" if $type ne 'snippets';
+    return PVE::Tools::file_get_contents($full_path, 1 * 1024 * 1024);
+}
+
 my $cloudinit_methods = {
     configdrive2 => \&generate_configdrive2,
     nocloud => \&generate_nocloud,