]> git.proxmox.com Git - pve-container.git/blobdiff - src/PVE/API2/LXC.pm
CT protection mode
[pve-container.git] / src / PVE / API2 / LXC.pm
index 8431125b9f344b3b7c568cb89ba661aedb7921e6..085a69683792b2eda65f4b32f4419973f7c8d779 100644 (file)
@@ -15,6 +15,7 @@ use PVE::RESTHandler;
 use PVE::RPCEnvironment;
 use PVE::LXC;
 use PVE::LXC::Create;
+use PVE::LXC::Migrate;
 use PVE::API2::LXC::Config;
 use PVE::API2::LXC::Status;
 use PVE::API2::LXC::Snapshot;
@@ -43,54 +44,6 @@ __PACKAGE__->register_method ({
     subclass => "PVE::API2::Firewall::CT",
     path => '{vmid}/firewall',
 });
-my $alloc_rootfs = sub {
-    my ($storage_conf, $storage, $disk_size_gb, $vmid) = @_;
-
-    my $volid;
-
-    my $size = 4*1024*1024; # defaults to 4G
-
-    $size = int($disk_size_gb*1024) * 1024 if defined($disk_size_gb);
-
-    eval {
-       my $scfg = PVE::Storage::storage_config($storage_conf, $storage);
-       # fixme: use better naming ct-$vmid-disk-X.raw?
-
-       if ($scfg->{type} eq 'dir' || $scfg->{type} eq 'nfs') {
-           if ($size > 0) {
-               $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'raw',
-                                                  undef, $size);
-           } else {
-               $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'subvol',
-                                                  undef, 0);
-           }
-       } elsif ($scfg->{type} eq 'zfspool') {
-
-           $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'subvol',
-                                              undef, $size);
-       } elsif ($scfg->{type} eq 'drbd') {
-
-           $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'raw', undef, $size);
-
-       } elsif ($scfg->{type} eq 'rbd') {
-
-           die "krbd option must be enabled on storage type '$scfg->{type}'\n" if !$scfg->{krbd};
-           $volid = PVE::Storage::vdisk_alloc($storage_conf, $storage, $vmid, 'raw', undef, $size);
-
-       } else {
-           die "unable to create containers on storage type '$scfg->{type}'\n";
-       }
-    };
-    if (my $err = $@) {
-       # cleanup
-       eval { PVE::Storage::vdisk_free($storage_conf, $volid) if $volid; };
-       warn $@ if $@;
-       die $err;
-    }
-
-    return $volid;
-};
 
 __PACKAGE__->register_method({
     name => 'vmlist',
@@ -153,13 +106,14 @@ __PACKAGE__->register_method({
     proxyto => 'node',
     parameters => {
        additionalProperties => 0,
-       properties => PVE::LXC::json_config_properties_no_rootfs({
+       properties => PVE::LXC::json_config_properties({
            node => get_standard_option('pve-node'),
-           vmid => get_standard_option('pve-vmid'),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::Cluster::complete_next_vmid }),
            ostemplate => {
                description => "The OS template or backup file.",
                type => 'string',
                maxLength => 255,
+               completion => \&PVE::LXC::complete_os_templates,
            },
            password => {
                optional => 1,
@@ -168,17 +122,10 @@ __PACKAGE__->register_method({
                minLength => 5,
            },
            storage => get_standard_option('pve-storage-id', {
-               description => "Target storage.",
+               description => "Default Storage.",
                default => 'local',
                optional => 1,
            }),
-           size => {
-               optional => 1,
-               type => 'number',
-               description => "Amount of disk space for the VM in GB. A zero indicates no limits.",
-               minimum => 0,
-               default => 4,
-           },
            force => {
                optional => 1,
                type => 'boolean',
@@ -225,12 +172,13 @@ __PACKAGE__->register_method({
 
        if (!($same_container_exists && $restore && $force)) {
            PVE::Cluster::check_vmid_unused($vmid);
+       } else {
+           my $conf = PVE::LXC::load_config($vmid);
+           PVE::LXC::check_protection($conf, "unable to restore CT $vmid");
        }
 
        my $password = extract_param($param, 'password');
 
-       my $disksize = extract_param($param, 'size');
-
        my $storage = extract_param($param, 'storage') // 'local';
        
        my $storage_cfg = cfs_read_file("storage.cfg");
@@ -273,9 +221,8 @@ __PACKAGE__->register_method({
                if $rpcenv->{type} ne 'cli'; 
            die "pipe can only be used with restore tasks\n" 
                if !$restore;
-           die "pipe requires --size parameter\n" 
-               if !defined($disksize);
            $archive = '-';
+           die "restore from pipe requires rootfs parameter\n" if !defined($param->{rootfs});
        } else {
            $rpcenv->check_volume_access($authuser, $storage_cfg, $vmid, $ostemplate);
            $archive = PVE::Storage::abs_filesystem_path($storage_cfg, $ostemplate);
@@ -283,11 +230,21 @@ __PACKAGE__->register_method({
 
        my $conf = {};
 
-       PVE::LXC::update_pct_config($vmid, $conf, 0, $param);
+       my $no_disk_param = {};
+       foreach my $opt (keys %$param) {
+           my $value = $param->{$opt};
+           if ($opt eq 'rootfs' || $opt =~ m/^mp\d+$/) {
+               # allow to use simple numbers (add default storage in that case)
+               $param->{$opt} = "$storage:$value" if $value =~ m/^\d+(\.\d+)?$/;
+           } else {
+               $no_disk_param->{$opt} = $value;
+           }
+       }
+       PVE::LXC::update_pct_config($vmid, $conf, 0, $no_disk_param);
 
        my $check_vmid_usage = sub {
            if ($force) {
-               die "cant overwrite running container\n"
+               die "can't overwrite running container\n"
                    if PVE::LXC::check_running($vmid);
            } else {
                PVE::Cluster::check_vmid_unused($vmid);
@@ -298,36 +255,32 @@ __PACKAGE__->register_method({
            &$check_vmid_usage(); # final check after locking
                    
            PVE::Cluster::check_cfs_quorum();
-
-           my $volid;
+           my $vollist = [];
 
            eval {
-               if (!defined($disksize)) {
+               if (!defined($param->{rootfs})) {
                    if ($restore) {
-                       (undef, $disksize) = PVE::LXC::Create::recover_config($archive);
-                       die "unable to detect disk size - please specify with --size\n"
+                       my (undef, $disksize) = PVE::LXC::Create::recover_config($archive);
+                       $disksize /= 1024 * 1024 * 1024; # create_disks expects GB as unit size
+                       die "unable to detect disk size - please specify rootfs (size)\n"
                            if !$disksize;
+                       $param->{rootfs} = "$storage:$disksize";
                    } else {
-                       $disksize = 4;
+                       $param->{rootfs} = "$storage:4"; # defaults to 4GB
                    }
                }
-               $volid = &$alloc_rootfs($storage_cfg, $storage, $disksize, $vmid);
 
-               PVE::LXC::Create::create_rootfs($storage_cfg, $storage, $volid, $vmid, $conf,
-                                               $archive, $password, $restore);
-
-               $conf->{rootfs} = PVE::LXC::print_ct_mountpoint({volume => $volid, size => $disksize });
+               $vollist = PVE::LXC::create_disks($storage_cfg, $vmid, $param, $conf);
 
+               PVE::LXC::Create::create_rootfs($storage_cfg, $vmid, $conf, $archive, $password, $restore);
                # set some defaults
                $conf->{hostname} ||= "CT$vmid";
                $conf->{memory} ||= 512;
                $conf->{swap} //= 512;
-
                PVE::LXC::create_config($vmid, $conf);
            };
            if (my $err = $@) {
-               eval { PVE::Storage::vdisk_free($storage_cfg, $volid) if $volid; };
-               warn $@ if $@;
+               PVE::LXC::destroy_disks($storage_cfg, $vollist);
                PVE::LXC::destroy_config($vmid);
                die $err;
            }
@@ -493,7 +446,7 @@ __PACKAGE__->register_method({
        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 }),
        },
     },
     returns => {
@@ -513,6 +466,11 @@ __PACKAGE__->register_method({
 
        my $storage_cfg = cfs_read_file("storage.cfg");
 
+       PVE::LXC::check_protection($conf, "can't remove CT $vmid");
+
+       die "unable to remove CT $vmid - used in HA resources\n"
+           if PVE::HA::Config::vm_is_ha_managed($vmid);
+
        my $code = sub {
            # reload config after lock
            $conf = PVE::LXC::load_config($vmid);
@@ -593,7 +551,7 @@ __PACKAGE__->register_method ({
        my $remcmd = $remip ?
            ['/usr/bin/ssh', '-t', $remip] : [];
 
-       my $conf = PVE::LXC::load_config($vmid);
+       my $conf = PVE::LXC::load_config($vmid, $node);
        my $concmd = PVE::LXC::get_console_command($vmid, $conf);
 
        my $shcmd = [ '/usr/bin/dtach', '-A',
@@ -715,6 +673,9 @@ __PACKAGE__->register_method ({
        my $permissions = 'VM.Console';
 
        my $conf = PVE::LXC::load_config($vmid);
+
+       die "CT $vmid not running\n" if !PVE::LXC::check_running($vmid);
+
        my $concmd = PVE::LXC::get_console_command($vmid, $conf);
 
        my $shcmd = ['/usr/bin/dtach', '-A',
@@ -741,8 +702,11 @@ __PACKAGE__->register_method({
        additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
-           vmid => get_standard_option('pve-vmid'),
-           target => get_standard_option('pve-node', { description => "Target node." }),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid }),
+           target => get_standard_option('pve-node', {
+               description => "Target node.",
+               completion => \&PVE::Cluster::complete_migration_target,
+           }),
            online => {
                type => 'boolean',
                description => "Use online/live migration.",
@@ -779,7 +743,7 @@ __PACKAGE__->register_method({
 
        # try to detect errors early
        if (PVE::LXC::check_running($vmid)) {
-           die "cant migrate running container without --online\n"
+           die "can't migrate running container without --online\n"
                if !$param->{online};
        }
 
@@ -806,8 +770,7 @@ __PACKAGE__->register_method({
            my $realcmd = sub {
                my $upid = shift;
 
-               # fixme: implement lxc container migration
-               die "lxc container migration not implemented\n";
+               PVE::LXC::Migrate->migrate($target, $targetip, $vmid, $param);
 
                return;
            };
@@ -895,7 +858,7 @@ __PACKAGE__->register_method({
        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 }),
        },
     },
     returns => { type => 'null'},