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);
+ PVE::Storage::activate_volumes($storecfg, [ $volid ]);
die "image '$path' does not exists\n" if (!(-f $path || -b $path));
$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']);
&& $rpcenv->{type} ne 'cli';
} else {
my $path = $rpcenv->check_volume_access($authuser, $storecfg, $vmid, $archive);
+ PVE::Storage::activate_volumes($storecfg, [ $archive ]);
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({
} else {
PVE::QemuServer::add_unused_volume($conf, $volid, $vmid);
}
- delete $conf->{$key};
}
}
+
+ delete $conf->{$key};
};
my $vmconfig_delete_option = sub {
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";
- return $rpcenv->fork_worker('qmstart', $vmid, $authuser, $realcmd);
+ PVE::Tools::run_command($cmd);
+
+ return;
+ };
+
+ 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];
- return $rpcenv->fork_worker('qmstop', $vmid, $authuser, $realcmd);
+ print "Executing HA stop for VM $vmid\n";
+
+ 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;
+ if (&$vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
- PVE::QemuMigrate->migrate($target, $targetip, $vmid, $param);
- };
+ 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;
+ };
+
+ return $rpcenv->fork_worker('hamigrate', $vmid, $authuser, $hacmd);
- my $upid = $rpcenv->fork_worker('qmigrate', $vmid, $authuser, $realcmd);
+ } 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({