You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by to...@apache.org on 2014/02/06 21:14:04 UTC

[3/6] git commit: LIBCLOUD-512: Added snapshot lifecycle support and fixture tests to support snapshot listing, creation and deletion.

LIBCLOUD-512: Added snapshot lifecycle support and fixture tests to support snapshot listing, creation and deletion.


Project: http://git-wip-us.apache.org/repos/asf/libcloud/repo
Commit: http://git-wip-us.apache.org/repos/asf/libcloud/commit/b064453d
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/b064453d
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/b064453d

Branch: refs/heads/trunk
Commit: b064453d8eb7db5fe673288c0d5dab62fe27e8cf
Parents: 8e36cb5
Author: Chris DeRamus <ch...@divvycloud.com>
Authored: Tue Feb 4 08:59:44 2014 -0500
Committer: Chris DeRamus <ch...@divvycloud.com>
Committed: Thu Feb 6 07:51:43 2014 -0500

----------------------------------------------------------------------
 libcloud/compute/drivers/openstack.py           | 81 +++++++++++++++++++-
 .../fixtures/openstack_v1.1/_os_snapshots.json  | 22 ++++++
 .../openstack_v1.1/_os_snapshots_create.json    | 11 +++
 libcloud/test/compute/test_openstack.py         | 38 +++++++++
 4 files changed, 151 insertions(+), 1 deletion(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/b064453d/libcloud/compute/drivers/openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/openstack.py b/libcloud/compute/drivers/openstack.py
index db5c7f1..8e28759 100644
--- a/libcloud/compute/drivers/openstack.py
+++ b/libcloud/compute/drivers/openstack.py
@@ -35,7 +35,8 @@ from libcloud.common.openstack import OpenStackBaseConnection
 from libcloud.common.openstack import OpenStackDriverMixin
 from libcloud.common.types import MalformedResponseError, ProviderError
 from libcloud.compute.base import NodeSize, NodeImage
-from libcloud.compute.base import NodeDriver, Node, NodeLocation, StorageVolume
+from libcloud.compute.base import (NodeDriver, Node, NodeLocation,
+                                   StorageVolume, VolumeSnapshot)
 from libcloud.compute.base import KeyPair
 from libcloud.compute.types import NodeState, Provider
 from libcloud.compute.types import KeyPairDoesNotExistError
@@ -1275,6 +1276,10 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
         volumes = obj['volumes']
         return [self._to_volume(volume) for volume in volumes]
 
+    def _to_snapshots(self, obj):
+        snapshots = obj['snapshots']
+        return [self._to_snapshot(snapshot) for snapshot in snapshots]
+
     def _to_sizes(self, obj):
         flavors = obj['flavors']
         return [self._to_size(flavor) for flavor in flavors]
@@ -1597,6 +1602,49 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
                                        method='POST', data=data).object
         return resp
 
+    def ex_list_snapshots(self):
+        return self._to_snapshots(
+            self.connection.request('/os-snapshots').object)
+
+    def ex_create_snapshot(self, volume, name, description=None, force=False):
+        """
+        Create a snapshot based off of a volume.
+
+        :param      node: volume
+        :type       node: :class:`StorageVolume`
+
+        :keyword    name: New name for the volume snapshot
+        :type       name: ``str``
+
+        :keyword    description: Description of the snapshot (optional)
+        :type       description: ``str``
+
+        :keyword    force: Whether to force creation (optional)
+        :type       force: ``bool``
+
+        :rtype:     :class:`VolumeSnapshot`
+        """
+        data = {'snapshot': {'display_name': name,
+                             'display_description': description,
+                             'volume_id': volume.id,
+                             'force': force}}
+
+        return self._to_snapshot(self.connection.request('/os-snapshots',
+                                                         method='POST',
+                                                         data=data).object)
+
+    def ex_delete_snapshot(self, snapshot):
+        """
+        Delete a VolumeSnapshot
+
+        :param      node: snapshot
+        :type       node: :class:`VolumeSnapshot`
+
+        :rtype:     ``bool``
+        """
+        return self.connection.request('/os-snapshots/%s' % snapshot.id,
+                                       method='DELETE').success()
+
     def _to_security_group_rules(self, obj):
         return [self._to_security_group_rule(security_group_rule) for
                 security_group_rule in obj]
@@ -1983,6 +2031,37 @@ class OpenStack_1_1_NodeDriver(OpenStackNodeDriver):
             }
         )
 
