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 2011/11/16 16:05:19 UTC

svn commit: r1202734 - in /libcloud/trunk: ./ libcloud/compute/drivers/ test/compute/ test/compute/fixtures/ec2/

Author: tomaz
Date: Wed Nov 16 15:05:18 2011
New Revision: 1202734

URL: http://svn.apache.org/viewvc?rev=1202734&view=rev
Log:
Add the following extension methods to the EC2 compute driver:
ex_describe_all_addresses, ex_associate_addresses, ex_start_node,
ex_stop_node.

Added:
    libcloud/trunk/test/compute/fixtures/ec2/associate_address.xml
    libcloud/trunk/test/compute/fixtures/ec2/describe_addresses_all.xml
    libcloud/trunk/test/compute/fixtures/ec2/start_instances.xml
    libcloud/trunk/test/compute/fixtures/ec2/stop_instances.xml
Modified:
    libcloud/trunk/CHANGES
    libcloud/trunk/libcloud/compute/drivers/ec2.py
    libcloud/trunk/test/compute/test_ec2.py

Modified: libcloud/trunk/CHANGES
URL: http://svn.apache.org/viewvc/libcloud/trunk/CHANGES?rev=1202734&r1=1202733&r2=1202734&view=diff
==============================================================================
--- libcloud/trunk/CHANGES (original)
+++ libcloud/trunk/CHANGES Wed Nov 16 15:05:18 2011
@@ -7,6 +7,11 @@ Changes with Apache Libcloud in developm
        driver.
        [Tomaz Muraus]
 
+     - Add the following extension methods to the EC2 compute driver:
+       ex_describe_all_addresses, ex_associate_addresses, ex_start_node,
+       ex_stop_node.
+       [Suvish Vt]
+
 Changes with Apache Libcloud 0.6.2:
 
   *) General

Modified: libcloud/trunk/libcloud/compute/drivers/ec2.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/libcloud/compute/drivers/ec2.py?rev=1202734&r1=1202733&r2=1202734&view=diff
==============================================================================
--- libcloud/trunk/libcloud/compute/drivers/ec2.py (original)
+++ libcloud/trunk/libcloud/compute/drivers/ec2.py Wed Nov 16 15:05:18 2011
@@ -199,7 +199,7 @@ class EC2Response(AWSBaseResponse):
 
 class EC2Connection(ConnectionUserAndKey):
     """
-    Repersents a single connection to the EC2 Endpoint
+    Represents a single connection to the EC2 Endpoint
     """
 
     host = EC2_US_EAST_HOST
@@ -305,6 +305,16 @@ class EC2NodeDriver(NodeDriver):
         tag = "{%s}%s" % (NAMESPACE, 'return')
         return element.findtext(tag) == 'true'
 
+    def _get_state_boolean(self, element):
+        """
+        Checks for the instances's state
+        """
+        state = findall(element=element,
+                        xpath='instancesSet/item/currentState/name',
+                        namespace=NAMESPACE)[0].text
+
+        return state in ('stopping', 'pending', 'starting')
+
     def _get_terminate_boolean(self, element):
         status = element.findtext(".//{%s}%s" % (NAMESPACE, 'name'))
         return any([term_status == status
@@ -551,7 +561,7 @@ class EC2NodeDriver(NodeDriver):
             }
 
     def ex_describe_keypairs(self, name):
-        """Describes a keypiar by name
+        """Describes a keypair by name
 
         @note: This is a non-standard extension API, and only works for EC2.
 
@@ -756,6 +766,55 @@ class EC2NodeDriver(NodeDriver):
             'Filter.0.Value.0': node.id
         })
 
