[pve-devel] [PATCH] vm_create : add support for mountpoints

Alexandre Derumier aderumier at odiso.com
Mon Aug 24 15:01:16 CEST 2015


rename alloc_roofs with create_disks,
to handle multiple disks.

$size param is removed, and must be provide like for qemuserver:

example:
pct create vmid template -rootfs local:5 -mp0 local:10

Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
 src/PVE/API2/LXC.pm   | 148 +++++++++++++++++++++++++++-----------------------
 src/PVE/LXC.pm        |   4 ++
 src/PVE/LXC/Create.pm |   9 ++-
 3 files changed, 91 insertions(+), 70 deletions(-)

diff --git a/src/PVE/API2/LXC.pm b/src/PVE/API2/LXC.pm
index 8431125..f565eee 100644
--- a/src/PVE/API2/LXC.pm
+++ b/src/PVE/API2/LXC.pm
@@ -44,52 +44,68 @@ __PACKAGE__->register_method ({
     path => '{vmid}/firewall',
 });
  
-my $alloc_rootfs = sub {
-    my ($storage_conf, $storage, $disk_size_gb, $vmid) = @_;
+my $create_disks = sub {
+    my ($storecfg, $vmid, $settings, $conf, $default_storage) = @_;
 
-    my $volid;
+    my $vollist = [];
 
-    my $size = 4*1024*1024; # defaults to 4G
+    PVE::LXC::foreach_mountpoint($settings, sub {
+        my ($ms, $mountpoint) = @_;
 
-    $size = int($disk_size_gb*1024) * 1024 if defined($disk_size_gb);
+        my $volid = $mountpoint->{volume};
+        my $mp = $mountpoint->{mp};
 
-    eval {
-	my $scfg = PVE::Storage::storage_config($storage_conf, $storage);
-	# fixme: use better naming ct-$vmid-disk-X.raw?
+	my ($storage, $volname) = PVE::Storage::parse_volume_id($volid, 1);
 
-	if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs') {
-	    if ($size > 0) {
-		$volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'raw',
-						   undef, $size);
-	    } else {
-		$volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'subvol',
-						   undef, 0);
-	    }
-	} elsif ($scfg->{type} eq 'zfspool') {
+        return if !$storage;
 
-	    $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'subvol',
-					       undef, $size);
-	} elsif ($scfg->{type} eq 'drbd') {
+	if ($volid =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
+            my ($storeid, $size) = ($2 || $default_storage, $3);
 
-	    $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'raw', undef, $size);
+	    $size = int($size*1024) * 1024;
 
-	} elsif ($scfg->{type} eq 'rbd') {
+	    eval {
+		my $scfg = PVE::Storage::storage_config($storecfg, $storage);
+		# fixme: use better naming ct-$vmid-disk-X.raw?
 
-	    die "krbd option must be enabled on storage type '$scfg->{type}'\n" if !$scfg->{krbd};
-	    $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'raw', undef, $size);
+		if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs') {
+		    if ($size > 0) {
+			$volid = PVE::Storage::vdisk_alloc($storecfg, $storage, $vmid, 'raw',
+							   undef, $size);
+		    } else {
+			$volid = PVE::Storage::vdisk_alloc($storecfg, $storage, $vmid, 'subvol',
+							   undef, 0);
+		    }
+		} elsif ($scfg->{type} eq 'zfspool') {
 
-	} else {
-	    die "unable to create containers on storage type '$scfg->{type}'\n";
+		    $volid = PVE::Storage::vdisk_alloc($storecfg, $storage, $vmid, 'subvol',
+					       undef, $size);
+		} elsif ($scfg->{type} eq 'drbd') {
+
+		    $volid = PVE::Storage::vdisk_alloc($storecfg, $storage, $vmid, 'raw', undef, $size);
+
+		} elsif ($scfg->{type} eq 'rbd') {
+
+		    die "krbd option must be enabled on storage type '$scfg->{type}'\n" if !$scfg->{krbd};
+		    $volid = PVE::Storage::vdisk_alloc($storecfg, $storage, $vmid, 'raw', undef, $size);
+		} else {
+		    die "unable to create containers on storage type '$scfg->{type}'\n";
+		}
+	    };
+            push @$vollist, $volid;
+	    $conf->{$ms} = PVE::LXC::print_ct_mountpoint({volume => $volid, size => $size, mp => $mp });
 	}
