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/02/17 01:18:09 UTC

svn commit: r1071455 - in /incubator/libcloud/trunk: libcloud/drivers/ec2.py test/test_ec2.py

Author: tomaz
Date: Thu Feb 17 00:18:09 2011
New Revision: 1071455

URL: http://svn.apache.org/viewvc?rev=1071455&view=rev
Log:
Make describe_addresses more efficient when requesting Elastic IP addresses for
multiple nodes. It's still pretty bad for the worse case (user has a lot of
unassociated Elastic IP addresses), but it's a lot better for the average case
(multiple numbers of nodes with not a lot of unassociated addresses).

Modified:
    incubator/libcloud/trunk/libcloud/drivers/ec2.py
    incubator/libcloud/trunk/test/test_ec2.py

Modified: incubator/libcloud/trunk/libcloud/drivers/ec2.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/libcloud/drivers/ec2.py?rev=1071455&r1=1071454&r2=1071455&view=diff
==============================================================================
--- incubator/libcloud/trunk/libcloud/drivers/ec2.py (original)
+++ incubator/libcloud/trunk/libcloud/drivers/ec2.py Thu Feb 17 00:18:09 2011
@@ -399,11 +399,9 @@ class EC2NodeDriver(NodeDriver):
                         for g in self._findall(rs, 'groupSet/item/groupId')]
             nodes += self._to_nodes(rs, 'instancesSet/item', groups)
 
+        nodes_elastic_ips_mappings = self.ex_describe_addresses(nodes)
         for node in nodes:
-            elastic_ip_address = self.ex_describe_addresses(node)
-
-            if elastic_ip_address:
-                node.public_ip.extend(elastic_ip_address)
+            node.public_ip.extend(nodes_elastic_ips_mappings[node.id])
         return nodes
 
     def list_sizes(self, location=None):
@@ -638,28 +636,56 @@ class EC2NodeDriver(NodeDriver):
             tags[key] = value
         return tags
 
-    def ex_describe_addresses(self, node):
+    def ex_describe_addresses(self, nodes):
         """
-        Return a list of Elastic IP addresses associated with this node.
+        Return Elastic IP addresses for all the nodes in the provided list.
 
-        @type node: C{Node}
-        @param node: Node instance
+        @type nodes: C{list}
+        @param nodes: List of C{Node} instances
 
-        @return list Elastic IP addresses attached to this node.
+        @return dict Dictionary where a key is a node ID and the value is a
+                     list with the Elastic IP addresses associated with this node.
         """
-        params = { 'Action': 'DescribeAddresses',
-                   'Filter.0.Name': 'instance-id',
-                   'Filter.0.Value.0': node.id
-                 }
+        if not nodes:
+            return {}
+
+        params = { 'Action': 'DescribeAddresses' }
+
+        if len(nodes) == 1:
+           params.update({
+                  'Filter.0.Name': 'instance-id',
+                  'Filter.0.Value.0': nodes[0].id
+           })
 
         result = self.connection.request(self.path,
                                          params=params.copy()).object
 
-        ip_addresses = []
+        node_instance_ids = [ node.id for node in nodes ]
+        nodes_elastic_ip_mappings = {}
+
+        for node_id in node_instance_ids:
+            nodes_elastic_ip_mappings.setdefault(node_id, [])
         for element in self._findall(result, 'addressesSet/item'):
+            instance_id = self._findtext(element, 'instanceId')
             ip_address = self._findtext(element, 'publicIp')
-            ip_addresses.append(ip_address)
-        return ip_addresses
+
+            if instance_id not in node_instance_ids:
+                continue
+
+            nodes_elastic_ip_mappings[instance_id].append(ip_address)
+        return nodes_elastic_ip_mappings
+
+    def ex_describe_addresses_for_node(self, node):
+        """
+        Return a list of Elastic IP addresses associated with this node.
+
+        @type node: C{Node}
+        @param node: Node instance
+
+        @return list Elastic IP addresses attached to this node.
+        """
+        node_elastic_ips = self.ex_describe_addresses([node])
+        return node_elastic_ips[node.id]
 
     def create_node(self, **kwargs):
         """Create a new EC2 node

Modified: incubator/libcloud/trunk/test/test_ec2.py
URL: http://svn.apache.org/viewvc/incubator/libcloud/trunk/test/test_ec2.py?rev=1071455&r1=1071454&r2=1071455&view=diff
==============================================================================
--- incubator/libcloud/trunk/test/test_ec2.py (original)
+++ incubator/libcloud/trunk/test/test_ec2.py Thu Feb 17 00:18:09 2011
@@ -161,12 +161,26 @@ class EC2Tests(unittest.TestCase, TestCa
         self.assertTrue('owner' in tags)
         self.assertTrue('stack' in tags)
 
+    def test_ex_describe_addresses_for_node(self):
+        node1 = Node('i-4382922a', None, None, None, None, self.driver)
+        ip_addresses1 = self.driver.ex_describe_addresses_for_node(node1)
+        node2 = Node('i-4382922b', None, None, None, None, self.driver)
+        ip_addresses2 = sorted(self.driver.ex_describe_addresses_for_node(node2))
+
+        self.assertEqual(len(ip_addresses1), 1)
+        self.assertEqual(ip_addresses1[0], '1.2.3.4')
+
+        self.assertEqual(len(ip_addresses2), 2)
+        self.assertEqual(ip_addresses2[0], '1.2.3.5')
+        self.assertEqual(ip_addresses2[1], '1.2.3.6')
+
     def test_ex_describe_addresses(self):
         node = Node('i-4382922a', None, None, None, None, self.driver)
-        ip_addresses = self.driver.ex_describe_addresses(node)
+        nodes_elastic_ips = self.driver.ex_describe_addresses([node])
 
-        self.assertEqual(len(ip_addresses), 1)
-        self.assertEqual(ip_addresses[0], '1.2.3.4')
+        self.assertEqual(len(nodes_elastic_ips), 1)
+        self.assertTrue(node.id in nodes_elastic_ips)
+        self.assertEqual(nodes_elastic_ips[node.id], ['1.2.3.4'])
 
 
 class EC2MockHttp(MockHttp):
@@ -210,7 +224,7 @@ class EC2MockHttp(MockHttp):
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
     def _DescribeAddresses(self, method, url, body, headers):
-        body = self.fixtures.load('describe_addresses.xml')
+        body = self.fixtures.load('describe_addresses_multi.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])