return undef;
}});
-__PACKAGE__->register_method ({
- name => 'startall',
- path => 'startall',
- method => 'POST',
- description => "Start all virtual machines (when onboot=1).",
- parameters => {
- additionalProperties => 0,
- properties => {},
- },
- returns => { type => 'null'},
- code => sub {
- my ($param) = @_;
-
- # wait up to 10 seconds for quorum
- for (my $i = 10; $i >= 0; $i--) {
- last if PVE::Cluster::check_cfs_quorum($i != 0 ? 1 : 0);
- sleep(1);
- }
-
- my $vzlist = PVE::QemuServer::vzlist();
- my $storecfg = PVE::Storage::config();
-
- my $count = 0;
- foreach my $vmid (keys %$vzlist) {
- next if $vzlist->{$vmid}->{pid}; # already running
-
- my $conf;
- eval { $conf = PVE::QemuServer::load_config($vmid); };
- if (my $err = $@) {
- warn $err;
- next;
- }
-
- next if !($conf && $conf->{onboot});
-
- sleep(2) if $count != 0; # reduce load
- $count++;
-
- PVE::Cluster::check_cfs_quorum(); # abort when we loose quorum
-
- eval {
- print STDERR "Starting Qemu VM $vmid\n";
- PVE::QemuServer::vm_start($storecfg, $vmid);
- };
- warn $@ if $@;
- }
-
- return undef;
- }});
-
-__PACKAGE__->register_method ({
- name => 'stopall',
- path => 'stopall',
- method => 'POST',
- description => "Stop all virtual machines.",
- parameters => {
- additionalProperties => 0,
- properties => {
- timeout => {
- description => "Timeout in seconds. Default is to wait 3 minutes.",
- type => 'integer',
- minimum => 1,
- optional => 1,
- }
- },
- },
- returns => { type => 'null'},
- code => sub {
- my ($param) = @_;
-
- my $timeout = $param->{timeout};
-
- my $storecfg = PVE::Storage::config();
-
- PVE::QemuServer::vm_stopall($storecfg, $timeout);
-
- return undef;
- }});
-
__PACKAGE__->register_method ({
name => 'wait',
path => 'wait',
last if $input =~ m/^\s*q(uit)?\s*$/;
eval {
- print PVE::QemuServer::vm_monitor_command ($vmid, $input);
+ print PVE::QemuServer::vm_human_monitor_command ($vmid, $input);
};
print "ERROR: $@" if $@;
}
}});
+__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}),
+ },
+ },
+ returns => { type => 'null'},
+ code => sub {
+ my ($param) = @_;
+
+ my $cfg = PVE::Cluster::cfs_read_file("storage.cfg");
+
+ my $info = PVE::Storage::vdisk_list($cfg, undef, $param->{vmid});
+
+ my $volid_hash = {};
+ foreach my $storeid (keys %$info) {
+ foreach my $item (@{$info->{$storeid}}) {
+ next if !($item->{volid} && $item->{size});
+ $volid_hash->{$item->{volid}} = $item;
+ }
+ }
+
+ my $updatefn = sub {
+ my ($vmid) = @_;
+
+ my $conf = PVE::QemuServer::load_config($vmid);
+
+ PVE::QemuServer::check_lock($conf);
+
+ my $changes;
+
+ my $used = {};
+
+ # update size info
+ foreach my $opt (keys %$conf) {
+ if (PVE::QemuServer::valid_drivename($opt)) {
+ my $drive = PVE::QemuServer::parse_drive($opt, $conf->{$opt});
+ my $volid = $drive->{file};
+ next if !$volid;
+
+ $used->{$volid} = 1;
+
+ next if PVE::QemuServer::drive_is_cdrom($drive);
+ next if !$volid_hash->{$volid};
+
+ $drive->{size} = $volid_hash->{$volid}->{size};
+ $changes = 1;
+ $conf->{$opt} = PVE::QemuServer::print_drive($vmid, $drive);
+ }
+ }
+
+ # add unused volumes
+ foreach my $storeid (keys %$info) {
+ foreach my $item (@{$info->{$storeid}}) {
+ next if !($item->{volid} && $item->{vmid});
+ next if $item->{vmid} ne $vmid;
+ next if $item->{volid} =~ m/vm-$vmid-state-/;
+ next if $used->{$item->{volid}};
+ $changes = 1;
+ PVE::QemuServer::add_unused_volume($conf, $item->{volid});
+ }
+ }
+
+ PVE::QemuServer::update_config_nolock($vmid, $conf, 1) if $changes;
+ };
+
+ if (defined($param->{vmid})) {
+ PVE::QemuServer::lock_config($param->{vmid}, $updatefn, $param->{vmid});
+ } else {
+ my $vmlist = PVE::QemuServer::config_list();
+ foreach my $vmid (keys %$vmlist) {
+ PVE::QemuServer::lock_config($vmid, $updatefn, $vmid);
+ }
+ }
+
+ return undef;
+ }});
+
my $cmddef = {
list => [ "PVE::API2::Qemu", 'vmlist', [],
{ node => $nodename }, sub {
set => [ "PVE::API2::Qemu", 'update_vm', ['vmid'], { node => $nodename } ],
+ resize => [ "PVE::API2::Qemu", 'resize_vm', ['vmid', 'disk', 'size'], { node => $nodename } ],
+
unlink => [ "PVE::API2::Qemu", 'unlink', ['vmid', 'idlist'], { node => $nodename } ],
config => [ "PVE::API2::Qemu", 'vm_config', ['vmid'],
status => [ __PACKAGE__, 'status', ['vmid']],
+ snapshot => [ "PVE::API2::Qemu", 'snapshot', ['vmid', 'snapname'], { node => $nodename } , $upid_exit ],
+
+ delsnapshot => [ "PVE::API2::Qemu", 'delsnapshot', ['vmid', 'snapname'], { node => $nodename } , $upid_exit ],
+
+ rollback => [ "PVE::API2::Qemu", 'rollback', ['vmid', 'snapname'], { node => $nodename } , $upid_exit ],
+
start => [ "PVE::API2::Qemu", 'vm_start', ['vmid'], { node => $nodename } , $upid_exit ],
stop => [ "PVE::API2::Qemu", 'vm_stop', ['vmid'], { node => $nodename }, $upid_exit ],
unlock => [ __PACKAGE__, 'unlock', ['vmid']],
- monitor => [ __PACKAGE__, 'monitor', ['vmid']],
-
- startall => [ __PACKAGE__, 'startall', []],
+ rescan => [ __PACKAGE__, 'rescan', []],
- stopall => [ __PACKAGE__, 'stopall', []],
+ monitor => [ __PACKAGE__, 'monitor', ['vmid']],
mtunnel => [ __PACKAGE__, 'mtunnel', []],
};
my $cmd = shift;
+# Note: disable '+' prefix for Getopt::Long (for resize command)
+use Getopt::Long qw(:config no_getopt_compat);
+
PVE::CLIHandler::handle_cmd($cmddef, "qm", $cmd, \@ARGV, undef, $0);
exit 0;