[Kimchi-devel] [PATCH 06/10] snapshot: Lookup current snapshot on a domain
Crístian Viana
vianac at linux.vnet.ibm.com
Wed Nov 12 13:08:44 UTC 2014
A new command is added to look up the current snapshot on a virtual
machine:
GET /vms/<vm-name>/snapshots/current
It returns a snapshot structure (as returned by 'GET
/vms/<vm-name>/snapshots/<snapshot-name>') of the current snapshot on
the specified virtual machine. If the VM doesn't have a current
snapshot, an exception will be returned.
Signed-off-by: Crístian Viana <vianac at linux.vnet.ibm.com>
---
docs/API.md | 4 ++++
src/kimchi/control/vm/snapshots.py | 13 +++++++++++++
src/kimchi/i18n.py | 2 ++
src/kimchi/mockmodel.py | 21 +++++++++++++++------
src/kimchi/model/vmsnapshots.py | 24 ++++++++++++++++++++++++
tests/test_rest.py | 17 +++++++++++++++++
6 files changed, 75 insertions(+), 6 deletions(-)
diff --git a/docs/API.md b/docs/API.md
index a6ca0c2..f4100c0 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -210,6 +210,10 @@ Represents a snapshot of the Virtual Machine's primary monitor.
will be deleted; if false, only the snapshot will be deleted
(optional, defaults to false).
+### Sub-resource: Current snapshot
+**URI:** /vms/*:name*/snapshots/current
+* **GET**: Retrieve current snapshot information for the virtual machine.
+
### Collection: Templates
**URI:** /templates
diff --git a/src/kimchi/control/vm/snapshots.py b/src/kimchi/control/vm/snapshots.py
index 5650435..d491015 100644
--- a/src/kimchi/control/vm/snapshots.py
+++ b/src/kimchi/control/vm/snapshots.py
@@ -29,6 +29,7 @@ class VMSnapshots(AsyncCollection):
self.vm = vm
self.resource_args = [self.vm, ]
self.model_args = [self.vm, ]
+ self.current = CurrentVMSnapshot(model, vm)
class VMSnapshot(Resource):
@@ -42,3 +43,15 @@ class VMSnapshot(Resource):
@property
def data(self):
return self.info
+
+
+class CurrentVMSnapshot(Resource):
+ def __init__(self, model, vm):
+ super(CurrentVMSnapshot, self).__init__(model)
+ self.vm = vm
+ self.model_args = [self.vm]
+ self.uri_fmt = '/vms/%s/snapshots/current'
+
+ @property
+ def data(self):
+ return self.info
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 6a1e193..b1b8060 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -317,4 +317,6 @@ messages = {
"KCHSNAP0004E": _("Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: %(err)s"),
"KCHSNAP0005E": _("Unable to list snapshots on virtual machine '%(vm)s'. Details: %(err)s"),
"KCHSNAP0006E": _("Unable to delete snapshot '%(name)s' on virtual machine '%(vm)s'. Details: %(err)s"),
+ "KCHSNAP0007E": _("Virtual machine '%(vm)s' does not have a current snapshot."),
+ "KCHSNAP0008E": _("Unable to retrieve current snapshot on virtual machine '%(vm)s'. Details: %(err)s"),
}
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
index 50c6e0c..33aaa33 100644
--- a/src/kimchi/mockmodel.py
+++ b/src/kimchi/mockmodel.py
@@ -987,12 +987,12 @@ class MockModel(object):
vm = self._get_vm(vm_name)
- parent = u''
- for sn, s in vm.snapshots.iteritems():
- if s.current:
- s.current = False
- parent = sn
- break
+ try:
+ parent = self.currentvmsnapshot_lookup(vm_name)['name']
+ except NotFoundError:
+ parent = u''
+ else:
+ vm.snapshots[parent].current = False
snap_info = {'parent': parent,
'state': vm.info['state']}
@@ -1004,6 +1004,15 @@ class MockModel(object):
vm = self._get_vm(vm_name)
return sorted(vm.snapshots.keys(), key=unicode.lower)
+ def currentvmsnapshot_lookup(self, vm_name):
+ vm = self._get_vm(vm_name)
+
+ for sn, s in vm.snapshots.iteritems():
+ if s.current:
+ return s.info
+
+ raise NotFoundError('KCHSNAP0007E', {'vm': vm_name})
+
def vmsnapshot_lookup(self, vm_name, name):
vm = self._get_vm(vm_name)
diff --git a/src/kimchi/model/vmsnapshots.py b/src/kimchi/model/vmsnapshots.py
index e02108d..8d6c296 100644
--- a/src/kimchi/model/vmsnapshots.py
+++ b/src/kimchi/model/vmsnapshots.py
@@ -156,3 +156,27 @@ class VMSnapshotModel(object):
raise OperationFailed('KCHSNAP0004E', {'name': name,
'vm': vm_name,
'err': e.message})
+
+
+class CurrentVMSnapshotModel(object):
+ def __init__(self, **kargs):
+ self.conn = kargs['conn']
+ self.vmsnapshot = VMSnapshotModel(**kargs)
+
+ def lookup(self, vm_name):
+ vir_dom = VMModel.get_vm(vm_name, self.conn)
+
+ try:
+ vir_snap = vir_dom.snapshotCurrent(0)
+ snap_name = vir_snap.getName().decode('utf-8')
+ except libvirt.libvirtError, e:
+ # If there is no current snapshot, "snapshotCurrent" raises an
+ # exception with the error code referenced below. In that case,
+ # return an empty dict.
+ if e.get_error_code() == libvirt.VIR_ERR_NO_DOMAIN_SNAPSHOT:
+ raise NotFoundError('KCHSNAP007E', {'vm': vm_name})
+
+ raise OperationFailed('KCHSNAP0008E',
+ {'vm': vm_name, 'err': e.message})
+
+ return self.vmsnapshot.lookup(vm_name, snap_name)
diff --git a/tests/test_rest.py b/tests/test_rest.py
index ef0fbf3..1129aec 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -386,6 +386,10 @@ class RestTests(unittest.TestCase):
self.assertEquals(original_vm_info, clone_vm_info)
+ # Look up current snapshot when there is no snapshot
+ resp = self.request('/vms/test-vm/snapshots/current', '{}', 'GET')
+ self.assertEquals(404, resp.status)
+
# Create a snapshot on a stopped VM
params = {'name': 'test-snap'}
resp = self.request('/vms/test-vm/snapshots', json.dumps(params),
@@ -413,9 +417,16 @@ class RestTests(unittest.TestCase):
snaps = json.loads(resp.read())
self.assertEquals(1, len(snaps))
+ # Look up current snapshot (the one created above)
+ resp = self.request('/vms/test-vm/snapshots/current', '{}', 'GET')
+ self.assertEquals(200, resp.status)
+ snap = json.loads(resp.read())
+ self.assertEquals(params['name'], snap['name'])
+
resp = self.request('/vms/test-vm/snapshots', '{}', 'POST')
self.assertEquals(202, resp.status)
task = json.loads(resp.read())
+ snap_name = task['target_uri'].split('/')[-1]
wait_task(self._task_lookup, task['id'])
resp = self.request('/tasks/%s' % task['id'], '{}', 'GET')
task = json.loads(resp.read())
@@ -426,6 +437,12 @@ class RestTests(unittest.TestCase):
snaps = json.loads(resp.read())
self.assertEquals(2, len(snaps))
+ # Look up current snapshot (the one created above)
+ resp = self.request('/vms/test-vm/snapshots/current', '{}', 'GET')
+ self.assertEquals(200, resp.status)
+ snap = json.loads(resp.read())
+ self.assertEquals(snap_name, snap['name'])
+
# Delete a snapshot
resp = self.request('/vms/test-vm/snapshots/foobar', '{}', 'DELETE')
self.assertEquals(404, resp.status)
--
1.9.3
More information about the Kimchi-devel
mailing list