[pve-devel] [PATCH 2/7] add qm snapshot command
Alexandre Derumier
aderumier at odiso.com
Thu Sep 6 10:33:35 CEST 2012
qm snapshot <vmid> <action> <snapshotname> --vmstate --freezefs
action : create|rollback|delete
vmstate : save the vmstate
freezefs: freezefs with qemu-ga
Signed-off-by: Alexandre Derumier <aderumier at odiso.com>
---
PVE/API2/Qemu.pm | 140 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
qm | 2 +
2 files changed, 142 insertions(+), 0 deletions(-)
diff --git a/PVE/API2/Qemu.pm b/PVE/API2/Qemu.pm
index bbb382f..079e522 100644
--- a/PVE/API2/Qemu.pm
+++ b/PVE/API2/Qemu.pm
@@ -1881,4 +1881,144 @@ __PACKAGE__->register_method({
return undef;
}});
+__PACKAGE__->register_method({
+ name => 'snapshot_vm',
+ path => '{vmid}/snapshot',
+ method => 'PUT',
+ protected => 1,
+ proxyto => 'node',
+ description => "Snapshot a VM.",
+ permissions => {
+ check => ['perm', '/vms/{vmid}', [ 'VM.Config.Disk' ]],
+ },
+ parameters => {
+ additionalProperties => 0,
+ properties => {
+ node => get_standard_option('pve-node'),
+ vmid => get_standard_option('pve-vmid'),
+ skiplock => get_standard_option('skiplock'),
+ action => {
+ type => 'string',
+ description => "Action",
+ enum => [ 'create', 'delete', 'rollback' ],
+ },
+ snapname => {
+ type => 'string',
+ description => "The name of the snapshot",
+ maxLength => 40,
+ },
+ vmstate => {
+ optional => 1,
+ type => 'boolean',
+ description => "Save the vmstate",
+ },
+ freezefs => {
+ optional => 1,
+ type => 'boolean',
+ description => "Freeze the filesystem",
+ },
+ digest => {
+ type => 'string',
+ description => 'Prevent changes if current configuration file has different SHA1 digest. This can be used to prevent concurrent modifications.',
+ maxLength => 40,
+ optional => 1,
+ },
+ },
+ },
+ returns => { type => 'null'},
+ 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 $digest = extract_param($param, 'digest');
+
+ my $action = extract_param($param, 'action');
+
+ my $snapname = extract_param($param, 'snapname');
+
+ my $vmstate = extract_param($param, 'vmstate');
+
+ my $freezefs = extract_param($param, 'freezefs');
+
+ my $skiplock = extract_param($param, 'skiplock');
+ raise_param_exc({ skiplock => "Only root may use this option." })
+ if $skiplock && $authuser ne 'root at pam';
+
+ my $storecfg = PVE::Storage::config();
+
+ my $updatefn = sub {
+
+ my $conf = PVE::QemuServer::load_config($vmid);
+
+ die "checksum missmatch (file change by other user?)\n"
+ if $digest && $digest ne $conf->{digest};
+ PVE::QemuServer::check_lock($conf) if !$skiplock;
+
+ &$check_storage_access($rpcenv, $authuser, $storecfg, $vmid, $conf);
+
+ #need to implement a check to see if all storages support snapshots
+
+ if($action eq 'create'){
+ PVE::Cluster::log_msg('info', $authuser, "snapshot VM $vmid: $snapname");
+
+ PVE::QemuServer::qemu_snapshot_start($vmid,$snapname) if $vmstate;
+
+ PVE::QemuServer::qga_freezefs($vmid) if $freezefs;
+
+ PVE::QemuServer::foreach_drive($conf, sub {
+ my ($ds, $drive) = @_;
+
+ return if PVE::QemuServer::drive_is_cdrom($drive);
+ my $volid = $drive->{file};
+ my $device = "drive-".$ds;
+ PVE::QemuServer::qemu_volume_snapshot($vmid, $device, $storecfg, $volid, $snapname);
+ });
+
+ PVE::QemuServer::gqa_unfreezefs($vmid) if $freezefs;
+
+ PVE::QemuServer::qemu_snapshot_end($vmid) if $vmstate;
+ }
+ elsif($action eq 'rollback'){
+
+ die "unable to rollback vm $vmid: vm is running\n"
+ if PVE::QemuServer::check_running($vmid);
+
+ PVE::QemuServer::foreach_drive($conf, sub {
+ my ($ds, $drive) = @_;
+
+ return if PVE::QemuServer::drive_is_cdrom($drive);
+ my $volid = $drive->{file};
+ my $device = "drive-".$ds;
+ PVE::QemuServer::qemu_volume_snapshot_rollback($vmid, $device, $storecfg, $volid, $snapname);
+ });
+
+ }
+ elsif($action eq 'delete'){
+
+ PVE::QemuServer::foreach_drive($conf, sub {
+ my ($ds, $drive) = @_;
+
+ return if PVE::QemuServer::drive_is_cdrom($drive);
+ my $volid = $drive->{file};
+ my $device = "drive-".$ds;
+ PVE::QemuServer::qemu_volume_snapshot_delete($vmid, $device, $storecfg, $volid, $snapname);
+ });
+
+ }
+
+ #need to implement config change with snapshots info
+ PVE::QemuServer::update_config_nolock($vmid, $conf, 1);
+ };
+
+ PVE::QemuServer::lock_config($vmid, $updatefn);
+ return undef;
+ }});
+
1;
diff --git a/qm b/qm
index 5e56eb9..e4fb361 100755
--- a/qm
+++ b/qm
@@ -433,6 +433,8 @@ my $cmddef = {
showcmd => [ __PACKAGE__, 'showcmd', ['vmid']],
+ snapshot => [ "PVE::API2::Qemu", 'snapshot_vm', ['vmid', 'action', 'snapname'], { node => $nodename } ],
+
status => [ __PACKAGE__, 'status', ['vmid']],
start => [ "PVE::API2::Qemu", 'vm_start', ['vmid'], { node => $nodename } , $upid_exit ],
--
1.7.2.5
More information about the pve-devel
mailing list