]> git.proxmox.com Git - pve-container.git/blobdiff - src/PVE/API2/LXC/Status.pm
api: stop: reword overrule-shutdown parameter description
[pve-container.git] / src / PVE / API2 / LXC / Status.pm
index bfd851f19aa55cb5a3e26aa48be747cc953182ae..2eeecdf260a436810443280309bd434047653937 100644 (file)
@@ -15,11 +15,18 @@ use PVE::RESTHandler;
 use PVE::RPCEnvironment;
 use PVE::LXC;
 use PVE::LXC::Create;
-use PVE::HA::Config;
 use PVE::JSONSchema qw(get_standard_option);
+
 use base qw(PVE::RESTHandler);
 
-use Data::Dumper; # fixme: remove
+BEGIN {
+    if (!$ENV{PVE_GENERATING_DOCS}) {
+       require PVE::HA::Env::PVE2;
+       import  PVE::HA::Env::PVE2;
+       require PVE::HA::Config;
+       import  PVE::HA::Config;
+    }
+}
 
 __PACKAGE__->register_method({
     name => 'vmcmdidx',
@@ -31,7 +38,7 @@ __PACKAGE__->register_method({
        user => 'all',
     },
     parameters => {
-       additionalProperties => 0,
+       additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
            vmid => get_standard_option('pve-vmid'),
@@ -51,15 +58,16 @@ __PACKAGE__->register_method({
        my ($param) = @_;
 
        # test if VM exists
-       my $conf = PVE::LXC::load_config($param->{vmid});
+       my $conf = PVE::LXC::Config->load_config($param->{vmid});
 
        my $res = [
            { subdir => 'current' },
            { subdir => 'start' },
            { subdir => 'stop' },
            { subdir => 'shutdown' },
+           { subdir => 'reboot' },
            { subdir => 'migrate' },
-           ];
+       ];
 
        return $res;
     }});
@@ -69,29 +77,39 @@ __PACKAGE__->register_method({
     path => 'current',
     method => 'GET',
     proxyto => 'node',
-    protected => 1, # openvz /proc entries are only readable by root
+    protected => 1, # /proc entries are only readable by root
     description => "Get virtual machine status.",
     permissions => {
        check => ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
     },
     parameters => {
-       additionalProperties => 0,
+       additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
            vmid => get_standard_option('pve-vmid'),
        },
     },
-    returns => { type => 'object' },
+    returns => {
+       type => 'object',
+       properties => {
+           %$PVE::LXC::vmstatus_return_properties,
+           ha => {
+               description => "HA manager service status.",
+               type => 'object',
+           },
+       },
+    },
     code => sub {
        my ($param) = @_;
 
        # test if VM exists
-       my $conf = PVE::LXC::load_config($param->{vmid});
+       my $vmid = $param->{vmid};
+       my $conf = PVE::LXC::Config->load_config($vmid);
 
-       my $vmstatus =  PVE::LXC::vmstatus($param->{vmid});
-       my $status = $vmstatus->{$param->{vmid}};
+       my $vmstatus = PVE::LXC::vmstatus($vmid);
+       my $status = $vmstatus->{$vmid};
 
-       $status->{ha} = PVE::HA::Config::vm_is_ha_managed($param->{vmid}) ? 1 : 0;
+       $status->{ha} = PVE::HA::Config::get_service_status("ct:$vmid");
 
        return $status;
     }});
@@ -107,10 +125,17 @@ __PACKAGE__->register_method({
        check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
     },
     parameters => {
-       additionalProperties => 0,
+       additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
-           vmid => get_standard_option('pve-vmid'),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_stopped }),
+           skiplock => get_standard_option('skiplock'),
+           debug => {
+               optional => 1,
+               type => 'boolean',
+               description => "If set, enables very verbose debug log-level on start.",
+               default => 0,
+           },
        },
     },
     returns => {
@@ -120,29 +145,28 @@ __PACKAGE__->register_method({
        my ($param) = @_;
 
        my $rpcenv = PVE::RPCEnvironment::get();
-
        my $authuser = $rpcenv->get_user();
 
        my $node = extract_param($param, 'node');
-
        my $vmid = extract_param($param, 'vmid');
 
+       my $skiplock = extract_param($param, 'skiplock');
+       raise_param_exc({ skiplock => "Only root may use this option." })
+           if $skiplock && $authuser ne 'root@pam';
+
        die "CT $vmid already running\n" if PVE::LXC::check_running($vmid);
 
+       PVE::Cluster::check_cfs_quorum();
+
        if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
 
            my $hacmd = sub {
                my $upid = shift;
 
-               my $service = "ct:$vmid";
-
-               my $cmd = ['ha-manager', 'enable', $service];
-
-               print "Executing HA start for CT $vmid\n";
+               print "Requesting HA start for CT $vmid\n";
 
+               my $cmd = ['ha-manager', 'set',  "ct:$vmid", '--state', 'started'];
                PVE::Tools::run_command($cmd);
-
-               return;
            };
 
            return $rpcenv->fork_worker('hastart', $vmid, $authuser, $hacmd);
@@ -152,22 +176,28 @@ __PACKAGE__->register_method({
            my $realcmd = sub {
                my $upid = shift;
 
-               syslog('info', "starting CT $vmid: $upid\n");
-
-               my $conf = PVE::LXC::load_config($vmid);
+               PVE::LXC::Config->lock_config($vmid, sub {
+                   syslog('info', "starting CT $vmid: $upid\n");
 
-               die "you can't start a CT if it's a template\n"
-                   if PVE::LXC::is_template($conf);
+                   my $conf = PVE::LXC::Config->load_config($vmid);
 
-               my $storage_cfg = cfs_read_file("storage.cfg");
+                   die "you can't start a CT if it's a template\n"
+                       if PVE::LXC::Config->is_template($conf);
 
-               PVE::LXC::update_lxc_config($storage_cfg, $vmid, $conf);
+                   if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
+                       PVE::LXC::Config->check_lock($conf);
+                   }
 
-               my $cmd = ['lxc-start', '-n', $vmid];
+                   if ($conf->{unprivileged}) {
+                       PVE::LXC::Config->foreach_volume($conf, sub {
+                           my ($ms, $mountpoint) = @_;
+                           die "Quotas are not supported by unprivileged containers.\n"
+                               if $mountpoint->{quota};
+                       });
+                   }
 
-               run_command($cmd);
-
-               return;
+                   PVE::LXC::vm_start($vmid, $conf, $skiplock, $param->{debug});
+               });
            };
 
            return $rpcenv->fork_worker('vzstart', $vmid, $authuser, $realcmd);
@@ -180,15 +210,22 @@ __PACKAGE__->register_method({
     method => 'POST',
     protected => 1,
     proxyto => 'node',
-    description => "Stop the container.",
+    description => "Stop the container. This will abruptly stop all processes running in the container.",
     permissions => {
        check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
     },
     parameters => {
-       additionalProperties => 0,
+       additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
-           vmid => get_standard_option('pve-vmid'),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
+           skiplock => get_standard_option('skiplock'),
+           'overrule-shutdown' => {
+               description => "Try to abort active 'vzshutdown' tasks before stopping.",
+               optional => 1,
+               type => 'boolean',
+               default => 0,
+           }
        },
     },
     returns => {
@@ -198,29 +235,30 @@ __PACKAGE__->register_method({
        my ($param) = @_;
 
        my $rpcenv = PVE::RPCEnvironment::get();
-
        my $authuser = $rpcenv->get_user();
-
        my $node = extract_param($param, 'node');
-
        my $vmid = extract_param($param, 'vmid');
 
+       my $skiplock = extract_param($param, 'skiplock');
+       raise_param_exc({ skiplock => "Only root may use this option." })
+           if $skiplock && $authuser ne 'root@pam';
+
+       my $overrule_shutdown = extract_param($param, 'overrule-shutdown');
+
        die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
 
        if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
 
+           raise_param_exc({ 'overrule-shutdown' => "Not applicable for HA resources." })
+               if $overrule_shutdown;
+
            my $hacmd = sub {
                my $upid = shift;
 
-               my $service = "ct:$vmid";
-
-               my $cmd = ['ha-manager', 'disable', $service];
-
-               print "Executing HA stop for CT $vmid\n";
+               print "Requesting HA stop for CT $vmid\n";
 
+               my $cmd = ['ha-manager', 'crm-command', 'stop', "ct:$vmid", '0'];
                PVE::Tools::run_command($cmd);
-
-               return;
            };
 
            return $rpcenv->fork_worker('hastop', $vmid, $authuser, $hacmd);
@@ -230,17 +268,24 @@ __PACKAGE__->register_method({
            my $realcmd = sub {
                my $upid = shift;
 
-               syslog('info', "stoping CT $vmid: $upid\n");
-
-               my $conf = PVE::LXC::load_config($vmid);
+               if ($overrule_shutdown) {
+                   my $overruled_tasks = PVE::GuestHelpers::abort_guest_tasks(
+                       $rpcenv, 'vzshutdown', $vmid);
+                   my $overruled_tasks_list = join(", ", $overruled_tasks->@*);
+                   print "overruled vzshutdown tasks: $overruled_tasks_list\n"
+                       if @$overruled_tasks;
+               };
 
-               my $storage_cfg = PVE::Storage::config();
+               PVE::LXC::Config->lock_config($vmid, sub {
+                   syslog('info', "stopping CT $vmid: $upid\n");
 
-               my $cmd = ['lxc-stop', '-n', $vmid, '--kill'];
+                   my $conf = PVE::LXC::Config->load_config($vmid);
+                   if (!$skiplock && !PVE::LXC::Config->has_lock($conf, 'mounted')) {
+                       PVE::LXC::Config->check_lock($conf);
+                   }
 
-               run_command($cmd);
-
-               return;
+                   PVE::LXC::vm_stop($vmid, 1);
+               });
            };
 
            return $rpcenv->fork_worker('vzstop', $vmid, $authuser, $realcmd);
@@ -253,15 +298,16 @@ __PACKAGE__->register_method({
     method => 'POST',
     protected => 1,
     proxyto => 'node',
-    description => "Shutdown the container.",
+    description => "Shutdown the container. This will trigger a clean shutdown " .
+       "of the container, see lxc-stop(1) for details.",
     permissions => {
        check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
     },
     parameters => {
-       additionalProperties => 0,
+       additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
-           vmid => get_standard_option('pve-vmid'),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
            timeout => {
                description => "Wait maximal timeout seconds.",
                type => 'integer',
@@ -284,51 +330,42 @@ __PACKAGE__->register_method({
        my ($param) = @_;
 
        my $rpcenv = PVE::RPCEnvironment::get();
-
        my $authuser = $rpcenv->get_user();
 
        my $node = extract_param($param, 'node');
-
        my $vmid = extract_param($param, 'vmid');
 
-       my $timeout = extract_param($param, 'timeout');
+       my $timeout = extract_param($param, 'timeout') // 60;
 
        die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
 
-       my $realcmd = sub {
-           my $upid = shift;
-
-           syslog('info', "shutdown CT $vmid: $upid\n");
-
-           my $cmd = ['lxc-stop', '-n', $vmid];
-
-           $timeout = 60 if !defined($timeout);
+       if (PVE::HA::Config::vm_is_ha_managed($vmid) && $rpcenv->{type} ne 'ha') {
+           my $hacmd = sub {
+               my $upid = shift;
 
-           my $conf = PVE::LXC::load_config($vmid);
+               print "Requesting HA stop for CT $vmid\n";
 
-           my $storage_cfg = PVE::Storage::config();
+               my $cmd = ['ha-manager', 'crm-command', 'stop',  "ct:$vmid", "$timeout"];
+               PVE::Tools::run_command($cmd);
+           };
 
-           push @$cmd, '--timeout', $timeout;
+           return $rpcenv->fork_worker('hastop', $vmid, $authuser, $hacmd);
+       }
 
-           eval { run_command($cmd, timeout => $timeout+5); };
-           my $err = $@;
-           if ($err && $param->{forceStop}) {
-               $err = undef;
-               warn "shutdown failed - forcing stop now\n";
+       my $realcmd = sub {
+           my $upid = shift;
 
-               push @$cmd, '--kill';
-               run_command($cmd);
-               
-           }
+           PVE::LXC::Config->lock_config($vmid, sub {
+               syslog('info', "shutdown CT $vmid: $upid\n");
 
-           die $err if !$err;
+               my $conf = PVE::LXC::Config->load_config($vmid);
+               PVE::LXC::Config->check_lock($conf);
 
-           return;
+               PVE::LXC::vm_stop($vmid, 0, $timeout, $param->{forceStop});
+           });
        };
 
-       my $upid = $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
-
-       return $upid;
+       return $rpcenv->fork_worker('vzshutdown', $vmid, $authuser, $realcmd);
     }});
 
 __PACKAGE__->register_method({
@@ -337,48 +374,46 @@ __PACKAGE__->register_method({
     method => 'POST',
     protected => 1,
     proxyto => 'node',
-    description => "Suspend the container.",
+    description => "Suspend the container. This is experimental.",
     permissions => {
-        check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
+       check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
     },
     parameters => {
-        additionalProperties => 0,
-        properties => {
-            node => get_standard_option('pve-node'),
-            vmid => get_standard_option('pve-vmid'),
-        },
+       additionalProperties => 0,
+       properties => {
+           node => get_standard_option('pve-node'),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_running }),
+       },
     },
     returns => {
-        type => 'string',
+       type => 'string',
     },
     code => sub {
-        my ($param) = @_;
-
-        my $rpcenv = PVE::RPCEnvironment::get();
-
-        my $authuser = $rpcenv->get_user();
-
-        my $node = extract_param($param, 'node');
-
-        my $vmid = extract_param($param, 'vmid');
+       my ($param) = @_;
 
-        die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
+       my $rpcenv = PVE::RPCEnvironment::get();
+       my $authuser = $rpcenv->get_user();
 
-        my $realcmd = sub {
-            my $upid = shift;
+       my $node = extract_param($param, 'node');
+       my $vmid = extract_param($param, 'vmid');
 
-            syslog('info', "suspend CT $vmid: $upid\n");
+       die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
 
-           my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/liv/vz/dump'];
+       my $realcmd = sub {
+           my $upid = shift;
 
-           run_command($cmd);
+           PVE::LXC::Config->lock_config($vmid, sub {
+               syslog('info', "suspend CT $vmid: $upid\n");
 
-            return;
-        };
+               my $conf = PVE::LXC::Config->load_config($vmid);
+               PVE::LXC::Config->check_lock($conf);
 
-        my $upid = $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
+               my $cmd = ['lxc-checkpoint', '-n', $vmid, '-s', '-D', '/var/lib/vz/dump'];
+               run_command($cmd);
+           });
+       };
 
-        return $upid;
+       return $rpcenv->fork_worker('vzsuspend', $vmid, $authuser, $realcmd);
     }});
 
 __PACKAGE__->register_method({
@@ -392,44 +427,89 @@ __PACKAGE__->register_method({
         check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
     },
     parameters => {
-        additionalProperties => 0,
-        properties => {
-            node => get_standard_option('pve-node'),
-            vmid => get_standard_option('pve-vmid'),
-        },
+       additionalProperties => 0,
+       properties => {
+           node => get_standard_option('pve-node'),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid_stopped }),
+       },
     },
     returns => {
-        type => 'string',
+       type => 'string',
     },
     code => sub {
-        my ($param) = @_;
+       my ($param) = @_;
 
-        my $rpcenv = PVE::RPCEnvironment::get();
+       my $rpcenv = PVE::RPCEnvironment::get();
+       my $authuser = $rpcenv->get_user();
 
-        my $authuser = $rpcenv->get_user();
+       my $node = extract_param($param, 'node');
+       my $vmid = extract_param($param, 'vmid');
 
-        my $node = extract_param($param, 'node');
+       die "CT $vmid already running\n" if PVE::LXC::check_running($vmid);
 
-        my $vmid = extract_param($param, 'vmid');
+       my $realcmd = sub {
+           my $upid = shift;
 
-        die "CT $vmid already running\n" if PVE::LXC::check_running($vmid);
+           syslog('info', "resume CT $vmid: $upid\n");
 
-        my $realcmd = sub {
-            my $upid = shift;
+           my $cmd = ['lxc-checkpoint', '-n', $vmid, '-r', '--foreground', '-D', '/var/lib/vz/dump'];
+           run_command($cmd);
+       };
 
-            syslog('info', "resume CT $vmid: $upid\n");
+       my $upid = $rpcenv->fork_worker('vzresume', $vmid, $authuser, $realcmd);
 
-           my $cmd = ['lxc-checkpoint', '-n', $vmid, '-r', '--foreground',
-                      '-D', '/var/liv/vz/dump'];
+       return $upid;
+    }});
 
-           run_command($cmd);
+__PACKAGE__->register_method({
+    name => 'vm_reboot',
+    path => 'reboot',
+    method => 'POST',
+    protected => 1,
+    proxyto => 'node',
+    description => "Reboot the container by shutting it down, and starting it again. Applies pending changes.",
+    permissions => {
+       check => ['perm', '/vms/{vmid}', [ 'VM.PowerMgmt' ]],
+    },
+    parameters => {
+       additionalProperties => 0,
+       properties => {
+           node => get_standard_option('pve-node'),
+           vmid => get_standard_option('pve-vmid',
+                                       { completion => \&PVE::LXC::complete_ctid_running }),
+           timeout => {
+               description => "Wait maximal timeout seconds for the shutdown.",
+               type => 'integer',
+               minimum => 0,
+               optional => 1,
+           },
+       },
+    },
+    returns => {
+       type => 'string',
+    },
+    code => sub {
+       my ($param) = @_;
+
+       my $rpcenv = PVE::RPCEnvironment::get();
+       my $authuser = $rpcenv->get_user();
+
+       my $node = extract_param($param, 'node');
+       my $vmid = extract_param($param, 'vmid');
+
+       die "VM $vmid not running\n" if !PVE::LXC::check_running($vmid);
 
-            return;
-        };
+       my $realcmd = sub {
+           my $upid = shift;
 
-        my $upid = $rpcenv->fork_worker('vzresume', $vmid, $authuser, $realcmd);
+           syslog('info', "requesting reboot of CT $vmid: $upid\n");
+           PVE::LXC::vm_reboot($vmid, $param->{timeout});
+           return;
+       };
 
-        return $upid;
+       return $rpcenv->fork_worker('vzreboot', $vmid, $authuser, $realcmd);
     }});
 
+
+
 1;