You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@libcloud.apache.org by vd...@apache.org on 2018/12/04 08:54:19 UTC

[04/23] libcloud git commit: Move floatingips to neutron api LIBCLOUD-874

Move floatingips to neutron api LIBCLOUD-874


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

Branch: refs/heads/trunk
Commit: 84aa986ff8c21db2e547b22c117cbff3795204dd
Parents: 2b2e1f1
Author: micafer <mi...@upv.es>
Authored: Tue Sep 25 15:35:28 2018 +0200
Committer: Rick van de Loo <ri...@gmail.com>
Committed: Tue Dec 4 09:45:48 2018 +0100

----------------------------------------------------------------------
 libcloud/common/openstack.py                    |   5 +-
 libcloud/compute/drivers/openstack.py           | 122 ++++++++++++++++++-
 .../openstack_v1.1/_v2_0__floatingip.json       |  23 ++++
 .../openstack_v1.1/_v2_0__floatingips.json      |  52 ++++++++
 .../openstack_v1.1/_v2_0__networks_public.json  |  64 ++++++++++
 libcloud/test/compute/test_openstack.py         |  70 ++++++++++-
 6 files changed, 329 insertions(+), 7 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/libcloud/blob/84aa986f/libcloud/common/openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/common/openstack.py b/libcloud/common/openstack.py
index b64f669..db9f43f 100644
--- a/libcloud/common/openstack.py
+++ b/libcloud/common/openstack.py
@@ -390,8 +390,9 @@ class OpenStackResponse(Response):
             context = self.connection.context
             driver = self.connection.driver
             key_pair_name = context.get('key_pair_name', None)
-
-            if len(values) > 0 and values[0]['code'] == 404 and key_pair_name:
+            print(values)
+            if len(values) > 0 and 'code' in values[0] and \
+                    values[0]['code'] == 404 and key_pair_name:
                 raise KeyPairDoesNotExistError(name=key_pair_name,
                                                driver=driver)
             elif len(values) > 0 and 'message' in values[0]:

