use strict;
use warnings;
-use POSIX;
-use IO::Handle;
-use IO::Select;
-use IO::File;
-use IO::Dir;
-use IO::Socket::UNIX;
+use Cwd 'abs_path';
+use Digest::SHA;
+use Fcntl ':flock';
+use Fcntl;
use File::Basename;
+use File::Copy qw(copy);
use File::Path;
use File::stat;
use Getopt::Long;
-use Digest::SHA;
-use Fcntl ':flock';
-use Cwd 'abs_path';
+use IO::Dir;
+use IO::File;
+use IO::Handle;
+use IO::Select;
+use IO::Socket::UNIX;
use IPC::Open3;
use JSON;
-use Fcntl;
-use PVE::SafeSyslog;
-use Storable qw(dclone);
use MIME::Base64;
-use PVE::Exception qw(raise raise_param_exc);
-use PVE::Storage;
-use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach $IPV6RE);
-use PVE::JSONSchema qw(get_standard_option);
+use POSIX;
+use Storable qw(dclone);
+use Time::HiRes qw(gettimeofday);
+use URI::Escape;
+
use PVE::Cluster qw(cfs_register_file cfs_read_file cfs_write_file cfs_lock_file);
+use PVE::Exception qw(raise raise_param_exc);
+use PVE::GuestHelpers;
use PVE::INotify;
+use PVE::JSONSchema qw(get_standard_option);
use PVE::ProcFSTools;
-use PVE::QemuConfig;
-use PVE::QMPClient;
use PVE::RPCEnvironment;
-use PVE::GuestHelpers;
-use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port);
-use PVE::QemuServer::Memory;
-use PVE::QemuServer::USB qw(parse_usb_device);
-use PVE::QemuServer::Cloudinit;
+use PVE::SafeSyslog;
+use PVE::Storage;
use PVE::SysFSTools;
use PVE::Systemd;
-use Time::HiRes qw(gettimeofday);
-use File::Copy qw(copy);
-use URI::Escape;
+use PVE::Tools qw(run_command lock_file lock_file_full file_read_firstline dir_glob_foreach $IPV6RE);
+
+use PVE::QMPClient;
+use PVE::QemuConfig;
+use PVE::QemuServer::Cloudinit;
+use PVE::QemuServer::Memory;
+use PVE::QemuServer::PCI qw(print_pci_addr print_pcie_addr print_pcie_root_port);
+use PVE::QemuServer::USB qw(parse_usb_device);
my $EDK2_FW_BASE = '/usr/share/pve-edk2-firmware/';
my $OVMF = {
sub destroy_vm {
my ($storecfg, $vmid, $keep_empty_config, $skiplock) = @_;
- my $conffile = PVE::QemuConfig->config_file($vmid);
-
my $conf = PVE::QemuConfig->load_config($vmid);
PVE::QemuConfig->check_lock($conf) if !$skiplock;
});
if ($keep_empty_config) {
- PVE::Tools::file_set_contents($conffile, "memory: 128\n");
+ PVE::QemuConfig->write_config($vmid, "memory: 128\n");
} else {
- unlink $conffile;
+ PVE::QemuConfig->destroy_config($vmid);
}
# also remove unused disk
if (my $vmstate = $conf->{vmstate}) {
my $statepath = PVE::Storage::path($storecfg, $vmstate);
- PVE::Storage::activate_volumes($storecfg, [$vmstate]);
+ push @$vollist, $statepath;
push @$cmd, '-loadstate', $statepath;
}
push @$cmd, '-incoming', $migrate_uri;
push @$cmd, '-S';
- } else {
+ } elsif (-e $statefile) {
push @$cmd, '-loadstate', $statefile;
+ } else {
+ my $statepath = PVE::Storage::path($storecfg, $statefile);
+ push @$vollist, $statepath;
+ push @$cmd, '-loadstate', $statepath;
}
} elsif ($paused) {
push @$cmd, '-S';
my ($src_storeid, $src_volname) = PVE::Storage::parse_volume_id($src_volid, 1);
my ($dst_storeid, $dst_volname) = PVE::Storage::parse_volume_id($dst_volid, 1);
- if ($src_storeid && $dst_storeid) {
+ die "destination '$dst_volid' is not a valid volid form qemu-img convert\n" if !$dst_storeid;
- PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
+ my $cachemode;
+ my $src_path;
+ my $src_is_iscsi = 0;
+ my $src_format = 'raw';
+ if ($src_storeid) {
+ PVE::Storage::activate_volumes($storecfg, [$src_volid], $snapname);
my $src_scfg = PVE::Storage::storage_config($storecfg, $src_storeid);
- my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
+ $src_format = qemu_img_format($src_scfg, $src_volname);
+ $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
+ $src_is_iscsi = ($src_path =~ m|^iscsi://|);
+ $cachemode = 'none' if $src_scfg->{type} eq 'zfspool';
+ } elsif (-f $src_volid) {
+ $src_path = $src_volid;
+ if ($src_path =~ m/\.($QEMU_FORMAT_RE)$/) {
+ $src_format = $1;
+ }
+ }
- my $src_format = qemu_img_format($src_scfg, $src_volname);
- my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
+ die "source '$src_volid' is not a valid volid nor path for qemu-img convert\n" if !$src_path;
- my $src_path = PVE::Storage::path($storecfg, $src_volid, $snapname);
- my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
+ my $dst_scfg = PVE::Storage::storage_config($storecfg, $dst_storeid);
+ my $dst_format = qemu_img_format($dst_scfg, $dst_volname);
+ my $dst_path = PVE::Storage::path($storecfg, $dst_volid);
+ my $dst_is_iscsi = ($dst_path =~ m|^iscsi://|);
- my $src_is_iscsi = ($src_path =~ m|^iscsi://|);
- my $dst_is_iscsi = ($dst_path =~ m|^iscsi://|);
+ my $cmd = [];
+ push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
+ push @$cmd, '-l', "snapshot.name=$snapname" if($snapname && $src_format eq "qcow2");
+ push @$cmd, '-t', 'none' if $dst_scfg->{type} eq 'zfspool';
+ push @$cmd, '-T', $cachemode if defined($cachemode);
+
+ if ($src_is_iscsi) {
+ push @$cmd, '--image-opts';
+ $src_path = convert_iscsi_path($src_path);
+ } else {
+ push @$cmd, '-f', $src_format;
+ }
- my $cmd = [];
- push @$cmd, '/usr/bin/qemu-img', 'convert', '-p', '-n';
- push @$cmd, '-l', "snapshot.name=$snapname" if($snapname && $src_format eq "qcow2");
- push @$cmd, '-t', 'none' if $dst_scfg->{type} eq 'zfspool';
- push @$cmd, '-T', 'none' if $src_scfg->{type} eq 'zfspool';
+ if ($dst_is_iscsi) {
+ push @$cmd, '--target-image-opts';
+ $dst_path = convert_iscsi_path($dst_path);
+ } else {
+ push @$cmd, '-O', $dst_format;
+ }
- if ($src_is_iscsi) {
- push @$cmd, '--image-opts';
- $src_path = convert_iscsi_path($src_path);
- } else {
- push @$cmd, '-f', $src_format;
- }
+ push @$cmd, $src_path;
- if ($dst_is_iscsi) {
- push @$cmd, '--target-image-opts';
- $dst_path = convert_iscsi_path($dst_path);
- } else {
- push @$cmd, '-O', $dst_format;
- }
+ if (!$dst_is_iscsi && $is_zero_initialized) {
+ push @$cmd, "zeroinit:$dst_path";
+ } else {
+ push @$cmd, $dst_path;
+ }
- push @$cmd, $src_path;
+ my $parser = sub {
+ my $line = shift;
+ if($line =~ m/\((\S+)\/100\%\)/){
+ my $percent = $1;
+ my $transferred = int($size * $percent / 100);
+ my $remaining = $size - $transferred;
- if (!$dst_is_iscsi && $is_zero_initialized) {
- push @$cmd, "zeroinit:$dst_path";
- } else {
- push @$cmd, $dst_path;
+ print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
}
- my $parser = sub {
- my $line = shift;
- if($line =~ m/\((\S+)\/100\%\)/){
- my $percent = $1;
- my $transferred = int($size * $percent / 100);
- my $remaining = $size - $transferred;
-
- print "transferred: $transferred bytes remaining: $remaining bytes total: $size bytes progression: $percent %\n";
- }
-
- };
+ };
- eval { run_command($cmd, timeout => undef, outfunc => $parser); };
- my $err = $@;
- die "copy failed: $err" if $err;
- }
+ eval { run_command($cmd, timeout => undef, outfunc => $parser); };
+ my $err = $@;
+ die "copy failed: $err" if $err;
}
sub qemu_img_format {
my (undef, $ovmf_vars) = get_ovmf_files($arch);
die "EFI vars default image not found\n" if ! -f $ovmf_vars;
- my $vars_size = PVE::Tools::convert_size(-s $ovmf_vars, 'b' => 'kb');
+ my $vars_size_b = -s $ovmf_vars;
+ my $vars_size = PVE::Tools::convert_size($vars_size_b, 'b' => 'kb');
my $volid = PVE::Storage::vdisk_alloc($storecfg, $storeid, $vmid, $fmt, undef, $vars_size);
PVE::Storage::activate_volumes($storecfg, [$volid]);
- my $path = PVE::Storage::path($storecfg, $volid);
- eval {
- run_command(['/usr/bin/qemu-img', 'convert', '-n', '-f', 'raw', '-O', $fmt, $ovmf_vars, $path]);
- };
- die "Copying EFI vars image failed: $@" if $@;
+ qemu_img_convert($ovmf_vars, $volid, $vars_size_b, undef, 0);
return ($volid, $vars_size);
}