[pve-devel] [PATCH 11/13] add clone_disks sub
Alexandre Derumier
aderumier at odiso.com
Tue Jan 29 17:13:51 CET 2013
Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
PVE/API2/Qemu.pm | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 100 insertions(+)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index 924af26..ed6da19 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -133,6 +133,106 @@ my $create_disks = sub {
return $vollist;
};
+my $clone_disks = sub {
+ my ($rpcenv, $authuser, $conf, $storecfg, $vmid, $pool, $settings, $snap, $mode, $clonefrom, $running, $onlysettings) = @_;
+
+ my $vollist = [];
+ my $voliddst = undef;
+ my $currentdrive = undef;
+ my $res = {};
+
+ eval {
+ local $SIG{INT} = $SIG{TERM} = $SIG{QUIT} = $SIG{HUP} = sub {die "interrupted by signal\n";};
+
+ PVE::QemuServer::foreach_drive($conf, sub {
+ my ($ds, $disk) = @_;
+
+ $currentdrive = $ds;
+
+ return if ($onlysettings && !$settings->{$ds});
+
+ my $volid = $disk->{file};
+ if (PVE::QemuServer::drive_is_cdrom($disk)) {
+ $res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
+ } else{
+
+ if($mode eq 'clone'){
+ print "clone volume $volid\n";
+ #if we clone from a template and we need to use the snapshot
+ if(PVE::Storage::volume_has_feature($storecfg, 'clone', $volid, 1, $running) && PVE::QemuServer::is_template($conf)){
+ $snap = "base";
+ }
+ $voliddst = PVE::Storage::volume_clone($storecfg, $volid, $snap, $vmid);
+ push @$vollist, $voliddst;
+
+ }elsif($mode eq 'copy'){
+
+ my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid, 1);
+ die "no storage ID specified (and no default storage)\n" if !$storeid;
+
+ my $fmt = undef;
+ if ($volname =~ m/\.(raw|qcow2|vmdk)$/){
+ $fmt = $1;
+ }
+
+ #target storage is different ? (ex: -virtio0:storeid:fmt)
+ if($settings->{$ds} && $settings->{$ds} =~ m/^(\S+):(raw|qcow2|vmdk)?$/){
+ ($storeid, $fmt) = ($1, $2);
+ }
+
+ $rpcenv->check($authuser, "/storage/$storeid", ['Datastore.AllocateSpace']);
+ print "activate volume source $volid\n";
+ PVE::Storage::activate_volumes($storecfg, [ $volid ]);
+
+ my ($size) = PVE::Storage::volume_size_info($storecfg, $volid, 1);
+ print "create target volume\n";
+ $voliddst = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $fmt, undef, ($size/1024));
+
+ push @$vollist, $voliddst;
+
+ print "activate volume $voliddst\n";
+ PVE::Storage::activate_volumes($storecfg, [ $voliddst ]);
+
+ print "copy $volid to $voliddst\n";
+ if(!$running || $snap){
+ PVE::QemuServer::qemu_img_convert($volid, $voliddst, $snap);
+ }else{
+ PVE::QemuServer::qemu_drive_mirror($clonefrom, $ds, $voliddst, $vmid);
+ }
+ }
+
+ $disk->{file} = $voliddst;
+ $disk->{size} = PVE::Storage::volume_size_info($storecfg, $voliddst, 1);
+
+ 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 clone disks failed");
+
+ eval {
+ PVE::QemuServer::vm_mon_cmd($vmid, "block-job-cancel", device => "drive-$currentdrive") if ($mode eq 'copy' && $running);
+ };
+
+ sleep 1; #some storage like rbd need to wait before release volume
+ 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) = @_;
--
1.7.10.4
More information about the pve-devel
mailing list