]>
git.proxmox.com Git - pve-container.git/blob - src/PVE/API2/LXC/Snapshot.pm
1 package PVE
::API2
::LXC
::Snapshot
;
7 use PVE
::Tools
qw(extract_param run_command);
8 use PVE
::Exception
qw(raise raise_param_exc);
10 use PVE
::Cluster
qw(cfs_read_file);
11 use PVE
::AccessControl
;
13 use PVE
::GuestHelpers
;
16 use PVE
::RPCEnvironment
;
19 use PVE
::JSONSchema
qw(get_standard_option);
20 use base
qw(PVE::RESTHandler);
22 __PACKAGE__-
>register_method({
26 description
=> "List all snapshots.",
28 check
=> ['perm', '/vms/{vmid}', [ 'VM.Audit' ]],
31 protected
=> 1, # lxc pid files are only readable by root
33 additionalProperties
=> 0,
35 vmid
=> get_standard_option
('pve-vmid', { completion
=> \
&PVE
::LXC
::complete_ctid
}),
36 node
=> get_standard_option
('pve-node'),
45 description
=> "Snapshot identifier. Value 'current' identifies the current VM.",
49 description
=> "Snapshot description.",
53 description
=> "Snapshot creation time",
55 renderer
=> 'timestamp',
59 description
=> "Parent snapshot identifier.",
65 links
=> [ { rel
=> 'child', href
=> "{name}" } ],
70 my $vmid = $param->{vmid
};
72 my $conf = PVE
::LXC
::Config-
>load_config($vmid);
73 my $snaphash = $conf->{snapshots
} || {};
77 foreach my $name (keys %$snaphash) {
78 my $d = $snaphash->{$name};
81 snaptime
=> $d->{snaptime
} || 0,
82 description
=> $d->{description
} || '',
84 $item->{parent
} = $d->{parent
} if defined($d->{parent
});
85 $item->{snapstate
} = $d->{snapstate
} if $d->{snapstate
};
89 my $running = PVE
::LXC
::check_running
($vmid) ?
1 : 0;
92 digest
=> $conf->{digest
},
94 description
=> "You are here!",
96 $current->{parent
} = $conf->{parent
} if defined($conf->{parent
});
103 __PACKAGE__-
>register_method({
109 description
=> "Snapshot a container.",
111 check
=> ['perm', '/vms/{vmid}', [ 'VM.Snapshot' ]],
114 additionalProperties
=> 0,
116 node
=> get_standard_option
('pve-node'),
117 vmid
=> get_standard_option
('pve-vmid', { completion
=> \
&PVE
::LXC
::complete_ctid
}),
118 snapname
=> get_standard_option
('pve-snapshot-name'),
122 # description => "Save the vmstate",
127 description
=> "A textual description or comment.",
133 description
=> "the task ID.",
138 my $rpcenv = PVE
::RPCEnvironment
::get
();
140 my $authuser = $rpcenv->get_user();
142 my $node = extract_param
($param, 'node');
144 my $vmid = extract_param
($param, 'vmid');
146 my $snapname = extract_param
($param, 'snapname');
148 die "unable to use snapshot name 'current' (reserved name)\n"
149 if $snapname eq 'current';
151 die "unable to use snapshot name 'vzdump' (reserved name)\n"
152 if $snapname eq 'vzdump';
155 PVE
::Cluster
::log_msg
('info', $authuser, "snapshot container $vmid: $snapname");
156 PVE
::LXC
::Config-
>snapshot_create($vmid, $snapname, 0, $param->{description
});
159 return $rpcenv->fork_worker('vzsnapshot', $vmid, $authuser, $realcmd);
162 __PACKAGE__-
>register_method({
163 name
=> 'delsnapshot',
164 path
=> '{snapname}',
168 description
=> "Delete a LXC snapshot.",
170 check
=> ['perm', '/vms/{vmid}', [ 'VM.Snapshot' ]],
173 additionalProperties
=> 0,
175 node
=> get_standard_option
('pve-node'),
176 vmid
=> get_standard_option
('pve-vmid'),
177 snapname
=> get_standard_option
('pve-snapshot-name'),
181 description
=> "For removal from config file, even if removing disk snapshots fails.",
187 description
=> "the task ID.",
192 my $rpcenv = PVE
::RPCEnvironment
::get
();
194 my $authuser = $rpcenv->get_user();
196 my $node = extract_param
($param, 'node');
198 my $vmid = extract_param
($param, 'vmid');
200 my $snapname = extract_param
($param, 'snapname');
203 my $do_delete = sub {
205 PVE
::Cluster
::log_msg
('info', $authuser, "delete snapshot VM $vmid: $snapname");
206 PVE
::LXC
::Config-
>snapshot_delete($vmid, $snapname, $param->{force
});
210 if ($param->{force
}) {
213 eval { PVE
::GuestHelpers
::guest_migration_lock
($vmid, 10, $do_delete); };
215 die $err if $lock_obtained;
216 die "Failed to obtain guest migration lock - replication running?\n";
221 return $rpcenv->fork_worker('vzdelsnapshot', $vmid, $authuser, $realcmd);
224 __PACKAGE__-
>register_method({
225 name
=> 'snapshot_cmd_idx',
226 path
=> '{snapname}',
233 additionalProperties
=> 0,
235 vmid
=> get_standard_option
('pve-vmid'),
236 node
=> get_standard_option
('pve-node'),
237 snapname
=> get_standard_option
('pve-snapshot-name'),
246 links
=> [ { rel
=> 'child', href
=> "{cmd}" } ],
253 push @$res, { cmd
=> 'rollback' };
254 push @$res, { cmd
=> 'config' };
259 __PACKAGE__-
>register_method({
261 path
=> '{snapname}/rollback',
265 description
=> "Rollback LXC state to specified snapshot.",
267 check
=> ['perm', '/vms/{vmid}', [ 'VM.Snapshot', 'VM.Snapshot.Rollback' ], any
=> 1],
270 additionalProperties
=> 0,
272 node
=> get_standard_option
('pve-node'),
273 vmid
=> get_standard_option
('pve-vmid'),
274 snapname
=> get_standard_option
('pve-snapshot-name'),
277 description
=> "Whether the container should get started after rolling back successfully",
285 description
=> "the task ID.",
290 my $rpcenv = PVE
::RPCEnvironment
::get
();
292 my $authuser = $rpcenv->get_user();
294 my $node = extract_param
($param, 'node');
296 my $vmid = extract_param
($param, 'vmid');
298 my $snapname = extract_param
($param, 'snapname');
301 PVE
::Cluster
::log_msg
('info', $authuser, "rollback snapshot LXC $vmid: $snapname");
302 PVE
::LXC
::Config-
>snapshot_rollback($vmid, $snapname);
304 if ($param->{start
}) {
305 PVE
::API2
::LXC
::Status-
>vm_start({ vmid
=> $vmid, node
=> $node })
310 # hold migration lock, this makes sure that nobody create replication snapshots
311 return PVE
::GuestHelpers
::guest_migration_lock
($vmid, 10, $realcmd);
314 return $rpcenv->fork_worker('vzrollback', $vmid, $authuser, $worker);
317 __PACKAGE__-
>register_method({
318 name
=> 'update_snapshot_config',
319 path
=> '{snapname}/config',
323 description
=> "Update snapshot metadata.",
325 check
=> ['perm', '/vms/{vmid}', [ 'VM.Snapshot' ]],
328 additionalProperties
=> 0,
330 node
=> get_standard_option
('pve-node'),
331 vmid
=> get_standard_option
('pve-vmid'),
332 snapname
=> get_standard_option
('pve-snapshot-name'),
336 description
=> "A textual description or comment.",
340 returns
=> { type
=> 'null' },
344 my $rpcenv = PVE
::RPCEnvironment
::get
();
346 my $authuser = $rpcenv->get_user();
348 my $vmid = extract_param
($param, 'vmid');
350 my $snapname = extract_param
($param, 'snapname');
352 return undef if !defined($param->{description
});
356 my $conf = PVE
::LXC
::Config-
>load_config($vmid);
357 PVE
::LXC
::Config-
>check_lock($conf);
359 my $snap = $conf->{snapshots
}->{$snapname};
361 die "snapshot '$snapname' does not exist\n" if !defined($snap);
363 $snap->{description
} = $param->{description
} if defined($param->{description
});
365 PVE
::LXC
::Config-
>write_config($vmid, $conf, 1);
368 PVE
::LXC
::Config-
>lock_config($vmid, $updatefn);
373 __PACKAGE__-
>register_method({
374 name
=> 'get_snapshot_config',
375 path
=> '{snapname}/config',
378 description
=> "Get snapshot configuration",
380 check
=> ['perm', '/vms/{vmid}', [ 'VM.Snapshot', 'VM.Snapshot.Rollback', 'VM.Audit' ], any
=> 1],
383 additionalProperties
=> 0,
385 node
=> get_standard_option
('pve-node'),
386 vmid
=> get_standard_option
('pve-vmid'),
387 snapname
=> get_standard_option
('pve-snapshot-name'),
390 returns
=> { type
=> "object" },
394 my $rpcenv = PVE
::RPCEnvironment
::get
();
396 my $authuser = $rpcenv->get_user();
398 my $vmid = extract_param
($param, 'vmid');
400 my $snapname = extract_param
($param, 'snapname');
402 my $conf = PVE
::LXC
::Config-
>load_config($vmid);
404 my $snap = $conf->{snapshots
}->{$snapname};
406 die "snapshot '$snapname' does not exist\n" if !defined($snap);