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 2013/12/30 13:33:25 UTC

[1/2] git commit: Issue LIBCLOUD-481: Store additional attributes (iops, tags, block_device_mapping) in the "extra" dictionary of the NodeImage object in the EC2 driver.

Updated Branches:
  refs/heads/trunk 58c1b6fc4 -> 369a16433


Issue LIBCLOUD-481: Store additional attributes (iops, tags,
block_device_mapping) in the   "extra" dictionary of the NodeImage object in
the EC2 driver.

Also fix ex_image_ids filtering in the list_images method.

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/c9e933b7
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/c9e933b7
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/c9e933b7

Branch: refs/heads/trunk
Commit: c9e933b7b32fc54bacece0c2ebee3913d591249e
Parents: 58c1b6f
Author: Chris DeRamus <ch...@divvycloud.com>
Authored: Sun Dec 29 09:37:34 2013 -0500
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Dec 30 00:11:53 2013 +0100

----------------------------------------------------------------------
 libcloud/compute/drivers/ec2.py                 | 191 +++++++++++++++----
 .../compute/fixtures/ec2/describe_images.xml    |  76 ++++++--
 .../ec2/describe_images_ex_imageids.xml         |  36 ++++
 libcloud/test/compute/test_ec2.py               |  37 +++-
 4 files changed, 278 insertions(+), 62 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/c9e933b7/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index 2011826..533a05c 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -819,49 +819,145 @@ class BaseEC2NodeDriver(NodeDriver):
         )
         return n
 
+    def _to_device_mappings(self, object):
+        return [self._to_device_mapping(el) for el in object.findall(
+            fixxpath(xpath='blockDeviceMapping/item', namespace=NAMESPACE))
+        ]
+
+    def _to_device_mapping(self, element):
+        """
+        Parse the XML element and return a dictionary of device properties.
+        Additional information can be found at http://goo.gl/GjWYBf.
+
+        @note: EBS volumes do not have a virtual name. Only ephemeral
+               disks use this property.
+        :rtype:     ``dict``
+        """
+        mapping = {}
+
+        mapping['device_name'] = findattr(element=element,
+                                          xpath='deviceName',
+                                          namespace=NAMESPACE)
+
+        mapping['virtual_name'] = findattr(element=element,
+                                           xpath='virtualName',
+                                           namespace=NAMESPACE)
+
+        # If virtual name does not exist then this is an EBS volume.
+        # Build the EBS dictionary leveraging the _get_extra_dict method.
+        if mapping['virtual_name'] is None:
+            # Build our attributes map
+            attributes_map = {
+                'snapshot_id': {
+                    'xpath': 'ebs/snapshotId',
+                    'transform_func': str
+                },
+                'volume_size': {
+                    'xpath': 'ebs/volumeSize',
+                    'transform_func': int
+                },
+                'delete': {
+                    'xpath': 'ebs/deleteOnTermination',
+                    'transform_func': str
+                },
+                'volume_type': {
+                    'xpath': 'ebs/volumeType',
+                    'transform_func': str
+                },
+                'iops': {
+                    'xpath': 'ebs/iops',
+                    'transform_func': int
+                }
+            }
+
+            mapping['ebs'] = self._get_extra_dict(element, attributes_map)
+
+        return mapping
+
     def _to_images(self, object):
         return [self._to_image(el) for el in object.findall(
             fixxpath(xpath='imagesSet/item', namespace=NAMESPACE))
         ]
 
     def _to_image(self, element):