+    def ex_describe_all_addresses(self, only_allocated=False):
+        """
+        Return all the Elastic IP addresses for this account
+        optionally, return only the allocated addresses
+
+        @keyword  only_allocated: If true, return only those addresses
+                                  that are associated with an instance
+        @type     only_allocated: C{string}
+
+        @return   list list of elastic ips for this particular account.
+        """
+        params = {'Action': 'DescribeAddresses'}
+
+        result = self.connection.request(self.path,
+                                         params=params.copy()).object
+
+        # the list which we return
+        elastic_ip_addresses = []
+        for element in findall(element=result, xpath='addressesSet/item',
+                               namespace=NAMESPACE):
+            instance_id = findtext(element=element, xpath='instanceId',
+                                   namespace=NAMESPACE)
+
+            # if only allocated addresses are requested
+            if only_allocated and not instance_id:
+                continue
+
+            ip_address = findtext(element=element, xpath='publicIp',
+                                  namespace=NAMESPACE)
+
+            elastic_ip_addresses.append(ip_address)
+
+        return elastic_ip_addresses
+
+    def ex_associate_addresses(self, node, elastic_ip_address):
+        """
+        Associate an IP address with a particular node.
+
+        @type node: C{Node}
+        @param node: Node instance
+
+        """
+        params = {'Action': 'AssociateAddress'}
+
+        params.update(self._pathlist('InstanceId', [node.id]))
+        params.update({'PublicIp': elastic_ip_address})
+        res = self.connection.request(self.path, params=params).object
+        return self._get_boolean(res)
+
     def ex_describe_addresses(self, nodes):
         """
         Return Elastic IP addresses for all the nodes in the provided list.
@@ -943,6 +1002,26 @@ class EC2NodeDriver(NodeDriver):
         res = self.connection.request(self.path, params=params).object
         return self._get_boolean(res)
 
+    def ex_start_node(self, node):
+        """
+        Start the node by passing in the node object, does not work with
+        instance store backed instances
+        """
+        params = {'Action': 'StartInstances'}
+        params.update(self._pathlist('InstanceId', [node.id]))
+        res = self.connection.request(self.path, params=params).object
+        return self._get_state_boolean(res)
+
+    def ex_stop_node(self, node):
+        """
+        Stop the node by passing in the node object, does not work with
+        instance store backed instances
+        """
+        params = {'Action': 'StopInstances'}
+        params.update(self._pathlist('InstanceId', [node.id]))
+        res = self.connection.request(self.path, params=params).object
+        return self._get_state_boolean(res)
+
     def destroy_node(self, node):
         """
         Destroy node by passing in the node object

Added: libcloud/trunk/test/compute/fixtures/ec2/associate_address.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/ec2/associate_address.xml?rev=1202734&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/ec2/associate_address.xml (added)
+++ libcloud/trunk/test/compute/fixtures/ec2/associate_address.xml Wed Nov 16 15:05:18 2011
@@ -0,0 +1,4 @@
+<AssociateAddressResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/">
+    <requestId>1a470be4-b44d-4423-a80c-44ef2070b8be</requestId>
+    <return>true</return>
+</AssociateAddressResponse>

Added: libcloud/trunk/test/compute/fixtures/ec2/describe_addresses_all.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/ec2/describe_addresses_all.xml?rev=1202734&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/ec2/describe_addresses_all.xml (added)
+++ libcloud/trunk/test/compute/fixtures/ec2/describe_addresses_all.xml Wed Nov 16 15:05:18 2011
@@ -0,0 +1,17 @@
+<DescribeAddressesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/">
+  <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
+  <addressesSet>
+     <item>
+        <publicIp>1.2.3.4</publicIp>
+        <instanceId>i-4382922a</instanceId>
+     </item>
+     <item>
+        <publicIp>1.2.3.6</publicIp>
+        <instanceId>i-4382922b</instanceId>
+     </item>
+     <item>
+        <publicIp>1.2.3.5</publicIp>
+        <instanceId /> 
+     </item>
+</addressesSet>
+</DescribeAddressesResponse>

Added: libcloud/trunk/test/compute/fixtures/ec2/start_instances.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/ec2/start_instances.xml?rev=1202734&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/ec2/start_instances.xml (added)
+++ libcloud/trunk/test/compute/fixtures/ec2/start_instances.xml Wed Nov 16 15:05:18 2011
@@ -0,0 +1,17 @@
+<StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/">
+    <requestId>322f78ee-967b-40c9-aecd-8d442022da20</requestId>
+    <instancesSet>
+        <item>
+            <instanceId>i-ff5de6aa</instanceId>
+            <currentState>
+                <code>0</code>
+                <name>pending</name>
+            </currentState>
+            <previousState>
+                <code>80</code>
+                <name>stopped</name>
+            </previousState>
+        </item>
+    </instancesSet>
+</StartInstancesResponse>
+

