[Kimchi-devel] [PATCH v2 03/10] snapshot: Lookup a domain snapshot

Crístian Viana vianac at linux.vnet.ibm.com
Wed Nov 12 19:12:05 UTC 2014


A new command is added to look up an existing snapshot:

GET /vms/<vm-name>/snapshots/<snapshot-name>

It returns the following values:

* created: The time when the snapshot was created (in seconds, since the
    Unix Epoch);
* name: The snapshot name;
* parent: The name of the parent snapshot;
* state: The corresponding VM state when the snapshot was created
    (currently, it can only be 'shutoff');

Signed-off-by: Crístian Viana <vianac at linux.vnet.ibm.com>
---
 docs/API.md                     | 10 ++++++++++
 src/kimchi/i18n.py              |  2 ++
 src/kimchi/mockmodel.py         |  8 ++++++++
 src/kimchi/model/vmsnapshots.py | 43 +++++++++++++++++++++++++++++++++++++++++
 tests/test_rest.py              | 12 ++++++++++++
 5 files changed, 75 insertions(+)

diff --git a/docs/API.md b/docs/API.md
index fe1c3cf..44cc825 100644
--- a/docs/API.md
+++ b/docs/API.md
@@ -194,6 +194,16 @@ Represents a snapshot of the Virtual Machine's primary monitor.
     * name: The snapshot name (optional, defaults to a value based on the
             current time).
 
+### Sub-resource: Snapshot
+**URI:** /vms/*:name*/snapshots/*:snapshot*
+* **GET**: Retrieve snapshot information.
+    * created: The time when the snapshot was created
+               (in seconds, since the epoch).
+    * name: The snapshot name.
+    * parent: The name of the parent snapshot, or an empty string if there is
+              no parent.
+    * state: The corresponding domain's state when the snapshot was created.
+
 ### Collection: Templates
 
 **URI:** /templates
diff --git a/src/kimchi/i18n.py b/src/kimchi/i18n.py
index 9c37931..159a2d2 100644
--- a/src/kimchi/i18n.py
+++ b/src/kimchi/i18n.py
@@ -313,4 +313,6 @@ messages = {
 
     "KCHSNAP0001E": _("Virtual machine '%(vm)s' must be stopped before creating a snapshot on it."),
     "KCHSNAP0002E": _("Unable to create snapshot '%(name)s' on virtual machine '%(vm)s'. Details: %(err)s"),
+    "KCHSNAP0003E": _("Snapshot '%(name)s' does not exist on virtual machine '%(vm)s'."),
+    "KCHSNAP0004E": _("Unable to retrieve snapshot '%(name)s' on virtual machine '%(vm)s'. Details: %(err)s"),
 }
diff --git a/src/kimchi/mockmodel.py b/src/kimchi/mockmodel.py
index 211ae66..b6fb531 100644
--- a/src/kimchi/mockmodel.py
+++ b/src/kimchi/mockmodel.py
@@ -996,6 +996,14 @@ class MockModel(object):
 
         cb('OK', True)
 
+    def vmsnapshot_lookup(self, vm_name, name):
+        vm = self._get_vm(vm_name)
+
+        try:
+            return vm.snapshots[name].info
+        except KeyError:
+            raise NotFoundError('KCHSNAP0003E', {'vm': vm_name, 'name': name})
+
     def tasks_get_list(self):
         with self.objstore as session:
             return session.get_list('task')
diff --git a/src/kimchi/model/vmsnapshots.py b/src/kimchi/model/vmsnapshots.py
index 1512d9e..1ce6e9f 100644
--- a/src/kimchi/model/vmsnapshots.py
+++ b/src/kimchi/model/vmsnapshots.py
@@ -21,6 +21,7 @@ import time
 
 import libvirt
 import lxml.etree as ET
+from lxml import objectify
 from lxml.builder import E
 
 from kimchi.exception import InvalidOperation, NotFoundError, OperationFailed
@@ -89,3 +90,45 @@ class VMSnapshotsModel(object):
                                    'err': e.message})
 
         cb('OK', True)
+
+
+class VMSnapshotModel(object):
+    def __init__(self, **kargs):
+        self.conn = kargs['conn']
+
+    def lookup(self, vm_name, name):
+        vir_snap = self.get_vmsnapshot(vm_name, name)
+
+        try:
+            snap_xml_str = vir_snap.getXMLDesc(0).decode('utf-8')
+        except libvirt.libvirtError, e:
+            raise OperationFailed('KCHSNAP0004E', {'name': name,
+                                                   'vm': vm_name,
+                                                   'err': e.message})
+
+        snap_xml = objectify.fromstring(snap_xml_str)
+
+        try:
+            parent = unicode(snap_xml.parent.name)
+        except AttributeError:
+            parent = u''
+
+        return {'created': unicode(snap_xml.creationTime),
+                'name': unicode(snap_xml.name),
+                'parent': parent,
+                'state': unicode(snap_xml.state)}
+
+    def get_vmsnapshot(self, vm_name, name):
+        vir_dom = VMModel.get_vm(vm_name, self.conn)
+
+        try:
+            return vir_dom.snapshotLookupByName(name)
+        except libvirt.libvirtError, e:
+            code = e.get_error_code()
+            if code == libvirt.VIR_ERR_NO_DOMAIN_SNAPSHOT:
+                raise NotFoundError('KCHSNAP0003E', {'name': name,
+                                                     'vm': vm_name})
+            else:
+                raise OperationFailed('KCHSNAP0004E', {'name': name,
+                                                       'vm': vm_name,
+                                                       'err': e.message})
diff --git a/tests/test_rest.py b/tests/test_rest.py
index 7e6d684..e6ce715 100644
--- a/tests/test_rest.py
+++ b/tests/test_rest.py
@@ -396,6 +396,18 @@ class RestTests(unittest.TestCase):
         task = json.loads(self.request('/tasks/%s' % task['id']).read())
         self.assertEquals('finished', task['status'])
 
+        # Look up a snapshot
+        resp = self.request('/vms/test-vm/snapshots/foobar', '{}', 'GET')
+        self.assertEquals(404, resp.status)
+        resp = self.request('/vms/test-vm/snapshots/%s' % params['name'], '{}',
+                            'GET')
+        self.assertEquals(200, resp.status)
+        snap = json.loads(resp.read())
+        self.assertTrue(int(time.time()) >= int(snap['created']))
+        self.assertEquals(params['name'], snap['name'])
+        self.assertEquals(u'', snap['parent'])
+        self.assertEquals(u'shutoff', snap['state'])
+
         # Delete the VM
         resp = self.request('/vms/test-vm', '{}', 'DELETE')
         self.assertEquals(204, resp.status)
-- 
1.9.3




More information about the Kimchi-devel mailing list