+    def _to_snapshot(self, api_node):
+        if 'snapshot' in api_node:
+            api_node = api_node['snapshot']
+
+        # RackSpace vs. OpenStack
+        if 'displayName' in api_node:
+            return VolumeSnapshot(
+                id=api_node['id'],
+                driver=self,
+                size=api_node['size'],
+                extra={
+                    'volume_id': api_node['volumeId'],
+                    'name': api_node['displayName'],
+                    'created': api_node['createdAt'],
+                    'description': api_node['displayDescription'],
+                    'status': api_node['status'],
+                })
+
+        else:
+            return VolumeSnapshot(
+                id=api_node['id'],
+                driver=self,
+                size=api_node['size'],
+                extra={
+                    'volume_id': api_node['volume_id'],
+                    'name': api_node['display_name'],
+                    'created': api_node['created_at'],
+                    'description': api_node['display_description'],
+                    'status': api_node['status'],
+                })
+
     def _to_size(self, api_flavor, price=None, bandwidth=None):
         # if provider-specific subclasses can get better values for
         # price/bandwidth, then can pass them in when they super().

http://git-wip-us.apache.org/repos/asf/libcloud/blob/b064453d/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json b/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json
new file mode 100644
index 0000000..032b553
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots.json
@@ -0,0 +1,22 @@
+{
+    "snapshots": [
+        {
+            "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+            "display_name": "snap-001",
+            "display_description": "Daily backup",
+            "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+            "status": "available",
+            "size": 30,
+            "created_at": "2012-02-29T03:50:07Z"
+        },
+        {
+            "id": "e479997c-650b-40a4-9dfe-77655818b0d2",
+            "display_name": "snap-002",
+            "display_description": "Weekly backup",
+            "volume_id": "76b8950a-8594-4e5b-8dce-0dfa9c696358",
+            "status": "available",
+            "size": 25,
+            "created_at": "2012-03-19T01:52:47Z"
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/b064453d/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json b/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json
new file mode 100644
index 0000000..e1059b5
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_v1.1/_os_snapshots_create.json
@@ -0,0 +1,11 @@
+{
+    "snapshot": {
+        "id": "3fbbcccf-d058-4502-8844-6feeffdf4cb5",
+        "display_name": "snap-001",
+        "display_description": "Daily backup",
+        "volume_id": "521752a6-acf6-4b2d-bc7a-119f9148cd8c",
+        "status": "available",
+        "size": 30,
+        "created_at": "2012-02-29T03:50:07Z"
+     }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/b064453d/libcloud/test/compute/test_openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py
index a249dfc..3b6c65f 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -1533,6 +1533,23 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
         expected_output = 'FAKE CONSOLE OUTPUT\nANOTHER\nLAST LINE'
         self.assertEqual(resp['output'], expected_output)
 
+    def test_ex_list_snapshots(self):
+        snapshots = self.driver.ex_list_snapshots()
+        self.assertEqual(len(snapshots), 2)
+        self.assertEqual(snapshots[0].extra['name'], 'snap-001')
+
+    def test_ex_create_snapshot(self):
+        volume = self.driver.list_volumes()[0]
+        ret = self.driver.ex_create_snapshot(volume,
+                                             'Test Volume',
+                                             'This is a test')
+        self.assertEqual(ret.id, '3fbbcccf-d058-4502-8844-6feeffdf4cb5')
+
+    def test_ex_delete_snapshot(self):
+        snapshot = self.driver.ex_list_snapshots()[0]
+        ret = self.driver.ex_delete_snapshot(snapshot)
+        self.assertTrue(ret is True)
+
 
 class OpenStack_1_1_FactoryMethodTests(OpenStack_1_1_Tests):
     should_list_locations = False
@@ -1871,6 +1888,7 @@ class OpenStack_1_1_MockHttp(MockHttpTestCase):
 
         return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
 
+<<<<<<< HEAD
     def _v1_1_slug_servers_12086_action(self, method, url, body, headers):
         if method == "POST":
             body = self.fixtures.load('_servers_12086_console_output.json')
@@ -1878,6 +1896,26 @@ class OpenStack_1_1_MockHttp(MockHttpTestCase):
         else:
             raise NotImplementedError()
 
+=======
+    def _v1_1_slug_os_snapshots(self, method, url, body, headers):
+        if method == "GET":
+            body = self.fixtures.load('_os_snapshots.json')
+        elif method == "POST":
+            body = self.fixtures.load('_os_snapshots_create.json')
+        else:
+            raise NotImplementedError()
+
+        return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+
+    def _v1_1_slug_os_snapshots_3fbbcccf_d058_4502_8844_6feeffdf4cb5(self, method, url, body, headers):
+        if method == "DELETE":
+            body = ''
+        else:
+            raise NotImplementedError()
+
+        return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+
+>>>>>>> LIBCLOUD-512: Added snapshot lifecycle support and fixture tests to support snapshot listing, creation and deletion.
 # This exists because the nova compute url in devstack has v2 in there but the v1.1 fixtures
 # work fine.