On 5/22/20 12:08 PM, Dominic Jäger wrote: > I'd appreciate a few hints for the importdisk GUI feature. > > Yes or no to automatically adding the drive as active (not unused)?
Well, IMO makes sense but I'd add an parameter for either a config ID (scsi0, sata2, ...) which it is added if free, and/or the bus (controller) where we then select the next free slot if any. > > 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).", please use concatenated multi line strings for description, i.e.: 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 ({ hmm, doesn't this puts _all_ of our VM config properties in here?? Most probably do not make sense, only some disk/bus related ones, I'd say. > + 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); nit: no parenthesis in die > + 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"; FYI: double quoted strings allow $variable interpolation, so you do not need to concat this extra. > + 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 > _______________________________________________ pve-devel mailing list pve-devel@pve.proxmox.com https://pve.proxmox.com/cgi-bin/mailman/listinfo/pve-devel