Added: libcloud/trunk/test/compute/fixtures/ec2/stop_instances.xml
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/fixtures/ec2/stop_instances.xml?rev=1202734&view=auto
==============================================================================
--- libcloud/trunk/test/compute/fixtures/ec2/stop_instances.xml (added)
+++ libcloud/trunk/test/compute/fixtures/ec2/stop_instances.xml Wed Nov 16 15:05:18 2011
@@ -0,0 +1,16 @@
+<StopInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/">
+    <requestId>4ace6850-c876-4971-af0b-67a4278c36a1</requestId>
+    <instancesSet>
+        <item>
+            <instanceId>i-2ba64342</instanceId>
+            <currentState>
+                <code>64</code>
+                <name>stopping</name>
+            </currentState>
+            <previousState>
+                <code>16</code>
+                <name>running</name>
+            </previousState>
+        </item>
+    </instancesSet>
+</StopInstancesResponse>

Modified: libcloud/trunk/test/compute/test_ec2.py
URL: http://svn.apache.org/viewvc/libcloud/trunk/test/compute/test_ec2.py?rev=1202734&r1=1202733&r2=1202734&view=diff
==============================================================================
--- libcloud/trunk/test/compute/test_ec2.py (original)
+++ libcloud/trunk/test/compute/test_ec2.py Wed Nov 16 15:05:18 2011
@@ -125,6 +125,16 @@ class EC2Tests(LibcloudTestCase, TestCas
         ret = self.driver.reboot_node(node)
         self.assertTrue(ret)
 
+    def test_ex_start_node(self):
+        node = Node('i-4382922a', None, None, None, None, self.driver)
+        ret = self.driver.ex_start_node(node)
+        self.assertTrue(ret)
+
+    def test_ex_stop_node(self):
+        node = Node('i-4382922a', None, None, None, None, self.driver)
+        ret = self.driver.ex_stop_node(node)
+        self.assertTrue(ret)
+
     def test_destroy_node(self):
         node = Node('i-4382922a', None, None, None, None, self.driver)
         ret = self.driver.destroy_node(node)
@@ -228,6 +238,22 @@ class EC2Tests(LibcloudTestCase, TestCas
         self.assertTrue(node2.id in nodes_elastic_ips2)
         self.assertEqual(nodes_elastic_ips2[node2.id], [])
 
+    def test_ex_describe_all_addresses(self):
+        EC2MockHttp.type = 'all_addresses'
+        elastic_ips1 = self.driver.ex_describe_all_addresses()
+        elastic_ips2 = self.driver.ex_describe_all_addresses(only_allocated=True)
+
+        self.assertEqual(len(elastic_ips1), 3)
+        self.assertTrue('1.2.3.5' in elastic_ips1)
+
+        self.assertEqual(len(elastic_ips2), 2)
+        self.assertTrue('1.2.3.5' not in elastic_ips2)
+
+    def test_ex_associate_addresses(self):
+        node = Node('i-4382922a', None, None, None, None, self.driver)
+        ret = self.driver.ex_associate_addresses(node, '1.2.3.4')
+        self.assertTrue(ret)
+
     def test_ex_change_node_size_same_size(self):
         size = NodeSize('m1.small', 'Small Instance', None, None, None, None, driver=self.driver)
         node = Node('i-4382922a', None, None, None, None, self.driver,
@@ -269,6 +295,14 @@ class EC2MockHttp(MockHttp):
         body = self.fixtures.load('reboot_instances.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _StartInstances(self, method, url, body, headers):
+        body = self.fixtures.load('start_instances.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _StopInstances(self, method, url, body, headers):
+        body = self.fixtures.load('stop_instances.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
     def _DescribeImages(self, method, url, body, headers):
         body = self.fixtures.load('describe_images.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
@@ -305,6 +339,14 @@ class EC2MockHttp(MockHttp):
         body = self.fixtures.load('describe_addresses_multi.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _AssociateAddress(self, method, url, body, headers):
+        body = self.fixtures.load('associate_address.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _all_addresses_DescribeAddresses(self, method, url, body, headers):
+        body = self.fixtures.load('describe_addresses_all.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
     def _WITH_TAGS_DescribeAddresses(self, method, url, body, headers):
         body = self.fixtures.load('describe_addresses_multi.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])