http://git-wip-us.apache.org/repos/asf/libcloud/blob/84aa986f/libcloud/compute/drivers/openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/compute/drivers/openstack.py b/libcloud/compute/drivers/openstack.py
index de6d445..fb92dab 100644
--- a/libcloud/compute/drivers/openstack.py
+++ b/libcloud/compute/drivers/openstack.py
@@ -59,6 +59,7 @@ __all__ = [
     'OpenStack_1_1_Connection',
     'OpenStack_1_1_NodeDriver',
     'OpenStack_1_1_FloatingIpPool',
+    'OpenStack_2_FloatingIpPool',
     'OpenStack_1_1_FloatingIpAddress',
     'OpenStack_2_PortInterfaceState',
     'OpenStack_2_PortInterface',
@@ -3255,10 +3256,29 @@ class OpenStack_2_NodeDriver(OpenStack_1_1_NodeDriver):
 
         :rtype: ``bool``
         """
-        resp = self.connection.request('/v2.0/security-group-rules/%s' %
-                                       (rule.id), method='DELETE')
+        resp = self.network_connection.request(
+            '/v2.0/security-group-rules/%s' % (rule.id), method='DELETE')
         return resp.status == httplib.NO_CONTENT
 
+    def _to_floating_ip_pool(self, obj):
+        return OpenStack_2_FloatingIpPool(obj['id'], obj['name'],
+                                          self.network_connection)
+
+    def _to_floating_ip_pools(self, obj):
+        pool_elements = obj['networks']
+        return [self._to_floating_ip_pool(pool) for pool in pool_elements]
+
+    def ex_list_floating_ip_pools(self):
+        """
+        List available floating IP pools
+
+        :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpPool`
+        """
+        return self._to_floating_ip_pools(
+            self.network_connection.request('/v2.0/networks?router:external'
+                                            '=True&fields=id&fields='
+                                            'name').object)
+
 
 class OpenStack_1_1_FloatingIpPool(object):
     """
@@ -3365,6 +3385,104 @@ class OpenStack_1_1_FloatingIpAddress(object):
                 % (self.id, self.ip_address, self.pool, self.driver))
 
 
+class OpenStack_2_FloatingIpPool(OpenStack_1_1_FloatingIpPool):
+    """
+    Floating IP Pool info.
+    """
+
+    def __init__(self, id, name, connection):
+        self.id = id
+        self.name = name
+        self.connection = connection
+
+    def _to_floating_ips(self, obj):
+        ip_elements = obj['floatingips']
+        return [self._to_floating_ip(ip) for ip in ip_elements]
+
+    def _to_floating_ip(self, obj):
+        instance_id = None
+
+        # In neutron version prior to 13.0.0 port_details does not exists
+        if 'port_details' not in obj and 'port_id' in obj:
+            port = self.connection.driver.ex_get_port(obj['port_id'])
+            if port:
+                obj['port_details'] = {"device_id": port.extra["device_id"],
+                                       "device_owner":
+                                           port.extra["device_owner"],
+                                       "mac_address":
+                                           port.extra["mac_address"]}
+
+        if 'port_details' in obj and obj['port_details']:
+            if obj['port_details']['device_owner'] == 'compute:nova':
+                instance_id = obj['port_details']['device_id']
+
+        ip_address = obj['floating_ip_address']
+        return OpenStack_1_1_FloatingIpAddress(id=obj['id'],
+                                               ip_address=ip_address,
+                                               pool=self,
+                                               node_id=instance_id,
+                                               driver=self.connection.driver)
+
+    def list_floating_ips(self):
+        """
+        List floating IPs in the pool
+
+        :rtype: ``list`` of :class:`OpenStack_1_1_FloatingIpAddress`
+        """
+        return self._to_floating_ips(
+            self.connection.request('/v2.0/floatingips').object)
+
+    def get_floating_ip(self, ip):
+        """
+        Get specified floating IP from the pool
+
+        :param      ip: floating IP to get
+        :type       ip: ``str``
+
+        :rtype: :class:`OpenStack_1_1_FloatingIpAddress`
+        """
+        floating_ips = self._to_floating_ips(
+            self.connection.request('/v2.0/floatingips?floating_ip_address'
+                                    '=%s' % ip).object)
+        return floating_ips[0]
+
+    def create_floating_ip(self):
+        """
+        Create new floating IP in the pool
+
+        :rtype: :class:`OpenStack_1_1_FloatingIpAddress`
+        """
+        resp = self.connection.request('/v2.0/floatingips',
+                                       method='POST',
+                                       data={'floatingip':
+                                             {'floating_network_id': self.id}}
+                                       )
+        data = resp.object['floatingip']
+        id = data['id']
+        ip_address = data['floating_ip_address']
+        return OpenStack_1_1_FloatingIpAddress(id=id,
+                                               ip_address=ip_address,
+                                               pool=self,
+                                               node_id=None,
+                                               driver=self.connection.driver)
+
+    def delete_floating_ip(self, ip):
+        """
+        Delete specified floating IP from the pool
+
+        :param      ip: floating IP to remove
+        :type       ip: :class:`OpenStack_1_1_FloatingIpAddress`
+
+        :rtype: ``bool``
+        """
+        resp = self.connection.request('/v2.0/floatingips/%s' % ip.id,
+                                       method='DELETE')
+        return resp.status in (httplib.NO_CONTENT, httplib.ACCEPTED)
+
+    def __repr__(self):
+        return ('<OpenStack_2_FloatingIpPool: name=%s>' % self.name)
+
+
 class OpenStack_2_SubNet(object):
     """
     A Virtual SubNet.

http://git-wip-us.apache.org/repos/asf/libcloud/blob/84aa986f/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingip.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingip.json b/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingip.json
new file mode 100644
index 0000000..0ef2ef5
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingip.json
@@ -0,0 +1,23 @@
+{
+    "floatingip": 
+    {
+        "router_id": null,
+        "description": "for test",
+        "dns_domain": "my-domain.org.",
+        "dns_name": "myfip2",
+        "created_at": "2016-12-21T11:55:50Z",
+        "updated_at": "2016-12-21T11:55:53Z",
+        "revision_number": 2,
+        "project_id": "4969c491a3c74ee4af974e6d800c62de",
+        "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+        "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+        "fixed_ip_address": null,
+        "floating_ip_address": "10.3.1.42",
+        "port_id": null,
+        "id": "09ea1784-2f81-46dc-8c91-244b4df75bde",
+        "status": "DOWN",
+        "port_details": null,
+        "tags": ["tag1,tag2"],
+        "port_forwardings": []
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/84aa986f/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingips.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingips.json b/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingips.json
new file mode 100644
index 0000000..fa71752
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__floatingips.json
@@ -0,0 +1,52 @@
+{
+    "floatingips": [
+        {
+            "router_id": null,
+            "description": "for test",
+            "dns_domain": "my-domain.org.",
+            "dns_name": "myfip2",
+            "created_at": "2016-12-21T11:55:50Z",
+            "updated_at": "2016-12-21T11:55:53Z",
+            "revision_number": 2,
+            "project_id": "4969c491a3c74ee4af974e6d800c62de",
+            "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+            "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+            "fixed_ip_address": null,
+            "floating_ip_address": "10.3.1.42",
+            "port_id": null,
+            "id": "09ea1784-2f81-46dc-8c91-244b4df75bde",
+            "status": "DOWN",
+            "port_details": null,
+            "tags": ["tag1,tag2"],
+            "port_forwardings": []
+        },
+        {
+            "router_id": "d23abc8d-2991-4a55-ba98-2aaea84cc72f",
+            "description": "for test",
+            "dns_domain": "my-domain.org.",
+            "dns_name": "myfip",
+            "created_at": "2016-12-21T10:55:50Z",
+            "updated_at": "2016-12-21T10:55:53Z",
+            "revision_number": 1,
+            "project_id": "4969c491a3c74ee4af974e6d800c62de",
+            "tenant_id": "4969c491a3c74ee4af974e6d800c62de",
+            "floating_network_id": "376da547-b977-4cfe-9cba-275c80debf57",
+            "fixed_ip_address": "10.0.0.3",
+            "floating_ip_address": "10.3.1.1",
+            "port_id": "ce705c24-c1ef-408a-bda3-7bbd946164ab",
+            "id": "04c5336a-0629-4694-ba30-04b0bdfa88a4",
+            "status": "ACTIVE",
+            "port_details": {
+                "status": "ACTIVE",
+                "name": "",
+                "admin_state_up": true,
+                "network_id": "02dd8479-ef26-4398-a102-d19d0a7b3a1f",
+                "device_owner": "compute:nova",
+                "mac_address": "fa:16:3e:b1:3b:30",
+                "device_id": "fcfc96da-19e2-40fd-8497-f29da1b21143"
+            },
+            "tags": ["tag1,tag2"],
+            "port_forwardings": []
+        }
+    ]
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/libcloud/blob/84aa986f/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks_public.json
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks_public.json b/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks_public.json
new file mode 100644
index 0000000..4ac5688
--- /dev/null
+++ b/libcloud/test/compute/fixtures/openstack_v1.1/_v2_0__networks_public.json
@@ -0,0 +1,64 @@
+{
+    "networks": [
+        {
+            "admin_state_up": true,
+            "availability_zone_hints": [],
+            "availability_zones": [
+                "nova"
+            ],
+            "created_at": "2016-03-08T20:19:41",
+            "dns_domain": "my-domain.org.",
+            "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
+            "ipv4_address_scope": null,
+            "ipv6_address_scope": null,
+            "l2_adjacency": false,
+            "mtu": 1500,
+            "name": "public",
+            "port_security_enabled": true,
+            "project_id": "4fd44f30292945e481c7b8a0c8908869",
+            "qos_policy_id": "6a8454ade84346f59e8d40665f878b2e",
+            "revision_number": 1,
+            "router:external": true,
+            "shared": false,
+            "status": "ACTIVE",
+            "subnets": [
+                "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
+            ],
+            "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
+            "updated_at": "2016-03-08T20:19:41",
+            "vlan_transparent": true,
+            "description": "",
+            "is_default": false
+        },
+        {
+            "admin_state_up": true,
+            "availability_zone_hints": [],
+            "availability_zones": [
+                "nova"
+            ],
+            "created_at": "2016-03-08T20:19:41",
+            "dns_domain": "my-domain.org.",
+            "id": "d32019d3-bc6e-4319-9c1d-6722fc136a22",
+            "ipv4_address_scope": null,
+            "ipv6_address_scope": null,
+            "l2_adjacency": false,
+            "mtu": 1500,
+            "name": "foobar",
+            "port_security_enabled": true,
+            "project_id": "4fd44f30292945e481c7b8a0c8908869",
+            "qos_policy_id": "6a8454ade84346f59e8d40665f878b2e",
+            "revision_number": 1,
+            "router:external": true,
+            "shared": false,
+            "status": "ACTIVE",
+            "subnets": [
+                "54d6f61d-db07-451c-9ab3-b9609b6b6f0b"
+            ],
+            "tenant_id": "4fd44f30292945e481c7b8a0c8908869",
+            "updated_at": "2016-03-08T20:19:41",
+            "vlan_transparent": true,
+            "description": "",
+            "is_default": false
+        }
+    ]
+}

http://git-wip-us.apache.org/repos/asf/libcloud/blob/84aa986f/libcloud/test/compute/test_openstack.py
----------------------------------------------------------------------
diff --git a/libcloud/test/compute/test_openstack.py b/libcloud/test/compute/test_openstack.py
index 3faea2b..db7b357 100644
--- a/libcloud/test/compute/test_openstack.py
+++ b/libcloud/test/compute/test_openstack.py
@@ -45,7 +45,7 @@ from libcloud.compute.drivers.openstack import (
     OpenStack_1_1_NodeDriver, OpenStackSecurityGroup,
     OpenStackSecurityGroupRule, OpenStack_1_1_FloatingIpPool,
     OpenStack_1_1_FloatingIpAddress, OpenStackKeyPair,
-    OpenStack_1_0_Connection,
+    OpenStack_1_0_Connection, OpenStack_2_FloatingIpPool,
     OpenStackNodeDriver,
     OpenStack_2_NodeDriver, OpenStack_2_PortInterfaceState, OpenStackNetwork)
 from libcloud.compute.base import Node, NodeImage, NodeSize
@@ -1399,6 +1399,53 @@ class OpenStack_1_1_Tests(unittest.TestCase, TestCaseMixin):
 
         self.assertEqual(pool.delete_floating_ip.call_count, 1)
 
+    def test_OpenStack_2_FloatingIpPool_list_floating_ips(self):
+        pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection)
+        ret = pool.list_floating_ips()
+
+        self.assertEqual(ret[0].id, '09ea1784-2f81-46dc-8c91-244b4df75bde')
+        self.assertEqual(ret[0].pool, pool)
+        self.assertEqual(ret[0].ip_address, '10.3.1.42')
+        self.assertEqual(ret[0].node_id, None)
+        self.assertEqual(ret[1].id, '04c5336a-0629-4694-ba30-04b0bdfa88a4')
+        self.assertEqual(ret[1].pool, pool)
+        self.assertEqual(ret[1].ip_address, '10.3.1.1')
+        self.assertEqual(
+            ret[1].node_id, 'fcfc96da-19e2-40fd-8497-f29da1b21143')
+
+    def test_OpenStack_2_FloatingIpPool_get_floating_ip(self):
+        pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection)
+        ret = pool.get_floating_ip('10.3.1.42')
+
+        self.assertEqual(ret.id, '09ea1784-2f81-46dc-8c91-244b4df75bde')
+        self.assertEqual(ret.pool, pool)
+        self.assertEqual(ret.ip_address, '10.3.1.42')
+        self.assertEqual(ret.node_id, None)
+
+    def test_OpenStack_2_FloatingIpPool_create_floating_ip(self):
+        pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection)
+        ret = pool.create_floating_ip()
+
+        self.assertEqual(ret.id, '09ea1784-2f81-46dc-8c91-244b4df75bde')
+        self.assertEqual(ret.pool, pool)
+        self.assertEqual(ret.ip_address, '10.3.1.42')
+        self.assertEqual(ret.node_id, None)
+
+    def test_OpenStack_2_FloatingIpPool_delete_floating_ip(self):
+        pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection)
+        ip = OpenStack_1_1_FloatingIpAddress('foo-bar-id', '42.42.42.42', pool)
+
+        self.assertTrue(pool.delete_floating_ip(ip))
+
+    def test_OpenStack_2_FloatingIpAddress_delete(self):
+        pool = OpenStack_2_FloatingIpPool(1, 'foo', self.driver.connection)
+        pool.delete_floating_ip = Mock()
+        ip = OpenStack_1_1_FloatingIpAddress('foo-bar-id', '42.42.42.42', pool)
+
+        ip.pool.delete_floating_ip()
+
+        self.assertEqual(pool.delete_floating_ip.call_count, 1)
+
     def test_ex_get_metadata_for_node(self):
         image = NodeImage(id=11, name='Ubuntu 8.10 (intrepid)', driver=self.driver)
         size = NodeSize(1, '256 slice', None, None, None, None, driver=self.driver)
@@ -2374,8 +2421,12 @@ class OpenStack_1_1_MockHttp(MockHttp, unittest.TestCase):
 
     def _v2_1337_v2_0_networks(self, method, url, body, headers):
         if method == 'GET':
-            body = self.fixtures.load('_v2_0__networks.json')
-            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+            if "router:external=True" in url:
+                body = self.fixtures.load('_v2_0__networks_public.json')
+                return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+            else:
+                body = self.fixtures.load('_v2_0__networks.json')
+                return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
         elif method == 'POST':
             body = self.fixtures.load('_v2_0__networks_POST.json')
             return (httplib.ACCEPTED, body, self.json_content_headers, httplib.responses[httplib.OK])
@@ -2453,6 +2504,19 @@ class OpenStack_1_1_MockHttp(MockHttp, unittest.TestCase):
             body = ''
             return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK])
 
+    def _v2_1337_v2_0_floatingips(self, method, url, body, headers):
+        if method == 'POST':
+            body = self.fixtures.load('_v2_0__floatingip.json')
+            return (httplib.CREATED, body, self.json_content_headers, httplib.responses[httplib.OK])
+        if method == 'GET':
+            body = self.fixtures.load('_v2_0__floatingips.json')
+            return (httplib.OK, body, self.json_content_headers, httplib.responses[httplib.OK])
+    
+    def _v2_1337_v2_0_floatingips_foo_bar_id(self, method, url, body, headers):
+        if method == 'DELETE':
+            body = ''
+            return (httplib.NO_CONTENT, body, self.json_content_headers, httplib.responses[httplib.OK])
+
 # This exists because the nova compute url in devstack has v2 in there but the v1.1 fixtures
 # work fine.