diff --git a/kuryr_libnetwork/controllers.py b/kuryr_libnetwork/controllers.py index 84ec5b7a..14a1887a 100755 --- a/kuryr_libnetwork/controllers.py +++ b/kuryr_libnetwork/controllers.py @@ -569,6 +569,9 @@ def network_driver_create_network(): neutron_name = generic_options.get(const.NEUTRON_NAME_OPTION) pool_name = generic_options.get(const.NEUTRON_POOL_NAME_OPTION) + if not pool_name: + pool_name = lib_utils.get_neutron_subnetpool_name(pool_cidr) + if pool_name: pools = _get_subnetpools_by_attrs(name=pool_name) if pools: diff --git a/kuryr_libnetwork/tests/unit/test_kuryr.py b/kuryr_libnetwork/tests/unit/test_kuryr.py index 219d9ec5..4e4e6502 100644 --- a/kuryr_libnetwork/tests/unit/test_kuryr.py +++ b/kuryr_libnetwork/tests/unit/test_kuryr.py @@ -67,6 +67,31 @@ def test_network_driver_create_network(self): "admin_state_up": True } } + + network_request = { + 'NetworkID': docker_network_id, + 'IPv4Data': [{ + 'AddressSpace': 'foo', + 'Pool': '192.168.42.0/24', + 'Gateway': '192.168.42.1/24', + }], + 'IPv6Data': [{ + 'AddressSpace': 'bar', + 'Pool': 'fe80::/64', + 'Gateway': 'fe80::f816:3eff:fe20:57c3/64', + }], + 'Options': {} + } + + self.mox.StubOutWithMock(app.neutron, "list_subnetpools") + fake_kuryr_subnetpool_id = uuidutils.generate_uuid() + fake_name = lib_utils.get_neutron_subnetpool_name( + network_request['IPv4Data'][0]['Pool']) + kuryr_subnetpools = self._get_fake_v4_subnetpools( + fake_kuryr_subnetpool_id, name=fake_name) + app.neutron.list_subnetpools(name=fake_name).AndReturn( + {'subnetpools': kuryr_subnetpools['subnetpools']}) + # The following fake response is retrieved from the Neutron doc: # http://developer.openstack.org/api-ref-networking-v2.html#createNetwork # noqa fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" @@ -108,11 +133,13 @@ def test_network_driver_create_network(self): 'cidr': fake_cidr_v4, 'enable_dhcp': app.enable_dhcp, 'gateway_ip': '192.168.42.1', + 'subnetpool_id': fake_kuryr_subnetpool_id }] } subnet_v4_id = uuidutils.generate_uuid() fake_v4_subnet = self._get_fake_v4_subnet( fake_neutron_net_id, subnet_v4_id, + fake_kuryr_subnetpool_id, name=fake_cidr_v4, cidr=fake_cidr_v4) fake_subnet_response = { 'subnets': [ @@ -124,6 +151,16 @@ def test_network_driver_create_network(self): self.mox.ReplayAll() + response = self.app.post('/NetworkDriver.CreateNetwork', + content_type='application/json', + data=jsonutils.dumps(network_request)) + + self.assertEqual(200, response.status_code) + decoded_json = jsonutils.loads(response.data) + self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json) + + def test_network_driver_create_network_with_net_name_option(self): + docker_network_id = lib_utils.get_hash() network_request = { 'NetworkID': docker_network_id, 'IPv4Data': [{ @@ -136,18 +173,23 @@ def test_network_driver_create_network(self): 'Pool': 'fe80::/64', 'Gateway': 'fe80::f816:3eff:fe20:57c3/64', }], - 'Options': {} + 'Options': { + 'com.docker.network.enable_ipv6': False, + 'com.docker.network.generic': { + 'neutron.net.name': 'my_network_name' + } + } } - response = self.app.post('/NetworkDriver.CreateNetwork', - content_type='application/json', - data=jsonutils.dumps(network_request)) - self.assertEqual(200, response.status_code) - decoded_json = jsonutils.loads(response.data) - self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json) + self.mox.StubOutWithMock(app.neutron, "list_subnetpools") + fake_kuryr_subnetpool_id = uuidutils.generate_uuid() + fake_name = lib_utils.get_neutron_subnetpool_name( + network_request['IPv4Data'][0]['Pool']) + kuryr_subnetpools = self._get_fake_v4_subnetpools( + fake_kuryr_subnetpool_id, name=fake_name) + app.neutron.list_subnetpools(name=fake_name).AndReturn( + {'subnetpools': kuryr_subnetpools['subnetpools']}) - def test_network_driver_create_network_with_net_name_option(self): - docker_network_id = lib_utils.get_hash() fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" self.mox.StubOutWithMock(app.neutron, "list_networks") fake_neutron_net_name = 'my_network_name' @@ -193,11 +235,13 @@ def test_network_driver_create_network_with_net_name_option(self): 'cidr': fake_cidr_v4, 'enable_dhcp': app.enable_dhcp, 'gateway_ip': '192.168.42.1', + 'subnetpool_id': fake_kuryr_subnetpool_id }] } subnet_v4_id = uuidutils.generate_uuid() fake_v4_subnet = self._get_fake_v4_subnet( fake_neutron_net_id, subnet_v4_id, + fake_kuryr_subnetpool_id, name=fake_cidr_v4, cidr=fake_cidr_v4) fake_subnet_response = { 'subnets': [ @@ -209,6 +253,17 @@ def test_network_driver_create_network_with_net_name_option(self): self.mox.ReplayAll() + response = self.app.post('/NetworkDriver.CreateNetwork', + content_type='application/json', + data=jsonutils.dumps(network_request)) + + self.assertEqual(200, response.status_code) + decoded_json = jsonutils.loads(response.data) + self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json) + + def test_network_driver_create_network_with_netid_option(self): + docker_network_id = lib_utils.get_hash() + fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" network_request = { 'NetworkID': docker_network_id, 'IPv4Data': [{ @@ -224,21 +279,20 @@ def test_network_driver_create_network_with_net_name_option(self): 'Options': { 'com.docker.network.enable_ipv6': False, 'com.docker.network.generic': { - 'neutron.net.name': 'my_network_name' + 'neutron.net.uuid': fake_neutron_net_id } } } - response = self.app.post('/NetworkDriver.CreateNetwork', - content_type='application/json', - data=jsonutils.dumps(network_request)) - self.assertEqual(200, response.status_code) - decoded_json = jsonutils.loads(response.data) - self.assertEqual(constants.SCHEMA['SUCCESS'], decoded_json) + self.mox.StubOutWithMock(app.neutron, "list_subnetpools") + fake_kuryr_subnetpool_id = uuidutils.generate_uuid() + fake_name = lib_utils.get_neutron_subnetpool_name( + network_request['IPv4Data'][0]['Pool']) + kuryr_subnetpools = self._get_fake_v4_subnetpools( + fake_kuryr_subnetpool_id, name=fake_name) + app.neutron.list_subnetpools(name=fake_name).AndReturn( + {'subnetpools': kuryr_subnetpools['subnetpools']}) - def test_network_driver_create_network_with_netid_option(self): - docker_network_id = lib_utils.get_hash() - fake_neutron_net_id = "4e8e5957-649f-477b-9e5b-f1f75b21c03c" self.mox.StubOutWithMock(app.neutron, "list_networks") fake_existing_networks_response = { "networks": [{ @@ -281,11 +335,13 @@ def test_network_driver_create_network_with_netid_option(self): 'cidr': fake_cidr_v4, 'enable_dhcp': app.enable_dhcp, 'gateway_ip': '192.168.42.1', + 'subnetpool_id': fake_kuryr_subnetpool_id }] } subnet_v4_id = uuidutils.generate_uuid() fake_v4_subnet = self._get_fake_v4_subnet( fake_neutron_net_id, subnet_v4_id, + fake_kuryr_subnetpool_id, name=fake_cidr_v4, cidr=fake_cidr_v4) fake_subnet_response = { 'subnets': [ @@ -297,25 +353,6 @@ def test_network_driver_create_network_with_netid_option(self): self.mox.ReplayAll() - network_request = { - 'NetworkID': docker_network_id, - 'IPv4Data': [{ - 'AddressSpace': 'foo', - 'Pool': '192.168.42.0/24', - 'Gateway': '192.168.42.1/24', - }], - 'IPv6Data': [{ - 'AddressSpace': 'bar', - 'Pool': 'fe80::/64', - 'Gateway': 'fe80::f816:3eff:fe20:57c3/64', - }], - 'Options': { - 'com.docker.network.enable_ipv6': False, - 'com.docker.network.generic': { - 'neutron.net.uuid': '4e8e5957-649f-477b-9e5b-f1f75b21c03c' - } - } - } response = self.app.post('/NetworkDriver.CreateNetwork', content_type='application/json', data=jsonutils.dumps(network_request)) @@ -428,6 +465,29 @@ def test_network_driver_create_network_with_pool_name_option(self): def test_network_driver_create_network_wo_gw(self): docker_network_id = lib_utils.get_hash() + network_request = { + 'NetworkID': docker_network_id, + 'IPv4Data': [{ + 'AddressSpace': 'foo', + 'Pool': '192.168.42.0/24', + }], + 'IPv6Data': [{ + 'AddressSpace': 'bar', + 'Pool': 'fe80::/64', + 'Gateway': 'fe80::f816:3eff:fe20:57c3/64', + }], + 'Options': {} + } + + self.mox.StubOutWithMock(app.neutron, "list_subnetpools") + fake_kuryr_subnetpool_id = uuidutils.generate_uuid() + fake_name = lib_utils.get_neutron_subnetpool_name( + network_request['IPv4Data'][0]['Pool']) + kuryr_subnetpools = self._get_fake_v4_subnetpools( + fake_kuryr_subnetpool_id, name=fake_name) + app.neutron.list_subnetpools(name=fake_name).AndReturn( + {'subnetpools': kuryr_subnetpools['subnetpools']}) + self.mox.StubOutWithMock(app.neutron, "create_network") fake_request = { "network": { @@ -475,11 +535,13 @@ def test_network_driver_create_network_wo_gw(self): 'ip_version': 4, 'cidr': fake_cidr_v4, 'enable_dhcp': app.enable_dhcp, + 'subnetpool_id': fake_kuryr_subnetpool_id }] } subnet_v4_id = uuidutils.generate_uuid() fake_v4_subnet = self._get_fake_v4_subnet( fake_neutron_net_id, subnet_v4_id, + fake_kuryr_subnetpool_id, name=fake_cidr_v4, cidr=fake_cidr_v4) fake_subnet_response = { 'subnets': [ @@ -491,19 +553,6 @@ def test_network_driver_create_network_wo_gw(self): self.mox.ReplayAll() - network_request = { - 'NetworkID': docker_network_id, - 'IPv4Data': [{ - 'AddressSpace': 'foo', - 'Pool': '192.168.42.0/24', - }], - 'IPv6Data': [{ - 'AddressSpace': 'bar', - 'Pool': 'fe80::/64', - 'Gateway': 'fe80::f816:3eff:fe20:57c3/64', - }], - 'Options': {} - } response = self.app.post('/NetworkDriver.CreateNetwork', content_type='application/json', data=jsonutils.dumps(network_request)) @@ -514,16 +563,7 @@ def test_network_driver_create_network_wo_gw(self): def test_network_driver_create_network_with_network_id_not_exist(self): docker_network_id = lib_utils.get_hash() - - self.mox.StubOutWithMock(app.neutron, "list_networks") fake_neutron_net_id = uuidutils.generate_uuid() - fake_existing_networks_response = { - "networks": [] - } - app.neutron.list_networks( - id=fake_neutron_net_id).AndReturn( - fake_existing_networks_response) - self.mox.ReplayAll() network_request = { 'NetworkID': docker_network_id, 'IPv4Data': [{ @@ -541,6 +581,24 @@ def test_network_driver_create_network_with_network_id_not_exist(self): } } } + + self.mox.StubOutWithMock(app.neutron, "list_subnetpools") + fake_kuryr_subnetpool_id = uuidutils.generate_uuid() + fake_name = lib_utils.get_neutron_subnetpool_name( + network_request['IPv4Data'][0]['Pool']) + kuryr_subnetpools = self._get_fake_v4_subnetpools( + fake_kuryr_subnetpool_id, name=fake_name) + app.neutron.list_subnetpools(name=fake_name).AndReturn( + {'subnetpools': kuryr_subnetpools['subnetpools']}) + + self.mox.StubOutWithMock(app.neutron, "list_networks") + fake_existing_networks_response = { + "networks": [] + } + app.neutron.list_networks( + id=fake_neutron_net_id).AndReturn( + fake_existing_networks_response) + self.mox.ReplayAll() response = self.app.post('/NetworkDriver.CreateNetwork', content_type='application/json', data=jsonutils.dumps(network_request)) @@ -553,16 +611,7 @@ def test_network_driver_create_network_with_network_id_not_exist(self): def test_network_driver_create_network_with_network_name_not_exist(self): docker_network_id = lib_utils.get_hash() - - self.mox.StubOutWithMock(app.neutron, "list_networks") fake_neutron_network_name = "fake_network" - fake_existing_networks_response = { - "networks": [] - } - app.neutron.list_networks( - name=fake_neutron_network_name).AndReturn( - fake_existing_networks_response) - self.mox.ReplayAll() network_request = { 'NetworkID': docker_network_id, 'IPv4Data': [{ @@ -580,6 +629,23 @@ def test_network_driver_create_network_with_network_name_not_exist(self): } } } + self.mox.StubOutWithMock(app.neutron, "list_subnetpools") + fake_kuryr_subnetpool_id = uuidutils.generate_uuid() + fake_name = lib_utils.get_neutron_subnetpool_name( + network_request['IPv4Data'][0]['Pool']) + kuryr_subnetpools = self._get_fake_v4_subnetpools( + fake_kuryr_subnetpool_id, name=fake_name) + app.neutron.list_subnetpools(name=fake_name).AndReturn( + {'subnetpools': kuryr_subnetpools['subnetpools']}) + + self.mox.StubOutWithMock(app.neutron, "list_networks") + fake_existing_networks_response = { + "networks": [] + } + app.neutron.list_networks( + name=fake_neutron_network_name).AndReturn( + fake_existing_networks_response) + self.mox.ReplayAll() response = self.app.post('/NetworkDriver.CreateNetwork', content_type='application/json', data=jsonutils.dumps(network_request)) diff --git a/kuryr_libnetwork/tests/unit/test_kuryr_existing_network.py b/kuryr_libnetwork/tests/unit/test_kuryr_existing_network.py index ff7139f3..ff2ec9a2 100644 --- a/kuryr_libnetwork/tests/unit/test_kuryr_existing_network.py +++ b/kuryr_libnetwork/tests/unit/test_kuryr_existing_network.py @@ -49,17 +49,45 @@ def _ids(self): @mock.patch('kuryr_libnetwork.controllers.app.neutron.update_network') @mock.patch('kuryr_libnetwork.controllers.app.neutron.add_tag') @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_networks') + @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools') @mock.patch('kuryr_libnetwork.controllers.app') @ddt.data( (True), (False)) def test_create_network_pre_existing(self, use_tags, - mock_tag, mock_list_networks, mock_add_tag, - mock_update_network, mock_list_subnets, - mock_create_subnet): + mock_tag, mock_list_subnetpools, mock_list_networks, + mock_add_tag, mock_update_network, + mock_list_subnets, mock_create_subnet): if not use_tags: mock_tag.tag = use_tags docker_network_id, fake_neutron_net_id, fake_response = self._ids() + fake_kuryr_subnetpool_id = self._ids() + + network_request = { + 'NetworkID': docker_network_id, + 'IPv4Data': [{ + 'AddressSpace': 'foo', + 'Pool': '192.168.42.0/24', + 'Gateway': '192.168.42.1/24', + }], + 'IPv6Data': [{ + 'AddressSpace': 'bar', + 'Pool': 'fe80::/64', + 'Gateway': 'fe80::f816:3eff:fe20:57c3/64', + }], + 'Options': { + const.NETWORK_GENERIC_OPTIONS: { + const.NEUTRON_UUID_OPTION: fake_neutron_net_id + } + } + } + + fake_subnetpool_name = lib_utils.get_neutron_subnetpool_name( + network_request['IPv4Data'][0]['Pool']) + kuryr_subnetpools = self._get_fake_v4_subnetpools( + fake_kuryr_subnetpool_id, name=fake_subnetpool_name) + mock_list_subnetpools.return_value = { + 'subnetpools': kuryr_subnetpools['subnetpools']} mock_list_networks.return_value = fake_response @@ -77,11 +105,13 @@ def test_create_network_pre_existing(self, use_tags, 'cidr': fake_cidr_v4, 'enable_dhcp': mock_tag.enable_dhcp, 'gateway_ip': '192.168.42.1', + 'subnetpool_id': fake_kuryr_subnetpool_id }] } subnet_v4_id = uuidutils.generate_uuid() fake_v4_subnet = self._get_fake_v4_subnet( fake_neutron_net_id, subnet_v4_id, + fake_kuryr_subnetpool_id, name=fake_cidr_v4, cidr=fake_cidr_v4) fake_subnet_response = { 'subnets': [ @@ -90,29 +120,12 @@ def test_create_network_pre_existing(self, use_tags, } mock_create_subnet.return_value = fake_subnet_response - network_request = { - 'NetworkID': docker_network_id, - 'IPv4Data': [{ - 'AddressSpace': 'foo', - 'Pool': '192.168.42.0/24', - 'Gateway': '192.168.42.1/24', - }], - 'IPv6Data': [{ - 'AddressSpace': 'bar', - 'Pool': 'fe80::/64', - 'Gateway': 'fe80::f816:3eff:fe20:57c3/64', - }], - 'Options': { - const.NETWORK_GENERIC_OPTIONS: { - const.NEUTRON_UUID_OPTION: fake_neutron_net_id - } - } - } response = self.app.post('/NetworkDriver.CreateNetwork', content_type='application/json', data=jsonutils.dumps(network_request)) self.assertEqual(200, response.status_code) + mock_list_subnetpools.assert_called_with(name=fake_subnetpool_name) mock_list_networks.assert_called_with(id=fake_neutron_net_id) mock_list_subnets.assert_called_with( network_id=fake_neutron_net_id, diff --git a/kuryr_libnetwork/tests/unit/test_kuryr_network.py b/kuryr_libnetwork/tests/unit/test_kuryr_network.py index 39fe131c..74a0b44c 100644 --- a/kuryr_libnetwork/tests/unit/test_kuryr_network.py +++ b/kuryr_libnetwork/tests/unit/test_kuryr_network.py @@ -15,6 +15,7 @@ import mock from neutronclient.common import exceptions from oslo_serialization import jsonutils +from oslo_utils import uuidutils from kuryr.lib import utils as lib_utils from kuryr_libnetwork import constants as const @@ -28,9 +29,19 @@ class TestKuryrNetworkCreateFailures(base.TestKuryrFailures): This test covers error responses listed in the spec: http://developer.openstack.org/api-ref-networking-v2-ext.html#createProviderNetwork # noqa """ - def _invoke_create_request(self, network_name): + def _invoke_create_request(self, network_request): + response = self.app.post('/NetworkDriver.CreateNetwork', + content_type='application/json', + data=jsonutils.dumps(network_request)) + return response + + @mock.patch('kuryr_libnetwork.controllers.app.neutron.create_network') + @mock.patch('kuryr_libnetwork.controllers.app.neutron.list_subnetpools') + def test_create_network_unauthorized(self, mock_list_subnetpools, + mock_create_network): + docker_network_id = lib_utils.get_hash() network_request = { - 'NetworkID': network_name, + 'NetworkID': docker_network_id, 'IPv4Data': [{ 'AddressSpace': 'foo', 'Pool': '192.168.42.0/24', @@ -45,14 +56,15 @@ def _invoke_create_request(self, network_name): }], 'Options': {} } - response = self.app.post('/NetworkDriver.CreateNetwork', - content_type='application/json', - data=jsonutils.dumps(network_request)) - return response - @mock.patch('kuryr_libnetwork.controllers.app.neutron.create_network') - def test_create_network_unauthorized(self, mock_create_network): - docker_network_id = lib_utils.get_hash() + fake_subnetpool_name = lib_utils.get_neutron_subnetpool_name( + network_request['IPv4Data'][0]['Pool']) + fake_kuryr_subnetpool_id = uuidutils.generate_uuid() + kuryr_subnetpools = self._get_fake_v4_subnetpools( + fake_kuryr_subnetpool_id, name=fake_subnetpool_name) + mock_list_subnetpools.return_value = { + 'subnetpools': kuryr_subnetpools['subnetpools']} + fake_request = { "network": { "name": utils.make_net_name(docker_network_id), @@ -60,19 +72,35 @@ def test_create_network_unauthorized(self, mock_create_network): } } mock_create_network.side_effect = exceptions.Unauthorized - response = self._invoke_create_request(docker_network_id) + response = self._invoke_create_request(network_request) self.assertEqual(401, response.status_code) decoded_json = jsonutils.loads(response.data) - mock_create_network.assert_called_with( - fake_request) + mock_list_subnetpools.assert_called_with(name=fake_subnetpool_name) + mock_create_network.assert_called_with(fake_request) self.assertIn('Err', decoded_json) self.assertEqual( {'Err': exceptions.Unauthorized.message}, decoded_json) def test_create_network_bad_request(self): invalid_docker_network_id = 'id-should-be-hexdigits' - response = self._invoke_create_request(invalid_docker_network_id) + network_request = { + 'NetworkID': invalid_docker_network_id, + 'IPv4Data': [{ + 'AddressSpace': 'foo', + 'Pool': '192.168.42.0/24', + 'Gateway': '192.168.42.1/24', + 'AuxAddresses': {} + }], + 'IPv6Data': [{ + 'AddressSpace': 'bar', + 'Pool': 'fe80::/64', + 'Gateway': 'fe80::f816:3eff:fe20:57c3/64', + 'AuxAddresses': {} + }], + 'Options': {} + } + response = self._invoke_create_request(network_request) self.assertEqual(400, response.status_code) decoded_json = jsonutils.loads(response.data) self.assertIn('Err', decoded_json)