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/01/13 00:10:35 UTC

[1/3] git commit: Issue LIBCLOUD-494: Add extension methods to support additional EC2 image calls. The first is ex_copy_image which is used to copy Amazon Machine Images between regions and the second is ex_create_image which can be used to create an AMI

Updated Branches:
  refs/heads/trunk edaff3f8d -> c3c90ac53


Issue LIBCLOUD-494: Add extension methods to support additional EC2 image
calls. The first is ex_copy_image which is used to copy Amazon Machine
Images between regions and the second is ex_create_image which can be
used to create an AMI from an EBS backed instance.

Closes #222.

Signed-off-by: Tomaz Muraus <to...@apache.org>


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

Branch: refs/heads/trunk
Commit: b81a63a88f11bd0fe1105be3868c915c69faba45
Parents: edaff3f
Author: Chris DeRamus <ch...@divvycloud.com>
Authored: Sun Jan 12 14:55:16 2014 -0500
Committer: Tomaz Muraus <to...@apache.org>
Committed: Sun Jan 12 23:53:23 2014 +0100

----------------------------------------------------------------------
 libcloud/compute/drivers/ec2.py                 | 132 +++++++++++++++++--
 .../test/compute/fixtures/ec2/copy_image.xml    |   4 +
 .../test/compute/fixtures/ec2/create_image.xml  |   4 +
 libcloud/test/compute/test_ec2.py               |  30 +++++
 4 files changed, 158 insertions(+), 12 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/b81a63a8/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index a226f88..176d450 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -1339,18 +1339,8 @@ class BaseEC2NodeDriver(NodeDriver):
             params['ClientToken'] = kwargs['ex_clienttoken']
 
         if 'ex_blockdevicemappings' in kwargs:
-            if not isinstance(kwargs['ex_blockdevicemappings'], (list, tuple)):
-                raise AttributeError(
-                    'ex_blockdevicemappings not list or tuple')
-
-            for idx, mapping in enumerate(kwargs['ex_blockdevicemappings']):
-                idx += 1  # we want 1-based indexes
-                if not isinstance(mapping, dict):
-                    raise AttributeError(
-                        'mapping %s in ex_blockdevicemappings '
-                        'not a dict' % mapping)
-                for k, v in mapping.items():
-                    params['BlockDeviceMapping.%d.%s' % (idx, k)] = str(v)
+            params.update(self._get_block_device_mapping_params(
+                          kwargs['ex_blockdevicemappings']))
 
         if 'ex_iamprofile' in kwargs:
             if not isinstance(kwargs['ex_iamprofile'], basestring):
@@ -1566,6 +1556,91 @@ class BaseEC2NodeDriver(NodeDriver):
                            namespace=NAMESPACE)
         return element == 'true'
 
