I'd appreciate a few hints for the importdisk GUI feature. Yes or no to automatically adding the drive as active (not unused)?
Signed-off-by: Dominic Jäger <d.jae...@proxmox.com> --- PVE/API2/Qemu.pm | 87 +++++++++++++++++++++++++++++++++++- PVE/CLI/qm.pm | 57 +---------------------- PVE/QemuServer/ImportDisk.pm | 2 +- 3 files changed, 87 insertions(+), 59 deletions(-) diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm index fd51bf3..5e75605 100644 --- a/PVE/API2/Qemu.pm +++ b/PVE/API2/Qemu.pm @@ -23,6 +23,7 @@ use PVE::QemuServer; use PVE::QemuServer::Drive; use PVE::QemuServer::CPUConfig; use PVE::QemuServer::Monitor qw(mon_cmd); +use PVE::QemuServer::ImportDisk qw(do_import); use PVE::QemuMigrate; use PVE::RPCEnvironment; use PVE::AccessControl; @@ -44,8 +45,6 @@ BEGIN { } } -use Data::Dumper; # fixme: remove - use base qw(PVE::RESTHandler); my $opt_force_description = "Force physical removal. Without this, we simple remove the disk from the config file and create an additional configuration entry called 'unused[n]', which contains the volume ID. Unlink of unused[n] always cause physical removal."; @@ -4203,4 +4202,88 @@ __PACKAGE__->register_method({ return PVE::QemuServer::Cloudinit::dump_cloudinit_config($conf, $param->{vmid}, $param->{type}); }}); +__PACKAGE__->register_method ({ + name => 'importdisk', + path => '{vmid}/importdisk', + method => 'POST', + protected => 1, + proxyto => 'node', + description => "Import an external disk image into a VM. + The image format has to be supported by qemu-img(1).", + permissions => { + description => "You need 'VM.Config.Disk' permissions on /vms/{vmid}, + and 'Datastore.AllocateSpace' permissions on the storage.", + check => [ 'and', + ['perm', '/vms/{vmid}', [ 'VM.Config.Disk' ]], + ['perm', '/storage/{storage}', [ 'Datastore.AllocateSpace' ]], + ], + }, + parameters => { + additionalProperties => 0, + properties => PVE::QemuServer::json_config_properties ({ + node => get_standard_option('pve-node'), + vmid => get_standard_option('pve-vmid', {completion => \&PVE::QemuServer::complete_vmid}), + source => { + description => 'Path to the disk image to import', + type => 'string', + optional => 0, + }, + format => { + type => 'string', + description => 'Target format', + enum => [ 'raw', 'qcow2', 'vmdk' ], + optional => 1, + }, + }), + }, + returns => { type => 'string'}, + code => sub { + my ($param) = @_; + print("start\n"); + + my $rpcenv = PVE::RPCEnvironment::get(); + my $authuser = $rpcenv->get_user(); + + my $node = extract_param($param, 'node'); + my $vmid = extract_param($param, 'vmid'); + my $source = extract_param($param, 'source'); + my $drive = extract_param($param, 'drive'); + my $format = extract_param($param, 'format'); + my $storecfg = PVE::Storage::config(); + + # TODO nice error message if drive is not reachable + my $check_replication = sub { }; # TODO implement me, maybe? + my $driveX; + foreach my $opt (keys %$param) { + die ("Die because multiple drives\n") if defined($driveX); + if (PVE::QemuServer::is_valid_drivename($opt)) { + # cleanup drive path + my $drive = PVE::QemuServer::parse_drive($opt, $param->{$opt}); + raise_param_exc({ $opt => "unable to parse drive options" }) if !$drive; + PVE::QemuServer::cleanup_drive_path($opt, $storecfg, $drive); + $check_replication->($drive); # TODO do I need this? + $param->{$opt} = PVE::QemuServer::print_drive($drive); + die "$source: non-existent or non-regular file\n" if (! -f $source); + $driveX = $drive; + } + } + $drive = $driveX; + + my $message = $drive ? "to drive $drive->{'file'} on" : 'as unused drive to'; + print "Importing disk '$source' " . $message . " VM $vmid ...\n"; + my $worker = sub { + eval { + my $dn = "$drive->{'interface'}$drive->{'index'}"; + print("before import dn is $dn\n"); + my ($storeid) = $drive->{'file'} =~ /^(.*):/; + print("storeid before import is $storeid\n"); + my ($drive_id, $volid) = PVE::QemuServer::ImportDisk::do_import( + $source, $vmid, $storeid, { format => $format, drive_name => $dn }); + print "Successfully imported disk '$source' as '$drive_id: $volid'\n"; + }; + die "Importing disk failed: $@\n" if $@; + }; + return $rpcenv->fork_worker('importdisk', $vmid, $authuser, $worker); + }}); + 1; diff --git a/PVE/CLI/qm.pm b/PVE/CLI/qm.pm index 282fa86..75e07fa 100755 --- a/PVE/CLI/qm.pm +++ b/PVE/CLI/qm.pm @@ -445,61 +445,6 @@ __PACKAGE__->register_method ({ return undef; }}); -__PACKAGE__->register_method ({ - name => 'importdisk', - path => 'importdisk', - method => 'POST', - description => "Import an external disk image as an unused disk in a VM. The - image format has to be supported by qemu-img(1).", - parameters => { - additionalProperties => 0, - properties => { - vmid => get_standard_option('pve-vmid', {completion => \&PVE::QemuServer::complete_vmid}), - source => { - description => 'Path to the disk image to import', - type => 'string', - optional => 0, - }, - storage => get_standard_option('pve-storage-id', { - description => 'Target storage ID', - completion => \&PVE::QemuServer::complete_storage, - optional => 0, - }), - format => { - type => 'string', - description => 'Target format', - enum => [ 'raw', 'qcow2', 'vmdk' ], - optional => 1, - }, - }, - }, - returns => { type => 'null'}, - code => sub { - my ($param) = @_; - - my $vmid = extract_param($param, 'vmid'); - my $source = extract_param($param, 'source'); - my $storeid = extract_param($param, 'storage'); - my $format = extract_param($param, 'format'); - - my $vm_conf = PVE::QemuConfig->load_config($vmid); - PVE::QemuConfig->check_lock($vm_conf); - die "$source: non-existent or non-regular file\n" if (! -f $source); - - my $storecfg = PVE::Storage::config(); - PVE::Storage::storage_check_enabled($storecfg, $storeid); - - my $target_storage_config = PVE::Storage::storage_config($storecfg, $storeid); - die "storage $storeid does not support vm images\n" - if !$target_storage_config->{content}->{images}; - - print "importing disk '$source' to VM $vmid ...\n"; - my ($drive_id, $volid) = PVE::QemuServer::ImportDisk::do_import($source, $vmid, $storeid, { format => $format }); - print "Successfully imported disk as '$drive_id:$volid'\n"; - - return undef; - }}); - __PACKAGE__->register_method ({ name => 'terminal', path => 'terminal', @@ -984,7 +929,7 @@ our $cmddef = { terminal => [ __PACKAGE__, 'terminal', ['vmid']], - importdisk => [ __PACKAGE__, 'importdisk', ['vmid', 'source', 'storage']], + importdisk => [ "PVE::API2::Qemu", 'importdisk', ['vmid', 'source', 'storage']], importovf => [ __PACKAGE__, 'importovf', ['vmid', 'manifest', 'storage']], diff --git a/PVE/QemuServer/ImportDisk.pm b/PVE/QemuServer/ImportDisk.pm index 51ad52e..d89cd4d 100755 --- a/PVE/QemuServer/ImportDisk.pm +++ b/PVE/QemuServer/ImportDisk.pm @@ -38,7 +38,7 @@ sub do_import { } if ($drive_name) { - # should never happen as setting $drive_name is not exposed to public interface + # Exposed in importdisk API only die "cowardly refusing to overwrite existing entry: $drive_name\n" if $vm_conf->{$drive_name}; my $modified = {}; # record what $option we modify -- 2.20.1 _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel