LIBCLOUD-525: Add VPC lifecycle support into the EC2 driver. This PR includes 
the ability to describe, create, delete, attach and detach VPC Internet 
gateways.

Closes #255

Signed-off-by: Tomaz Muraus <[email protected]>


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

Branch: refs/heads/trunk
Commit: 0cdc81fe6c8149409c28a9f77c889aba409870da
Parents: badc79a
Author: Chris DeRamus <[email protected]>
Authored: Sun Mar 2 09:43:27 2014 -0500
Committer: Tomaz Muraus <[email protected]>
Committed: Sun Mar 2 16:33:49 2014 +0100

----------------------------------------------------------------------
 libcloud/compute/drivers/ec2.py                 | 151 +++++++++++++++++++
 .../fixtures/ec2/attach_internet_gateway.xml    |   4 +
 .../fixtures/ec2/create_internet_gateway.xml    |   8 +
 .../fixtures/ec2/delete_internet_gateway.xml    |   4 +
 .../fixtures/ec2/describe_internet_gateways.xml |  20 +++
 .../fixtures/ec2/detach_internet_gateway.xml    |   4 +
 libcloud/test/compute/test_ec2.py               |  52 +++++++
 7 files changed, 243 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/0cdc81fe/libcloud/compute/drivers/ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/ec2.py b/libcloud/compute/drivers/ec2.py
index 6222657..58d0ce7 100644
--- a/libcloud/compute/drivers/ec2.py
+++ b/libcloud/compute/drivers/ec2.py
@@ -1171,6 +1171,24 @@ class ElasticIP(object):
                 % (self.ip, self.domain, self.instance_id))
 
 
