if (!$volid || $volid eq 'none') {
# nothing to check
+ } elsif ($isCDROM && ($volid eq 'cdrom')) {
+ $rpcenv->check($authuser, "/", ['Sys.Console']);
} elsif (!$isCDROM && ($volid =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/)) {
my ($storeid, $size) = ($2 || $default_storage, $3);
die "no storage ID specified (and no default storage)\n" if !$storeid;
$rpcenv->check($authuser, "/storage/$storeid", ['Datastore.AllocateSpace']);
} else {
- my $path = $rpcenv->check_volume_access($authuser, $storecfg, $vmid, $volid);
- die "image '$path' does not exists\n" if (!(-f $path || -b $path));
+ $rpcenv->check_volume_access($authuser, $storecfg, $vmid, $volid);
}
});
};
my $volid = $disk->{file};
- if (!$volid || $volid eq 'none') {
+ if (!$volid || $volid eq 'none' || $volid eq 'cdrom') {
$res->{$ds} = $settings->{$ds};
} elsif ($volid =~ m/^(([^:\s]+):)?(\d+(\.\d+)?)$/) {
my ($storeid, $size) = ($2 || $default_storage, $3);
$res->{$ds} = PVE::QemuServer::print_drive($vmid, $disk);
} else {
my $path = $rpcenv->check_volume_access($authuser, $storecfg, $vmid, $volid);
- die "image '$path' does not exists\n" if (!(-f $path || -b $path));
+ PVE::Storage::activate_volumes($storecfg, [ $volid ])
+ if PVE::Storage::parse_volume_id ($volid, 1);
+
+ my ($storeid, $volname) = PVE::Storage::parse_volume_id($volid);
+ my $dl = PVE::Storage::vdisk_list($storecfg, $storeid, undef);
+ my $foundvolid = undef;
+
+ PVE::Storage::foreach_volid($dl, sub {
+ my ($volumeid) = @_;
+ if($volumeid eq $volid) {
+ $foundvolid = 1;
+ return;
+ }
+ });
+
+ die "image '$path' does not exists\n" if (!(-f $path || -b $path || $foundvolid));
$res->{$ds} = $settings->{$ds};
}
});
my $check_vm_modify_config_perm = sub {
my ($rpcenv, $authuser, $vmid, $pool, $key_list) = @_;
- return 1 if $authuser ne 'root@pam';
+ return 1 if $authuser eq 'root@pam';
foreach my $opt (@$key_list) {
# disk checks need to be done somewhere else
if ($opt eq 'sockets' || $opt eq 'cores' ||
$opt eq 'cpu' || $opt eq 'smp' ||
- $opt eq 'cpuimit' || $opt eq 'cpuunits') {
+ $opt eq 'cpulimit' || $opt eq 'cpuunits') {
$rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.CPU']);
} elsif ($opt eq 'boot' || $opt eq 'bootdisk') {
$rpcenv->check_vm_perm($authuser, $vmid, $pool, ['VM.Config.Disk']);
if (defined($pool)) {
$rpcenv->check_pool_exist($pool);
- $rpcenv->check_perm_modify($authuser, "/pool/$pool");
}
$rpcenv->check($authuser, "/storage/$storage", ['Datastore.AllocateSpace'])
if ($archive eq '-') {
die "pipe requires cli environment\n"
- && $rpcenv->{type} ne 'cli';
+ if $rpcenv->{type} ne 'cli';
} else {
my $path = $rpcenv->check_volume_access($authuser, $storecfg, $vmid, $archive);
+
+ PVE::Storage::activate_volumes($storecfg, [ $archive ])
+ if PVE::Storage::parse_volume_id ($archive, 1);
+
die "can't find archive file '$archive'\n" if !($path && -f $path);
$archive = $path;
}
my $createfn = sub {
- # second test (after locking test is accurate)
+ # test after locking
die "unable to create vm $vmid: config file already exists\n"
if -f $filename;
return $rpcenv->fork_worker('qmcreate', $vmid, $authuser, $realcmd);
};
- return PVE::QemuServer::lock_config($vmid, $archive ? $restorefn : $createfn);
+ return PVE::QemuServer::lock_config_full($vmid, 1, $archive ? $restorefn : $createfn);
}});
__PACKAGE__->register_method({
if (&$vm_is_volid_owner($storecfg, $vmid, $volid)) {
if ($force || $key =~ m/^unused/) {
eval { PVE::Storage::vdisk_free($storecfg, $volid); };
- warn $@ if $@;
+ die $@ if $@;
} else {
PVE::QemuServer::add_unused_volume($conf, $volid, $vmid);
}
- delete $conf->{$key};
}
}
+
+ delete $conf->{$key};
};
my $vmconfig_delete_option = sub {
my $delVMfromPoolFn = sub {
my $usercfg = cfs_read_file("user.cfg");
- my $pool = $usercfg->{vms}->{$vmid};
- if (my $data = $usercfg->{pools}->{$pool}) {
- delete $data->{vms}->{$vmid};
- delete $usercfg->{vms}->{$vmid};
- cfs_write_file("user.cfg", $usercfg);
+ if (my $pool = $usercfg->{vms}->{$vmid}) {
+ if (my $data = $usercfg->{pools}->{$pool}) {
+ delete $data->{vms}->{$vmid};
+ delete $usercfg->{vms}->{$vmid};
+ cfs_write_file("user.cfg", $usercfg);
+ }
}
};
return $res;
}});
+my $vm_is_ha_managed = sub {
+ my ($vmid) = @_;
+
+ my $cc = PVE::Cluster::cfs_read_file('cluster.conf');
+ if (PVE::Cluster::cluster_conf_lookup_pvevm($cc, 0, $vmid, 1)) {
+ return 1;
+ }
+ return 0;
+};
+
__PACKAGE__->register_method({
name => 'vm_status',
path => '{vmid}/status/current',
my $vmstatus = PVE::QemuServer::vmstatus($param->{vmid});
my $status = $vmstatus->{$param->{vmid}};
- my $cc = PVE::Cluster::cfs_read_file('cluster.conf');
- if (PVE::Cluster::cluster_conf_lookup_pvevm($cc, 0, $param->{vmid}, 1)) {
- $status->{ha} = 1;
- } else {
- $status->{ha} = 0;
- }
+ $status->{ha} = &$vm_is_ha_managed($param->{vmid});
return $status;
}});
my $storecfg = PVE::Storage::config();
- my $realcmd = sub {
- my $upid = shift;
+ if (&$vm_is_ha_managed($vmid) && !$stateuri &&
+ $rpcenv->{type} ne 'ha') {
- syslog('info', "start VM $vmid: $upid\n");
+ my $hacmd = sub {
+ my $upid = shift;
- PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock);
+ my $service = "pvevm:$vmid";
- return;
- };
+ my $cmd = ['clusvcadm', '-e', $service, '-m', $node];
+
+ print "Executing HA start for VM $vmid\n";
+
+ PVE::Tools::run_command($cmd);
+
+ return;
+ };
- return $rpcenv->fork_worker('qmstart', $vmid, $authuser, $realcmd);
+ return $rpcenv->fork_worker('hastart', $vmid, $authuser, $hacmd);
+
+ } else {
+
+ my $realcmd = sub {
+ my $upid = shift;
+
+ syslog('info', "start VM $vmid: $upid\n");
+
+ PVE::QemuServer::vm_start($storecfg, $vmid, $stateuri, $skiplock);
+
+ return;
+ };
+
+ return $rpcenv->fork_worker('qmstart', $vmid, $authuser, $realcmd);
+ }
}});
__PACKAGE__->register_method({
my $storecfg = PVE::Storage::config();
- my $realcmd = sub {
- my $upid = shift;
+ if (&$vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
- syslog('info', "stop VM $vmid: $upid\n");
+ my $hacmd = sub {
+ my $upid = shift;
- PVE::QemuServer::vm_stop($storecfg, $vmid, $skiplock, 0,
- $param->{timeout}, 0, 1, $keepActive);
+ my $service = "pvevm:$vmid";
- return;
- };
+ my $cmd = ['clusvcadm', '-d', $service];
+
+ print "Executing HA stop for VM $vmid\n";
- return $rpcenv->fork_worker('qmstop', $vmid, $authuser, $realcmd);
+ PVE::Tools::run_command($cmd);
+
+ return;
+ };
+
+ return $rpcenv->fork_worker('hastop', $vmid, $authuser, $hacmd);
+
+ } else {
+ my $realcmd = sub {
+ my $upid = shift;
+
+ syslog('info', "stop VM $vmid: $upid\n");
+
+ PVE::QemuServer::vm_stop($storecfg, $vmid, $skiplock, 0,
+ $param->{timeout}, 0, 1, $keepActive);
+
+ return;
+ };
+
+ return $rpcenv->fork_worker('qmstop', $vmid, $authuser, $realcmd);
+ }
}});
__PACKAGE__->register_method({
if !$param->{online};
}
- my $realcmd = sub {
- my $upid = shift;
+ my $storecfg = PVE::Storage::config();
+ PVE::QemuServer::check_storage_availability($storecfg, $conf, $target);
- PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
- };
+ if (&$vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
+
+ my $hacmd = sub {
+ my $upid = shift;
+
+ my $service = "pvevm:$vmid";
+
+ my $cmd = ['clusvcadm', '-M', $service, '-m', $target];
+
+ print "Executing HA migrate for VM $vmid to node $target\n";
+
+ PVE::Tools::run_command($cmd);
+
+ return;
+ };
- my $upid = $rpcenv->fork_worker('qmigrate', $vmid, $authuser, $realcmd);
+ return $rpcenv->fork_worker('hamigrate', $vmid, $authuser, $hacmd);
+
+ } else {
+
+ my $realcmd = sub {
+ my $upid = shift;
+
+ PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
+ };
+
+ return $rpcenv->fork_worker('qmigrate', $vmid, $authuser, $realcmd);
+ }
- return $upid;
}});
__PACKAGE__->register_method({