[pve-devel] [PATCH container] Close #1234: pct: implement rescan
Alwin Antreich
a.antreich at proxmox.com
Tue Sep 18 11:16:17 CEST 2018
This patch implements the same feature as already exists for qm
'rescan'. With options for updating the disksize or the unused disks
only.
Signed-off-by: Alwin Antreich <a.antreich at proxmox.com>
---
Sure some methods can be migrated into the guest-common. Comments appreciated.
src/PVE/CLI/pct.pm | 44 ++++++++++++++++
src/PVE/LXC.pm | 149 +++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 193 insertions(+)
diff --git a/src/PVE/CLI/pct.pm b/src/PVE/CLI/pct.pm
index 6296d6f..36e3fcf 100755
--- a/src/PVE/CLI/pct.pm
+++ b/src/PVE/CLI/pct.pm
@@ -461,6 +461,49 @@ sub create_file {
return $fd;
}
+__PACKAGE__->register_method ({
+ name => 'rescan',
+ path => 'rescan',
+ method => 'POST',
+ description => "Rescan all storages and update disk sizes and unused disk images.",
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ vmid => get_standard_option('pve-vmid', {
+ optional => 1,
+ completion => \&PVE::LXC::complete_ctid,
+ }),
+ dryrun => {
+ type => 'boolean',
+ optional => 1,
+ default => 0,
+ description => 'Do not actually write changes out to conifg.',
+ },
+ unusedOnly => {
+ type => 'boolean',
+ optional => 1,
+ default => 0,
+ description => 'Add only unsued disk(s) to the config.',
+ },
+ disksizeOnly => {
+ type => 'boolean',
+ optional => 1,
+ default => 0,
+ description => 'Only update the disk size in the conifg.',
+ },
+ },
+ },
+ returns => { type => 'null'},
+ code => sub {
+ my ($param) = @_;
+
+ print "NOTE: running in dry-run mode, won't write changes out!\n" if $param->{dryrun};
+
+ PVE::LXC::rescan($param->{vmid}, 0, $param);
+
+ return undef;
+ }});
+
__PACKAGE__->register_method({
name => 'pull',
path => 'pull',
@@ -774,6 +817,7 @@ our $cmddef = {
pull => [ __PACKAGE__, 'pull', ['vmid', 'path', 'destination']],
df => [ __PACKAGE__, 'df', ['vmid']],
+ rescan => [ __PACKAGE__, 'rescan', []],
destroy => [ 'PVE::API2::LXC', 'destroy_vm', ['vmid'],
{ node => $nodename }, $upid_exit ],
diff --git a/src/PVE/LXC.pm b/src/PVE/LXC.pm
index 0b57ae9..e78128a 100644
--- a/src/PVE/LXC.pm
+++ b/src/PVE/LXC.pm
@@ -1538,6 +1538,155 @@ sub create_disks {
return $vollist;
}
+sub update_disksize {
+ my ($vmid, $conf, $volid_hash) = @_;
+
+ my $changes;
+
+ my $update_mp = sub {
+ my ($key, $mp, @param) = @_;
+ my $size = $volid_hash->{$mp->{volume}}->{size};
+
+ if ($size != $mp->{size}) {
+ $changes = 1;
+ $mp->{size} = $size;
+ }
+
+ my $skip = $key eq 'rootfs' ? 1 : 0;
+ $conf->{$key} = PVE::LXC::Config->print_ct_mountpoint($mp, $skip);
+ };
+
+ PVE::LXC::Config->foreach_mountpoint($conf, $update_mp);
+
+ return $changes;
+
+}
+
+sub update_unused {
+ my ($vmid, $conf, $volid_hash) = @_;
+
+ my $changes;
+ my $prefix = "CT $vmid:";
+
+ # Note: it is allowed to define multiple storages with same path (alias), so
+ # we need to check both 'volid' and real 'path' (two different volid can point
+ # to the same path).
+
+ # used and unused disks
+ my $refpath = {};
+ my $referenced = {};
+
+ foreach my $opt (keys %$conf) {
+ next if ($opt !~ m/^unused(\d+)$/);
+ my $vol = $volid_hash->{$conf->{$opt}};
+ $refpath->{$vol->{path}} = $vol->{volid};
+ }
+
+ foreach my $key (keys %$volid_hash) {
+ my $vol = $volid_hash->{$key};
+ my $in_use = PVE::LXC::Config->is_volume_in_use($conf, $vol->{volid});
+
+ if ($in_use) {
+ $refpath->{$vol->{path}} = $key;
+ delete $referenced->{$vol->{path}} if $referenced->{$vol->{path}};
+ } else {
+ if ((!$referenced->{$vol->{path}}) && (!$refpath->{$vol->{path}})) {
+ $referenced->{$vol->{path}} = $key;
+ }
+ }
+
+ }
+
+ for my $key (keys %$referenced) {
+ my $disk = $referenced->{$key};
+ my $unused = PVE::LXC::Config->add_unused_volume($conf, $disk);
+
+ if ($unused) {
+ $changes = 1;
+ print "$prefix add unreferenced volume '$disk' as '$unused' to config.\n";
+ }
+ }
+
+ return $changes;
+
+}
+
+sub scan_volids {
+ my ($cfg, $vmid) = @_;
+
+ my $info = PVE::Storage::vdisk_list($cfg, undef, $vmid);
+
+ my $volid_hash = {};
+ foreach my $storeid (keys %$info) {
+ foreach my $item (@{$info->{$storeid}}) {
+ next if !($item->{volid} && $item->{size});
+ $item->{path} = PVE::Storage::path($cfg, $item->{volid});
+ $volid_hash->{$item->{volid}} = $item;
+ }
+ }
+
+ return $volid_hash;
+}
+
+sub rescan {
+ my ($vmid, $nolock, $param) = @_;
+
+ my $cfg = PVE::Storage::config();
+
+ # FIXME: Remove once our RBD plugin can handle CT and VM on a single storage
+ # see: https://pve.proxmox.com/pipermail/pve-devel/2018-July/032900.html
+ foreach my $stor (keys %{$cfg->{ids}}) {
+ delete($cfg->{ids}->{$stor}) if !$cfg->{ids}->{$stor}->{content}->{rootdir};
+ }
+
+ print "rescan volumes...\n";
+ my $volid_hash = scan_volids($cfg, $vmid);
+
+ my $updatefn = sub {
+ my ($vmid) = @_;
+
+ my $changes;
+ my $unused = $param->{unusedOnly};
+ my $disksize = $param->{disksizeOnly};
+
+ $unused = $disksize = 1 if ((!$unused) && (!$disksize));
+
+ my $conf = PVE::LXC::Config->load_config($vmid);
+
+ PVE::LXC::Config->check_lock($conf);
+
+ my $vm_volids = {};
+ foreach my $volid (keys %$volid_hash) {
+ my $info = $volid_hash->{$volid};
+ $vm_volids->{$volid} = $info if $info->{vmid} && $info->{vmid} == $vmid;
+ }
+
+ my $upu = update_unused($vmid, $conf, $vm_volids) if $unused;
+ my $upd = update_disksize($vmid, $conf, $vm_volids) if $disksize;
+ $changes = $upu // $upd;
+
+ PVE::LXC::Config->write_config($vmid, $conf) if $changes && !$param->{dryrun};
+ };
+
+ if (defined($vmid)) {
+ if ($nolock) {
+ &$updatefn($vmid);
+ } else {
+ PVE::LXC::Config->lock_config($vmid, $updatefn, $vmid);
+ }
+ } else {
+ my $vmlist = config_list();
+ foreach my $vmid (keys %$vmlist) {
+ if ($nolock) {
+ &$updatefn($vmid);
+ } else {
+ PVE::LXC::Config->lock_config($vmid, $updatefn, $vmid);
+ }
+ }
+ }
+}
+
+
# bash completion helper
sub complete_os_templates {
--
2.11.0
More information about the pve-devel
mailing list