+    def ex_copy_image(self, source_region, image, name=None, description=None):
+        """
+        Copy an Amazon Machine Image from the specified source region
+        to the current region.
+
+        :param      source_region: The region where the image resides
+        :type       source_region: ``str``
+
+        :param      image: Instance of class NodeImage
+        :type       image: :class:`NodeImage`
+
+        :param      name: The name of the new image
+        :type       name: ``str``
+
+        :param      description: The description of the new image
+        :type       description: ``str``
+
+        :return:    Instance of class ``NodeImage``
+        :rtype:     :class:`NodeImage`
+        """
+        params = {'Action': 'CopyImage',
+                  'SourceRegion': source_region,
+                  'SourceImageId':    image.id}
+
+        if name is not None:
+            params['Name'] = name
+
+        if description is not None:
+            params['Description'] = description
+
+        image = self._to_image(
+            self.connection.request(self.path, params=params).object)
+
+        return image
+
+    def ex_create_image_from_node(self, node, name, block_device_mapping,
+                                  reboot=False, description=None):
+        """
+        Create an Amazon Machine Image based off of an EBS-backed instance.
+
+        :param      node: Instance of ``Node``
+        :type       node: :class: `Node`
+
+        :param      name: The name for the new image
+        :type       name: ``str``
+
+        :param      block_device_mapping: A dictionary of the disk layout
+                                          An example of this dict is included
+                                          below.
+        :type       block_device_mapping: ``list`` of ``dict``
+
+        :param      reboot: Whether or not to shutdown the instance before
+                               creation. By default Amazon sets this to false
+                               to ensure a clean image.
+        :type       reboot: ``bool``
+
+        :param      description: An optional description for the new image
+        :type       description: ``str``
+
+        @note       An example block device mapping dictionary is included:
+                    mapping = [{'VirtualName': None,
+                                'Ebs': {'VolumeSize': 10,
+                                        'VolumeType': 'standard',
+                                        'DeleteOnTermination': 'true'},
+                                'DeviceName': '/dev/sda1'}]
+
+        :return:    Instance of class ``NodeImage``
+        :rtype:     :class:`NodeImage`
+        """
+        params = {'Action': 'CreateImage',
+                  'InstanceId': node.id,
+                  'Name': name,
+                  'Reboot': reboot}
+
+        if description is not None:
+            params['Description'] = description
+
+        params.update(self._get_block_device_mapping_params(
+                      block_device_mapping))
+
+        image = self._to_image(
+            self.connection.request(self.path, params=params).object)
+
+        return image
+
     def ex_destroy_image(self, image):
         params = {
             'Action': 'DeregisterImage',
@@ -3447,6 +3522,39 @@ class BaseEC2NodeDriver(NodeDriver):
 
         return tags
 
+    def _get_block_device_mapping_params(self, block_device_mapping):
+        """
+        Return a list of dictionaries with query parameters for
+        a valid block device mapping.
+
+        :param      mapping: List of dictionaries with the drive layout
+        :type       mapping: ``list`` or ``dict``
+
+        :return:    Dictionary representation of the drive mapping
+        :rtype:     ``dict``
+        """
+
+        if not isinstance(block_device_mapping, (list, tuple)):
+            raise AttributeError(
+                'block_device_mapping not list or tuple')
+
+        params = {}
+
+        for idx, mapping in enumerate(block_device_mapping):
+            idx += 1  # We want 1-based indexes
+            if not isinstance(mapping, dict):
+                raise AttributeError(
+                    'mapping %s in block_device_mapping '
+                    'not a dict' % mapping)
+            for k, v in mapping.items():
+                if not isinstance(v, dict):
+                    params['BlockDeviceMapping.%d.%s' % (idx, k)] = str(v)
+                else:
+                    for key, value in v.items():
+                        params['BlockDeviceMapping.%d.%s.%s'
+                               % (idx, k, key)] = str(value)
+        return params
+
     def _get_common_security_group_params(self, group_id, protocol,
                                           from_port, to_port, cidr_ips,
                                           group_pairs):

http://git-wip-us.apache.org/repos/asf/libcloud/blob/b81a63a8/libcloud/test/compute/fixtures/ec2/copy_image.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/copy_image.xml b/libcloud/test/compute/fixtures/ec2/copy_image.xml
new file mode 100644
index 0000000..f2e76b0
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/copy_image.xml
@@ -0,0 +1,4 @@
+<CopyImageResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
+    <requestId>7b7d87d5-c045-4c2c-a2c4-b538debe14b2</requestId>
+    <imageId>ami-4db38224</imageId>
+</CopyImageResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/b81a63a8/libcloud/test/compute/fixtures/ec2/create_image.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/create_image.xml b/libcloud/test/compute/fixtures/ec2/create_image.xml
new file mode 100644
index 0000000..1213f0a
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/create_image.xml
@@ -0,0 +1,4 @@
+<CreateImageResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
+    <requestId>3629ec66-c1f8-4b66-aac5-a8ad1cdf6c15</requestId>
+    <imageId>ami-e9b38280</imageId>
+</CreateImageResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/b81a63a8/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py
index d86af68..e0af93d 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -442,6 +442,28 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
 
         self.assertEqual(len(images), 2)
 
+    def test_ex_copy_image(self):
+        image = self.driver.list_images()[0]
+        resp = self.driver.ex_copy_image('us-east-1', image,
+                                         name='Faux Image',
+                                         description='Test Image Copy')
+        self.assertEqual(resp.id, 'ami-4db38224')
+
+    def test_ex_create_image_from_node(self):
+        node = self.driver.list_nodes()[0]
+
+        mapping = [{'VirtualName': None,
+                    'Ebs': {'VolumeSize': 10,
+                            'VolumeType': 'standard',
+                            'DeleteOnTermination': 'true'},
+                    'DeviceName': '/dev/sda1'}]
+
+        resp = self.driver.ex_create_image_from_node(node,
+                                                     'New Image',
+                                                     mapping,
+                                                     description='New EBS Image')
+        self.assertEqual(resp.id, 'ami-e9b38280')
+
     def ex_destroy_image(self):
         images = self.driver.list_images()
         image = images[0]
@@ -1222,6 +1244,14 @@ class EC2MockHttp(MockHttpTestCase):
         body = self.fixtures.load('delete_snapshot.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _CopyImage(self, method, url, body, headers):
+        body = self.fixtures.load('copy_image.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _CreateImage(self, method, url, body, headers):
+        body = self.fixtures.load('create_image.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
     def _DeregisterImage(self, method, url, body, headers):
         body = self.fixtures.load('deregister_image.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])


[3/3] git commit: Update CHANGES.

Posted by to...@apache.org.
Update CHANGES.


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

Branch: refs/heads/trunk
Commit: c3c90ac534ea22418d82abeb825caaeaee111a8f
Parents: 457da9f
Author: Tomaz Muraus <to...@apache.org>
Authored: Mon Jan 13 00:06:51 2014 +0100
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Jan 13 00:06:51 2014 +0100

----------------------------------------------------------------------
 CHANGES | 4 ++++
 1 file changed, 4 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/c3c90ac5/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 9a22b3f..df07e91 100644
--- a/CHANGES
+++ b/CHANGES
@@ -192,6 +192,10 @@ Changes with Apache Libcloud in development
      the Node object in the EC2 driver. (LIBCLOUD-493, GITHUB-221)
      [Chris DeRamus]
 
+   - Add ex_copy_image and ex_create_image_from_node method to the EC2 driver.
+     (LIBCLOUD-494, GITHUB-222)
+     [Chris DeRamus]
+
   *) Storage
 
     - Allow user to specify 'Content-Disposition' header in the CloudFiles


[2/3] git commit: Fix docstring issue which caused failed documentation build.

Posted by to...@apache.org.
Fix docstring issue which caused failed documentation build.


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

Branch: refs/heads/trunk
Commit: 457da9fb75f03431c6993b2c6270abcbbe9e42f9
Parents: b81a63a
Author: Tomaz Muraus <to...@apache.org>
Authored: Mon Jan 13 00:01:58 2014 +0100
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Jan 13 00:01:58 2014 +0100

----------------------------------------------------------------------
 libcloud/compute/drivers/ec2.py | 13 +++++++------
 1 file changed, 7 insertions(+), 6 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/457da9fb/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index 176d450..164fd88 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -1615,12 +1615,13 @@ class BaseEC2NodeDriver(NodeDriver):
         :param      description: An optional description for the new image
         :type       description: ``str``
 
-        @note       An example block device mapping dictionary is included:
-                    mapping = [{'VirtualName': None,
-                                'Ebs': {'VolumeSize': 10,
-                                        'VolumeType': 'standard',
-                                        'DeleteOnTermination': 'true'},
-                                'DeviceName': '/dev/sda1'}]
+        An example block device mapping dictionary is included:
+
+        mapping = [{'VirtualName': None,
+                    'Ebs': {'VolumeSize': 10,
+                            'VolumeType': 'standard',
+                            'DeleteOnTermination': 'true'},
+                            'DeviceName': '/dev/sda1'}]
 
         :return:    Instance of class ``NodeImage``
         :rtype:     :class:`NodeImage`