]> git.proxmox.com Git - pve-container.git/blobdiff - src/PVE/API2/LXC/Snapshot.pm
fix #3424: api: snapshot delete: wait for active replication
[pve-container.git] / src / PVE / API2 / LXC / Snapshot.pm
index 3938d7d259fd8ceab184e854d87def715e5459a5..8d0319a1bba97cde05799d309ba78b84194381d9 100644 (file)
@@ -10,12 +10,12 @@ use PVE::INotify;
 use PVE::Cluster qw(cfs_read_file);
 use PVE::AccessControl;
 use PVE::Firewall;
+use PVE::GuestHelpers;
 use PVE::Storage;
 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);
 
@@ -32,7 +32,7 @@ __PACKAGE__->register_method({
     parameters => {
        additionalProperties => 0,
        properties => {
-           vmid => get_standard_option('pve-vmid'),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid }),
            node => get_standard_option('pve-node'),
        },
     },
@@ -40,7 +40,27 @@ __PACKAGE__->register_method({
        type => 'array',
        items => {
            type => "object",
-           properties => {},
+           properties => {
+               name => {
+                   description => "Snapshot identifier. Value 'current' identifies the current VM.",
+                   type => 'string',
+               },
+               description => {
+                   description => "Snapshot description.",
+                   type => 'string',
+               },
+               snaptime => {
+                   description => "Snapshot creation time",
+                   type => 'integer',
+                   renderer => 'timestamp',
+                   optional => 1,
+               },
+               parent => {
+                   description => "Parent snapshot identifier.",
+                   type => 'string',
+                   optional => 1,
+               },
+           },
        },
        links => [ { rel => 'child', href => "{name}" } ],
     },
@@ -49,7 +69,7 @@ __PACKAGE__->register_method({
 
        my $vmid = $param->{vmid};
 
-       my $conf = PVE::LXC::load_config($vmid);
+       my $conf = PVE::LXC::Config->load_config($vmid);
        my $snaphash = $conf->{snapshots} || {};
 
        my $res = [];
@@ -67,7 +87,12 @@ __PACKAGE__->register_method({
        }
 
        my $running = PVE::LXC::check_running($vmid) ? 1 : 0;
-       my $current = { name => 'current', digest => $conf->{digest}, running => $running };
+       my $current = {
+           name => 'current',
+           digest => $conf->{digest},
+           running => $running,
+           description => "You are here!",
+       };
        $current->{parent} = $conf->{parent} if defined($conf->{parent});
 
        push @$res, $current;
@@ -75,7 +100,6 @@ __PACKAGE__->register_method({
        return $res;
     }});
 
-use Data::Dumper; # fixme: remove
 __PACKAGE__->register_method({
     name => 'snapshot',
     path => '',
@@ -90,8 +114,8 @@ __PACKAGE__->register_method({
        additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
-           vmid => get_standard_option('pve-vmid'),
-           snapname => get_standard_option('pve-lxc-snapshot-name'),
+           vmid => get_standard_option('pve-vmid', { completion => \&PVE::LXC::complete_ctid }),
+           snapname => get_standard_option('pve-snapshot-name'),
 #          vmstate => {
 #              optional => 1,
 #              type => 'boolean',
@@ -124,12 +148,15 @@ __PACKAGE__->register_method({
        die "unable to use snapshot name 'current' (reserved name)\n"
            if $snapname eq 'current';
 
+       die "unable to use snapshot name 'vzdump' (reserved name)\n"
+           if $snapname eq 'vzdump';
+
        my $realcmd = sub {
            PVE::Cluster::log_msg('info', $authuser, "snapshot container $vmid: $snapname");
-           PVE::LXC::snapshot_create($vmid, $snapname, $param->{description});
+           PVE::LXC::Config->snapshot_create($vmid, $snapname, 0, $param->{description});
        };
 
-       return $rpcenv->fork_worker('pctsnapshot', $vmid, $authuser, $realcmd);
+       return $rpcenv->fork_worker('vzsnapshot', $vmid, $authuser, $realcmd);
     }});
 
 __PACKAGE__->register_method({
@@ -147,7 +174,7 @@ __PACKAGE__->register_method({
        properties => {
            node => get_standard_option('pve-node'),
            vmid => get_standard_option('pve-vmid'),
-           snapname => get_standard_option('pve-lxc-snapshot-name'),
+           snapname => get_standard_option('pve-snapshot-name'),
            force => {
                optional => 1,
                type => 'boolean',
@@ -172,12 +199,20 @@ __PACKAGE__->register_method({
 
        my $snapname = extract_param($param, 'snapname');
 
-       my $realcmd = sub {
+       my $do_delete = sub {
            PVE::Cluster::log_msg('info', $authuser, "delete snapshot VM $vmid: $snapname");
-           PVE::LXC::snapshot_delete($vmid, $snapname, $param->{force});
+           PVE::LXC::Config->snapshot_delete($vmid, $snapname, $param->{force});
        };
 
-       return $rpcenv->fork_worker('lxcdelsnapshot', $vmid, $authuser, $realcmd);
+       my $realcmd = sub {
+           if ($param->{force}) {
+               $do_delete->();
+           } else {
+               PVE::GuestHelpers::guest_migration_lock($vmid, 10, $do_delete);
+           }
+       };
+
+       return $rpcenv->fork_worker('vzdelsnapshot', $vmid, $authuser, $realcmd);
     }});
 
 __PACKAGE__->register_method({
@@ -193,7 +228,7 @@ __PACKAGE__->register_method({
        properties => {
            vmid => get_standard_option('pve-vmid'),
            node => get_standard_option('pve-node'),
-           snapname => get_standard_option('pve-lxc-snapshot-name'),
+           snapname => get_standard_option('pve-snapshot-name'),
        },
     },
     returns => {
@@ -223,14 +258,14 @@ __PACKAGE__->register_method({
     proxyto => 'node',
     description => "Rollback LXC state to specified snapshot.",
     permissions => {
-       check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot' ]],
+       check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot', 'VM.Snapshot.Rollback' ], any => 1],
     },
     parameters => {
        additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
            vmid => get_standard_option('pve-vmid'),
-           snapname => get_standard_option('pve-lxc-snapshot-name'),
+           snapname => get_standard_option('pve-snapshot-name'),
        },
     },
     returns => {
@@ -252,10 +287,15 @@ __PACKAGE__->register_method({
 
        my $realcmd = sub {
            PVE::Cluster::log_msg('info', $authuser, "rollback snapshot LXC $vmid: $snapname");
-           PVE::LXC::snapshot_rollback($vmid, $snapname);
+           PVE::LXC::Config->snapshot_rollback($vmid, $snapname);
        };
 
-       return $rpcenv->fork_worker('lxcrollback', $vmid, $authuser, $realcmd);
+       my $worker = sub {
+           # hold migration lock, this makes sure that nobody create replication snapshots
+           return PVE::GuestHelpers::guest_migration_lock($vmid, 10, $realcmd);
+       };
+
+       return $rpcenv->fork_worker('vzrollback', $vmid, $authuser, $worker);
     }});
 
 __PACKAGE__->register_method({
@@ -273,7 +313,7 @@ __PACKAGE__->register_method({
        properties => {
            node => get_standard_option('pve-node'),
            vmid => get_standard_option('pve-vmid'),
-           snapname => get_standard_option('pve-lxc-snapshot-name'),
+           snapname => get_standard_option('pve-snapshot-name'),
            description => {
                optional => 1,
                type => 'string',
@@ -297,8 +337,8 @@ __PACKAGE__->register_method({
 
        my $updatefn =  sub {
 
-           my $conf = PVE::LXC::load_config($vmid);
-           PVE::LXC::check_lock($conf);
+           my $conf = PVE::LXC::Config->load_config($vmid);
+           PVE::LXC::Config->check_lock($conf);
 
            my $snap = $conf->{snapshots}->{$snapname};
 
@@ -306,10 +346,10 @@ __PACKAGE__->register_method({
 
            $snap->{description} = $param->{description} if defined($param->{description});
 
-           PVE::LXC::write_config($vmid, $conf, 1);
+           PVE::LXC::Config->write_config($vmid, $conf, 1);
        };
 
-       PVE::LXC::lock_container($vmid, 10, $updatefn);
+       PVE::LXC::Config->lock_config($vmid, $updatefn);
 
        return undef;
     }});
@@ -321,14 +361,14 @@ __PACKAGE__->register_method({
     proxyto => 'node',
     description => "Get snapshot configuration",
     permissions => {
-       check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot' ]],
+       check => ['perm', '/vms/{vmid}', [ 'VM.Snapshot', 'VM.Snapshot.Rollback', 'VM.Audit' ], any => 1],
     },
     parameters => {
        additionalProperties => 0,
        properties => {
            node => get_standard_option('pve-node'),
            vmid => get_standard_option('pve-vmid'),
-           snapname => get_standard_option('pve-lxc-snapshot-name'),
+           snapname => get_standard_option('pve-snapshot-name'),
        },
     },
     returns => { type => "object" },
@@ -343,7 +383,7 @@ __PACKAGE__->register_method({
 
        my $snapname = extract_param($param, 'snapname');
 
-       my $conf = PVE::LXC::load_config($vmid);
+       my $conf = PVE::LXC::Config->load_config($vmid);
 
        my $snap = $conf->{snapshots}->{$snapname};