+class VPCInternetGateway(object):
+    """
+    Class which stores information about VPC Internet Gateways.
+
+    Note: This class is VPC specific.
+    """
+
+    def __init__(self, id, name, vpc_id, state, driver, extra=None):
+        self.id = id
+        self.name = name
+        self.vpc_id = vpc_id
+        self.state = state
+        self.extra = extra or {}
+
+    def __repr__(self):
+        return (('<VPCInternetGateway: id=%s>') % (self.id))
+
+
 class BaseEC2NodeDriver(NodeDriver):
     """
     Base Amazon EC2 node driver.
@@ -3171,6 +3189,105 @@ class BaseEC2NodeDriver(NodeDriver):
 
         return result
 
+    def ex_list_internet_gateways(self):
+        """
+        Describes available Internet gateways and whether or not they are
+        attached to a VPC. These are required for VPC nodes to communicate
+        over the Internet.
+
+        :rtype: ``list`` of :class:`.VPCInternetGateway`
+        """
+        params = {'Action': 'DescribeInternetGateways'}
+
+        response = self.connection.request(self.path, params=params).object
+
+        return self._to_internet_gateways(response, 'internetGatewaySet/item')
+
+    def ex_create_internet_gateway(self, name=None):
+        """
+        Delete a VPC Internet gateway
+
+        :rtype:     ``bool``
+        """
+        params = {'Action': 'CreateInternetGateway'}
+
+        resp = self.connection.request(self.path, params=params).object
+
+        element = resp.findall(fixxpath(xpath='internetGateway',
+                                        namespace=NAMESPACE))
+
+        gateway = self._to_internet_gateway(element[0], name)
+
+        if name is not None:
+            self.ex_create_tags(gateway, {'Name': name})
+
+        return gateway
+
+    def ex_delete_internet_gateway(self, gateway):
+        """
+        Delete a VPC Internet gateway
+
+        :param      gateway: The gateway to delete
+        :type       gateway: :class:`.VPCInternetGateway`
+
+        :rtype:     ``bool``
+        """
+        params = {'Action': 'DeleteInternetGateway',
+                  'InternetGatewayId': gateway.id}
+
+        result = self.connection.request(self.path, params=params).object
+        element = findtext(element=result,
+                           xpath='return',
+                           namespace=NAMESPACE)
+
+        return element == 'true'
+
+    def ex_attach_internet_gateway(self, gateway, network):
+        """
+        Attach a Internet gateway to a VPC
+
+        :param      gateway: The gateway to attach
+        :type       gateway: :class:`.VPCInternetGateway`
+
+        :param      network: The VPC network to attach to
+        :type       network: :class:`.EC2Network`
+
+        :rtype:     ``bool``
+        """
+        params = {'Action': 'AttachInternetGateway',
+                  'InternetGatewayId': gateway.id,
+                  'VpcId': network.id}
+
+        result = self.connection.request(self.path, params=params).object
+        element = findtext(element=result,
+                           xpath='return',
+                           namespace=NAMESPACE)
+
+        return element == 'true'
+
+    def ex_detach_internet_gateway(self, gateway, network):
+        """
+        Detach a Internet gateway from a VPC
+
+        :param      gateway: The gateway to detach
+        :type       gateway: :class:`.VPCInternetGateway`
+
+        :param      network: The VPC network to detach from
+        :type       network: :class:`.EC2Network`
+
+        :rtype:     ``bool``
+        """
+        params = {'Action': 'DetachInternetGateway',
+                  'InternetGatewayId': gateway.id,
+                  'VpcId': network.id}
+
+        result = self.connection.request(self.path, params=params).object
+        element = findtext(element=result,
+                           xpath='return',
+                           namespace=NAMESPACE)
+
+        return element == 'true'
+
     def _to_nodes(self, object, xpath):
         return [self._to_node(el)
                 for el in object.findall(fixxpath(xpath=xpath,
@@ -3557,6 +3674,40 @@ class BaseEC2NodeDriver(NodeDriver):
 
         return mapping
 
+    def _to_internet_gateways(self, object, xpath):
+        return [self._to_internet_gateway(el)
+                for el in object.findall(fixxpath(xpath=xpath,
+                                                  namespace=NAMESPACE))]
+
+    def _to_internet_gateway(self, element, name=None):
+        id = findtext(element=element,
+                      xpath='internetGatewayId',
+                      namespace=NAMESPACE)
+
+        vpc_id = findtext(element=element,
+                          xpath='attachmentSet/item/vpcId',
+                          namespace=NAMESPACE)
+
+        state = findtext(element=element,
+                         xpath='attachmentSet/item/state',
+                         namespace=NAMESPACE)
+
+        # If there's no attachment state, let's
+        # set it to available
+        if not state:
+            state = 'available'
+
+        # Get our tags
+        tags = self._get_resource_tags(element)
+
+        # If name was not passed into the method then
+        # fall back then use the gateway id
+        name = name if name else tags.get('Name', id)
+
+        return VPCInternetGateway(id=id, name=name, vpc_id=vpc_id,
+                                  state=state, driver=self.connection.driver,
+                                  extra={'tags': tags})
+
     def _pathlist(self, key, arr):
         """
         Converts a key and an array of values into AWS query param format.

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0cdc81fe/libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml 
b/libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml
new file mode 100644
index 0000000..852ec39
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/attach_internet_gateway.xml
@@ -0,0 +1,4 @@
+<AttachInternetGatewayResponse 
xmlns="http://ec2.amazonaws.com/doc/2013-10-15/";>
+    <requestId>1eb45fd7-d4f6-4b63-a52f-54fc0c82617e</requestId>
+    <return>true</return>
+</AttachInternetGatewayResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0cdc81fe/libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml 
b/libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml
new file mode 100644
index 0000000..0891423
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/create_internet_gateway.xml
@@ -0,0 +1,8 @@
+<CreateInternetGatewayResponse 
xmlns="http://ec2.amazonaws.com/doc/2013-10-15/";>
+    <requestId>437b9824-8143-4583-98f7-0937d53aea83</requestId>
+    <internetGateway>
+        <internetGatewayId>igw-13ac2b36</internetGatewayId>
+        <attachmentSet/>
+        <tagSet/>
+    </internetGateway>
+</CreateInternetGatewayResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0cdc81fe/libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml 
b/libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml
new file mode 100644
index 0000000..619ab54
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/delete_internet_gateway.xml
@@ -0,0 +1,4 @@
+<DeleteInternetGatewayResponse 
xmlns="http://ec2.amazonaws.com/doc/2013-10-15/";>
+    <requestId>b1a5c8c9-91c7-43f3-8234-c162db89a2df</requestId>
+    <return>true</return>
+</DeleteInternetGatewayResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0cdc81fe/libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml 
b/libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml
new file mode 100644
index 0000000..44c7185
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/describe_internet_gateways.xml
@@ -0,0 +1,20 @@
+<DescribeInternetGatewaysResponse 
xmlns="http://ec2.amazonaws.com/doc/2013-10-15/";>
+    <requestId>843ff26c-f1ac-48f5-93a6-fa28f8abd9dd</requestId>
+    <internetGatewaySet>
+        <item>
+            <internetGatewayId>igw-84dd3ae1</internetGatewayId>
+            <attachmentSet/>
+            <tagSet/>
+        </item>
+        <item>
+            <internetGatewayId>igw-7fdae215</internetGatewayId>
+            <attachmentSet>
+                <item>
+                    <vpcId>vpc-62cad41e</vpcId>
+                    <state>available</state>
+                </item>
+            </attachmentSet>
+            <tagSet/>
+        </item>
+    </internetGatewaySet>
+</DescribeInternetGatewaysResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0cdc81fe/libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml 
b/libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml
new file mode 100644
index 0000000..8fa1e50
--- /dev/null
+++ b/libcloud/test/compute/fixtures/ec2/detach_internet_gateway.xml
@@ -0,0 +1,4 @@
+<DetachInternetGatewayResponse 
xmlns="http://ec2.amazonaws.com/doc/2013-10-15/";>
+    <requestId>7098cc6d-a984-4d34-a5ed-6ae1a645c0b6</requestId>
+    <return>true</return>
+</DetachInternetGatewayResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/0cdc81fe/libcloud/test/compute/test_ec2.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_ec2.py 
b/libcloud/test/compute/test_ec2.py
index 63f15aa..1a3cb20 100644
--- a/libcloud/test/compute/test_ec2.py
+++ b/libcloud/test/compute/test_ec2.py
@@ -995,6 +995,38 @@ class EC2Tests(LibcloudTestCase, TestCaseMixin):
         resp = self.driver.ex_detach_network_interface('eni-attach-2b588b47')
         self.assertTrue(resp)
 