-    };
+    });
+    # free allocated images on error
     if (my $err = $@) {
-	# cleanup
-	eval { PVE::Storage::vdisk_free($storage_conf, $volid) if $volid; };
-	warn $@ if $@;
-	die $err;
+        syslog('err', "VM $vmid creating disks failed");
+        foreach my $volid (@$vollist) {
+            eval { PVE::Storage::vdisk_free($storecfg, $volid); };
+            warn $@ if $@;
+        }
+        die $err;
     }
-
-    return $volid;
+    return $vollist;
 };
 
 __PACKAGE__->register_method({
@@ -153,7 +169,7 @@ __PACKAGE__->register_method({
     proxyto => 'node',
     parameters => {
     	additionalProperties => 0,
-	properties => PVE::LXC::json_config_properties_no_rootfs({
+	properties => PVE::LXC::json_config_properties({
 	    node => get_standard_option('pve-node'),
 	    vmid => get_standard_option('pve-vmid'),
 	    ostemplate => {
@@ -168,17 +184,10 @@ __PACKAGE__->register_method({
 		minLength => 5,
 	    },
 	    storage => get_standard_option('pve-storage-id', {
-		description => "Target storage.",
+		description => "Default Storage.",
 		default => 'local',
 		optional => 1,
 	    }),
-	    size => {
-		optional => 1,
-		type => 'number',
-		description => "Amount of disk space for the VM in GB. A zero indicates no limits.",
-		minimum => 0,
-		default => 4,
-	    },
 	    force => {
 		optional => 1,
 		type => 'boolean',
@@ -229,8 +238,6 @@ __PACKAGE__->register_method({
 
 	my $password = extract_param($param, 'password');
 
-	my $disksize = extract_param($param, 'size');
-
 	my $storage = extract_param($param, 'storage') // 'local';
 	
 	my $storage_cfg = cfs_read_file("storage.cfg");
@@ -268,13 +275,13 @@ __PACKAGE__->register_method({
 
 	my $archive;
 
+	$param->{rootfs} = $storage if !$param->{rootfs};
+
 	if ($ostemplate eq '-') {
 	    die "pipe requires cli environment\n" 
 		if $rpcenv->{type} ne 'cli'; 
 	    die "pipe can only be used with restore tasks\n" 
 		if !$restore;
-	    die "pipe requires --size parameter\n" 
-		if !defined($disksize);
 	    $archive = '-';
 	} else {
 	    $rpcenv->check_volume_access($authuser, $storage_cfg, $vmid, $ostemplate);
@@ -298,36 +305,43 @@ __PACKAGE__->register_method({
 	    &$check_vmid_usage(); # final check after locking
 	    	    
 	    PVE::Cluster::check_cfs_quorum();
-
-	    my $volid;
+	    my $vollist = [];
 
 	    eval {
-		if (!defined($disksize)) {
-		    if ($restore) {
-			(undef, $disksize) = PVE::LXC::Create::recover_config($archive);
-			die "unable to detect disk size - please specify with --size\n"
-			    if !$disksize;
-		    } else {
-			$disksize = 4;
-		    }
-		}
-		$volid = &$alloc_rootfs($storage_cfg, $storage, $disksize, $vmid);
-
-		PVE::LXC::Create::create_rootfs($storage_cfg, $storage, $volid, $vmid, $conf,
-						$archive, $password, $restore);
-
-		$conf->{rootfs} = PVE::LXC::print_ct_mountpoint({volume => $volid, size => $disksize });
-
+                my $rootmp = PVE::LXC::parse_ct_mountpoint($param->{rootfs});
+		my $root_volid = $rootmp->{volume};
+		my $disksize = undef;
+
+		if ($root_volid =~ m/^(([^:\s]+):)?(\d+)?/) {
+
+		    my ($storeid, $disksize) = ($2 || $storage, $3);
+
+                    if (!defined($disksize)) {
+                        if ($restore) {
+                            (undef, $disksize) = PVE::LXC::Create::recover_config($archive);
+                            die "unable to detect disk size - please specify rootfs size\n"
+                                if !$disksize;
+                        } else {
+                            $disksize = 4;
+                        }
+                        $param->{rootfs} = "$storeid:$disksize";
+                    }
+                }
+		$vollist = &$create_disks($storage_cfg, $vmid, $param, $conf, $storage);
+
+		PVE::LXC::Create::create_rootfs($storage_cfg, $vmid, $conf, $archive, $password, $restore);
 		# set some defaults
 		$conf->{hostname} ||= "CT$vmid";
 		$conf->{memory} ||= 512;
 		$conf->{swap} //= 512;
-
 		PVE::LXC::create_config($vmid, $conf);
 	    };
 	    if (my $err = $@) {
-		eval { PVE::Storage::vdisk_free($storage_cfg, $volid) if $volid; };
-		warn $@ if $@;
+		foreach my $volid (@$vollist) {
+		    eval { PVE::Storage::vdisk_free($storage_cfg, $volid); };
+		    warn $@ if $@;
+		}
+
 		PVE::LXC::destroy_config($vmid);
 		die $err;
 	    }
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 5196fff..dd75c02 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -1095,6 +1095,8 @@ sub update_pct_config {
 		next if !$running;
 		my $netid = $1;
 		PVE::Network::veth_delete("veth${vmid}i$netid");
+	    } elsif ($opt eq 'rootfs' || $opt =~ m/^mp(\d+)$/) {
+		#implement me
 	    } else {
 		die "implement me"
 	    }
@@ -1161,6 +1163,8 @@ sub update_pct_config {
 	    } else {
 		update_net($vmid, $conf, $opt, $net, $netid, $rootdir);
 	    }
+        } elsif ($opt eq 'rootfs' || $opt =~ m/^mp(\d+)$/) {
+                #implement me
 	} else {
 	    die "implement me: $opt";
 	}
diff --git a/src/PVE/LXC/Create.pm b/src/PVE/LXC/Create.pm
index 9cb52e3..fcebb7d 100644
--- a/src/PVE/LXC/Create.pm
+++ b/src/PVE/LXC/Create.pm
@@ -175,7 +175,7 @@ sub restore_and_configure {
 }
 
 sub create_rootfs {
-    my ($storage_cfg, $storage, $volid, $vmid, $conf, $archive, $password, $restore) = @_;
+    my ($storage_cfg, $vmid, $conf, $archive, $password, $restore) = @_;
 
     my $config_fn = PVE::LXC::config_file($vmid);
     if (-f $config_fn) {
@@ -199,14 +199,17 @@ sub create_rootfs {
 	PVE::LXC::create_config($vmid, $conf);
     }
 
+    my $mountpoint = PVE::LXC::parse_ct_mountpoint($conf->{rootfs});
+    $mountpoint->{mp} = '/' if !$mountpoint->{mp};
+
+    my $volid = $mountpoint->{volume};
+
     my $image_path = PVE::Storage::path($storage_cfg, $volid);
     my $mountpoint_path = "/var/lib/lxc/$vmid/rootfs";
-    my $mountpoint = { volume => $volid, mp => "/" };
 
     eval {
         PVE::Storage::activate_volumes($storage_cfg, [$volid]);
         my $loopdevs = PVE::LXC::attach_loops($storage_cfg, [$volid]);
-
 	if (!-d $image_path) {
 	    my $cmd = ['mkfs.ext4', $image_path];
 	    PVE::Tools::run_command($cmd);
-- 
2.1.4




More information about the pve-devel mailing list