[pve-devel] [PATCH 7/7] add clone_disks
Alexandre Derumier
aderumier at odiso.com
Mon Dec 3 14:30:30 CET 2012
qm create --clonefrom vmid --snapname snap
Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
PVE/API2/Qemu.pm | 89 ++++++++++++++++++++++++++++++++++++++++++++++++++++--
1 file changed, 86 insertions(+), 3 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index d2dba3c..548987f 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -78,6 +78,7 @@ my $create_disks = sub {
die "no storage ID specified (and no default storage)\n" if !$storeid;
my $defformat = PVE::Storage::storage_default_format($storecfg, $storeid);
my $fmt = $disk->{format} || $defformat;
+
my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid,
$fmt, undef, $size*1024*1024);
$disk->{file} = $volid;
@@ -132,6 +133,48 @@ my $create_disks = sub {
return $vollist;
};
+my $clone_disks = sub {
+ my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $settings, $snap) = @_;
+
+ my $vollist = [];
+
+ my $res = {};
+ PVE::QemuServer::foreach_drive($settings, sub {
+ my ($ds, $disk) = @_;
+
+ my $volid = $disk->{file};
+ if (!$volid || $volid eq 'none' || $volid eq 'cdrom') {
+ $res->{$ds} = $settings->{$ds};
+ } else{
+ my $voliddst = PVE::Storage::volume_clone($storecfg, $volid, $snap, $vmid);
+
+ $disk->{file} = $voliddst;
+ $disk->{size} = PVE::Storage::volume_size_info($storecfg, $voliddst, 1);
+
+ push @$vollist, $voliddst;
+ delete $disk->{format}; # no longer needed
+ $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
+ }
+ });
+
+ # free allocated images on error
+ if (my $err = $@) {
+ syslog('err', "VM $vmid creating disks failed");
+ foreach my $volid (@$vollist) {
+ eval { PVE::Storage::vdisk_free($storecfg, $volid); };
+ warn $@ if $@;
+ }
+ die $err;
+ }
+
+ # modify vm config if everything went well
+ foreach my $ds (keys %$res) {
+ $conf->{$ds} = $res->{$ds};
+ }
+
+ return $vollist;
+};
+
my $check_vm_modify_config_perm = sub {
my ($rpcenv, $authuser, $vmid, $pool, $key_list) = @_;
@@ -256,6 +299,15 @@ __PACKAGE__->register_method({
type => 'string', format => 'pve-poolid',
description => "Add the VM to the specified pool.",
},
+ clonefrom => get_standard_option('pve-vmid', {
+ description => "Template Vmid.",
+ optional => 1,
+ }),
+ snapname => get_standard_option('pve-snapshot-name', {
+ description => "Template Snapshot Name.",
+ optional => 1,
+ }),
+
}),
},
returns => {
@@ -282,6 +334,10 @@ __PACKAGE__->register_method({
my $pool = extract_param($param, 'pool');
+ my $clonefrom = extract_param($param, 'clonefrom');
+
+ my $snapname = extract_param($param, 'snapname');
+
my $filename = PVE::QemuServer::config_file($vmid);
my $storecfg = PVE::Storage::config();
@@ -375,12 +431,39 @@ __PACKAGE__->register_method({
my $vollist = [];
- my $conf = $param;
+ if($clonefrom){
- eval {
+ my $parentconf = PVE::QemuServer::load_config($clonefrom);
+
+ if($snapname){
+ die "You can't clone. vmid $clonefrom snap $snapname is not a template" if !defined($parentconf->{snapshots}->{$snapname}->{template});
+ $param = $parentconf->{snapshots}->{$snapname};
+ delete $param->{snaptime};
+
+ }else{
+ die "You can't clone. vmid $clonefrom is not a template" if !defined($parentconf->{template});
+ $param = $parentconf;
+ delete $param->{parent};
+ delete $param->{snapshots};
+ }
- $vollist = &$create_disks($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $param, $storage);
+ foreach my $opt (keys %$param) {
+ if ($opt =~ m/^net(\d+)$/) {
+ # add macaddr
+ my $net = PVE::QemuServer::parse_net($param->{$opt});
+ $net->{macaddr} = PVE::Tools::random_ether_addr();
+ $param->{$opt} = PVE::QemuServer::print_net($net);
+ }
+ }
+ }
+ my $conf = $param;
+ eval {
+ if($clonefrom){
+ $vollist = &$clone_disks($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $param, $snapname);
+ }else{
+ $vollist = &$create_disks($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $param, $storage);
+ }
# try to be smart about bootdisk
my @disks = PVE::QemuServer::disknames();
my $firstdisk;
--
1.7.10.4
More information about the pve-devel
mailing list