+    def test_ex_list_internet_gateways(self):
+        gateways = self.driver.ex_list_internet_gateways()
+
+        self.assertEqual(len(gateways), 2)
+
+        self.assertEqual('igw-84dd3ae1', gateways[0].id)
+        self.assertEqual('igw-7fdae215', gateways[1].id)
+        self.assertEqual('available', gateways[1].state)
+        self.assertEqual('vpc-62cad41e', gateways[1].vpc_id)
+
+    def test_ex_create_internet_gateway(self):
+        gateway = self.driver.ex_create_internet_gateway()
+
+        self.assertEqual('igw-13ac2b36', gateway.id)
+
+    def test_ex_delete_internet_gateway(self):
+        gateway = self.driver.ex_list_internet_gateways()[0]
+        resp = self.driver.ex_delete_internet_gateway(gateway)
+        self.assertTrue(resp)
+
+    def test_ex_attach_internet_gateway(self):
+        gateway = self.driver.ex_list_internet_gateways()[0]
+        network = self.driver.ex_list_networks()[0]
+        resp = self.driver.ex_attach_internet_gateway(gateway, network)
+        self.assertTrue(resp)
+
+    def test_ex_detach_internet_gateway(self):
+        gateway = self.driver.ex_list_internet_gateways()[0]
+        network = self.driver.ex_list_networks()[0]
+        resp = self.driver.ex_detach_internet_gateway(gateway, network)
+        self.assertTrue(resp)
+
 
 class EC2USWest1Tests(EC2Tests):
     region = 'us-west-1'
@@ -1346,6 +1378,26 @@ class EC2MockHttp(MockHttpTestCase):
         body = self.fixtures.load('detach_network_interface.xml')
         return (httplib.OK, body, {}, httplib.responses[httplib.OK])
 
+    def _DescribeInternetGateways(self, method, url, body, headers):
+        body = self.fixtures.load('describe_internet_gateways.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _CreateInternetGateway(self, method, url, body, headers):
+        body = self.fixtures.load('create_internet_gateway.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _DeleteInternetGateway(self, method, url, body, headers):
+        body = self.fixtures.load('delete_internet_gateway.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _AttachInternetGateway(self, method, url, body, headers):
+        body = self.fixtures.load('attach_internet_gateway.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
+    def _DetachInternetGateway(self, method, url, body, headers):
+        body = self.fixtures.load('detach_internet_gateway.xml')
+        return (httplib.OK, body, {}, httplib.responses[httplib.OK])
+
 
 class EucMockHttp(EC2MockHttp):
     fixtures = ComputeFileFixtures('ec2')

Reply via email to