-        n = NodeImage(
-            id=findtext(element=element, xpath='imageId', namespace=NAMESPACE),
-            name=findtext(element=element, xpath='imageLocation',
-                          namespace=NAMESPACE),
-            driver=self.connection.driver,
-            extra={
-                'state': findattr(element=element, xpath="imageState",
-                                  namespace=NAMESPACE),
-                'ownerid': findattr(element=element, xpath="imageOwnerId",
-                                    namespace=NAMESPACE),
-                'owneralias': findattr(element=element,
-                                       xpath="imageOwnerAlias",
-                                       namespace=NAMESPACE),
-                'ispublic': findattr(element=element,
-                                     xpath="isPublic",
-                                     namespace=NAMESPACE),
-                'architecture': findattr(element=element,
-                                         xpath="architecture",
-                                         namespace=NAMESPACE),
-                'imagetype': findattr(element=element,
-                                      xpath="imageType",
-                                      namespace=NAMESPACE),
-                'platform': findattr(element=element,
-                                     xpath="platform",
-                                     namespace=NAMESPACE),
-                'rootdevicetype': findattr(element=element,
-                                           xpath="rootDeviceType",
-                                           namespace=NAMESPACE),
-                'virtualizationtype': findattr(
-                    element=element, xpath="virtualizationType",
-                    namespace=NAMESPACE),
-                'hypervisor': findattr(element=element,
-                                       xpath="hypervisor",
-                                       namespace=NAMESPACE)
+
+        id = findtext(element=element, xpath='imageId', namespace=NAMESPACE)
+        name = findtext(element=element, xpath='name', namespace=NAMESPACE)
+
+        # Build block device mapping
+        block_device_mapping = self._to_device_mappings(element)
+
+        # Get our tags
+        tags = self._get_resource_tags(element)
+
+        # Build our extra attributes map
+        extra_attributes_map = {
+            'state': {
+                'xpath': 'imageState',
+                'transform_func': str
+            },
+            'owner_id': {
+                'xpath': 'imageOwnerId',
+                'transform_func': str
+            },
+            'owner_alias': {
+                'xpath': 'imageOwnerAlias',
+                'transform_func': str
+            },
+            'is_public': {
+                'xpath': 'isPublic',
+                'transform_func': str
+            },
+            'architecture': {
+                'xpath': 'architecture',
+                'transform_func': str
+            },
+            'image_type': {
+                'xpath': 'imageType',
+                'transform_func': str
+            },
+            'image_location': {
+                'xpath': 'imageLocation',
+                'transform_func': str
+            },
+            'platform': {
+                'xpath': 'platform',
+                'transform_func': str
+            },
+            'description': {
+                'xpath': 'description',
+                'transform_func': str
+            },
+            'root_device_type': {
+                'xpath': 'rootDeviceType',
+                'transform_func': str
+            },
+            'virtualization_type': {
+                'xpath': 'virtualizationType',
+                'transform_func': str
+            },
+            'hypervisor': {
+                'xpath': 'hypervisor',
+                'transform_func': str
+            },
+            'kernel_id': {
+                'xpath': 'kernelId',
+                'transform_func': str
+            },
+            'ramdisk_id': {
+                'xpath': 'ramdisk_id',
+                'transform_func': str
             }
-        )
-        return n
+        }
+
+        # Get our extra dictionary
+        extra = self._get_extra_dict(element, extra_attributes_map)
+
+        # Add our tags and block device mapping
+        extra['tags'] = tags
+        extra['block_device_mapping'] = block_device_mapping
+
+        return NodeImage(id=id, name=name, driver=self, extra=extra)
 
     def _to_volume(self, element, name=None):
         """
@@ -1146,7 +1242,8 @@ class BaseEC2NodeDriver(NodeDriver):
             sizes.append(NodeSize(driver=self, **attributes))
         return sizes
 
-    def list_images(self, location=None, ex_image_ids=None, ex_owner=None):
+    def list_images(self, location=None, ex_image_ids=None, ex_owner=None,
+                    ex_executableby=None):
         """
         List all images
 
@@ -1159,11 +1256,22 @@ class BaseEC2NodeDriver(NodeDriver):
         with the corresponding owner will be returned.
         Valid values: amazon|aws-marketplace|self|all|aws id
 
+        Ex_executableby parameter describes images for which
+        the specified user has explicit launch permissions.
+        The user can be an AWS account ID, self to return
+        images for which the sender of the request has
+        explicit launch permissions, or all to return
+        images with public launch permissions.
+        Valid values: all|self|aws id
+
         :param      ex_image_ids: List of ``NodeImage.id``
         :type       ex_image_ids: ``list`` of ``str``
 
         :param      ex_owner: Owner name
-        :type       ex_image_ids: ``str``
+        :type       ex_owner: ``str``
+
+        :param      ex_executableby: Executable by
+        :type       ex_executableby: ``str``
 
         :rtype: ``list`` of :class:`NodeImage`
         """
@@ -1172,8 +1280,13 @@ class BaseEC2NodeDriver(NodeDriver):
         if ex_owner:
             params.update({'Owner.1': ex_owner})
 
+        if ex_executableby:
+            params.update({'ExecutableBy.1': ex_executableby})
+
         if ex_image_ids:
-            params.update(self._pathlist('ImageId', ex_image_ids))
+            for index, image_id in enumerate(ex_image_ids):
+                index += 1
+                params.update({'ImageId.%s' % (index): image_id})
 
         images = self._to_images(
             self.connection.request(self.path, params=params).object

http://git-wip-us.apache.org/repos/asf/libcloud/blob/c9e933b7/libcloud/test/compute/fixtures/ec2/describe_images.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/describe_images.xml b/libcloud/test/compute/fixtures/ec2/describe_images.xml
index e99cbe7..03594e9 100644
--- a/libcloud/test/compute/fixtures/ec2/describe_images.xml
+++ b/libcloud/test/compute/fixtures/ec2/describe_images.xml
@@ -1,16 +1,62 @@
 <DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
-  <imagesSet>
-    <item>
-      <imageId>ami-be3adfd7</imageId>
-      <imageLocation>ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml</imageLocation>
-      <imageState>available</imageState>
-      <imageOwnerId>206029621532</imageOwnerId>
-      <isPublic>false</isPublic>
-      <architecture>i386</architecture>
-      <imageType>machine</imageType>
-      <kernelId>aki-4438dd2d</kernelId>
-      <ramdiskId>ari-4538dd2c</ramdiskId>
-    </item>
-  </imagesSet>
-</DescribeImagesResponse>
-
+    <requestId>73fac9c5-f6d2-4b45-846f-47adf1e82d6c</requestId>
+    <imagesSet>
+        <item>
+            <imageId>ami-57ba933a</imageId>
+            <imageLocation>123456788908/Test Image</imageLocation>
+            <imageState>available</imageState>
+            <imageOwnerId>123456788908</imageOwnerId>
+            <isPublic>false</isPublic>
+            <architecture>x86_64</architecture>
+            <imageType>machine</imageType>
+            <kernelId>aki-88aa75e1</kernelId>
+            <name>Test Image</name>
+            <description>Testing Stuff</description>
+            <rootDeviceType>ebs</rootDeviceType>
+            <rootDeviceName>/dev/sda1</rootDeviceName>
+            <blockDeviceMapping>
+                <item>
+                    <deviceName>/dev/sda1</deviceName>
+                    <ebs>
+                        <snapshotId>snap-88123ed9</snapshotId>
+                        <volumeSize>10</volumeSize>
+                        <deleteOnTermination>true</deleteOnTermination>
+                        <volumeType>standard</volumeType>
+                    </ebs>
+                </item>
+                <item>
+                    <deviceName>/dev/sda2</deviceName>
+                    <virtualName>ephemeral0</virtualName>
+                </item>
+            </blockDeviceMapping>
+            <virtualizationType>paravirtual</virtualizationType>
+            <hypervisor>xen</hypervisor>
+        </item>
+        <item>
+            <imageId>ami-85b2a8ae</imageId>
+            <imageLocation>123456788908/Test Image 2</imageLocation>
+            <imageState>available</imageState>
+            <imageOwnerId>123456788908</imageOwnerId>
+            <isPublic>false</isPublic>
+            <architecture>x86_64</architecture>
+            <imageType>machine</imageType>
+            <kernelId>aki-88aa75e1</kernelId>
+            <name>Test Image 2</name>
+            <rootDeviceType>ebs</rootDeviceType>
+            <rootDeviceName>/dev/sda1</rootDeviceName>
+            <blockDeviceMapping>
+                <item>
+                    <deviceName>/dev/sda1</deviceName>
+                    <ebs>
+                        <snapshotId>snap-c0bfbbdb</snapshotId>
+                        <volumeSize>20</volumeSize>
+                        <deleteOnTermination>false</deleteOnTermination>
+                        <volumeType>standard</volumeType>
+                    </ebs>
+                </item>
+            </blockDeviceMapping>
+            <virtualizationType>paravirtual</virtualizationType>
+            <hypervisor>xen</hypervisor>
+        </item>
+    </imagesSet>
+</DescribeImagesResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/c9e933b7/libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml b/libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml
new file mode 100644
index 0000000..47f2be0
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/describe_images_ex_imageids.xml
@@ -0,0 +1,36 @@
+<DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2013-10-15/">
+    <requestId>73fac9c5-f6d2-4b45-846f-47adf1e82d6c</requestId>
+    <imagesSet>
+        <item>
+            <imageId>ami-57ba933a</imageId>
+            <imageLocation>123456788908/Test Image</imageLocation>
+            <imageState>available</imageState>
+            <imageOwnerId>123456788908</imageOwnerId>
+            <isPublic>false</isPublic>
+            <architecture>x86_64</architecture>
+            <imageType>machine</imageType>
+            <kernelId>aki-88aa75e1</kernelId>
+            <name>Test Image</name>
+            <description>Testing Stuff</description>
+            <rootDeviceType>ebs</rootDeviceType>
+            <rootDeviceName>/dev/sda1</rootDeviceName>
+            <blockDeviceMapping>
+                <item>
+                    <deviceName>/dev/sda1</deviceName>
+                    <ebs>
+                        <snapshotId>snap-88123ed9</snapshotId>
+                        <volumeSize>10</volumeSize>
+                        <deleteOnTermination>true</deleteOnTermination>
+                        <volumeType>standard</volumeType>
+                    </ebs>
+                </item>
+                <item>
+                    <deviceName>/dev/sda2</deviceName>
+                    <virtualName>ephemeral0</virtualName>
+                </item>
+            </blockDeviceMapping>
+            <virtualizationType>paravirtual</virtualizationType>
+            <hypervisor>xen</hypervisor>
+        </item>
+    </imagesSet>
+</DescribeImagesResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/c9e933b7/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py b/libcloud/test/compute/test_ec2.py
index 81ac6bd..b68f944 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -411,19 +411,36 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
 
     def test_list_images(self):
         images = self.driver.list_images()
-        image = images[0]
 
-        name = 'ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml'
-        self.assertEqual(len(images), 1)
-        self.assertEqual(image.name, name)
-        self.assertEqual(image.id, 'ami-be3adfd7')
+        self.assertEqual(len(images), 2)
+        location = '123456788908/Test Image'
+        self.assertEqual(images[0].id, 'ami-57ba933a')
+        self.assertEqual(images[0].name, 'Test Image')
+        self.assertEqual(images[0].extra['image_location'], location)
+        self.assertEqual(images[0].extra['architecture'], 'x86_64')
+        self.assertEqual(len(images[0].extra['block_device_mapping']), 2)
+        ephemeral = images[0].extra['block_device_mapping'][1]['virtual_name']
+        self.assertEqual(ephemeral, 'ephemeral0')
+
+        location = '123456788908/Test Image 2'
+        self.assertEqual(images[1].id, 'ami-85b2a8ae')
+        self.assertEqual(images[1].name, 'Test Image 2')
+        self.assertEqual(images[1].extra['image_location'], location)
+        self.assertEqual(images[1].extra['architecture'], 'x86_64')
+        size = images[1].extra['block_device_mapping'][0]['ebs']['volume_size']
+        self.assertEqual(size, 20)
 
     def test_list_images_with_image_ids(self):
-        images = self.driver.list_images(ex_image_ids=['ami-be3adfd7'])
+        EC2MockHttp.type = 'ex_imageids'
+        images = self.driver.list_images(ex_image_ids=['ami-57ba933a'])
 
-        name = 'ec2-public-images/fedora-8-i386-base-v1.04.manifest.xml'
         self.assertEqual(len(images), 1)
-        self.assertEqual(images[0].name, name)
+        self.assertEqual(images[0].name, 'Test Image')
+
+    def test_list_images_with_executable_by(self):
+        images = self.driver.list_images(ex_executableby='self')
+
+        self.assertEqual(len(images), 2)
 
     def ex_destroy_image(self):
         images = self.driver.list_images()
@@ -968,6 +985,10 @@ class EC2MockHttp(MockHttpTestCase):
         body = self.fixtures.load('describe_images.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _ex_imageids_DescribeImages(self, method, url, body, headers):
+        body = self.fixtures.load('describe_images_ex_imageids.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
     def _RunInstances(self, method, url, body, headers):
         body = self.fixtures.load('run_instances.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])


[2/2] 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/369a1643
Tree: http://git-wip-us.apache.org/repos/asf/libcloud/tree/369a1643
Diff: http://git-wip-us.apache.org/repos/asf/libcloud/diff/369a1643

Branch: refs/heads/trunk
Commit: 369a16433bb541256a6c0303912613adaec99ad0
Parents: c9e933b
Author: Tomaz Muraus <to...@apache.org>
Authored: Mon Dec 30 13:32:49 2013 +0100
Committer: Tomaz Muraus <to...@apache.org>
Committed: Mon Dec 30 13:32:49 2013 +0100

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


http://git-wip-us.apache.org/repos/asf/libcloud/blob/369a1643/CHANGES
----------------------------------------------------------------------
diff --git a/CHANGES b/CHANGES
index 7d2c471..5854bae 100644
--- a/CHANGES
+++ b/CHANGES
@@ -146,6 +146,13 @@ Changes with Apache Libcloud in development
      now it's used as a Tag with a key "Name". (LIBCLOUD-480, GITHUB-214)
      [Chris DeRamus]
 
+   - Store additional attributes (iops, tags, block_device_mapping) in the 
+     "extra" dictionary of the NodeImage object in the EC2 driver.
+
+     Also fix ex_image_ids filtering in the list_images method.
+     (LIBCLOUD-481, GITHUB-215)
+     [Chris DeRamus]
+
   *) Storage
 
     - Allow user to specify 'Content-Disposition' header in the CloudFiles