diff --git a/src/config/api-server/tests/test_crud_basic.py b/src/config/api-server/tests/test_crud_basic.py index 4ca499ea932..9c38c1eb18b 100644 --- a/src/config/api-server/tests/test_crud_basic.py +++ b/src/config/api-server/tests/test_crud_basic.py @@ -31,6 +31,7 @@ from vnc_api.common import exceptions as vnc_exceptions import vnc_api.gen.vnc_api_test_gen from vnc_api.gen.resource_test import * +import cfgm_common sys.path.append('../common/tests') from test_utils import * @@ -822,6 +823,40 @@ def test_put_on_wrong_type(self): rb_obj = self._vnc_lib.virtual_network_read(id=vn_obj.uuid) self.assertThat(rb_obj.display_name, Equals('foobar')) + def test_floatingip_as_instanceip(self): + ipam_fixt = self.useFixture(NetworkIpamTestFixtureGen(self._vnc_lib)) + + project_fixt = self.useFixture(ProjectTestFixtureGen(self._vnc_lib, 'default-project')) + + subnet_vnc = IpamSubnetType(subnet=SubnetType('1.1.1.0', 24)) + vnsn_data = VnSubnetsType([subnet_vnc]) + logger.info("Creating a virtual network") + logger.info("Creating subnet 1.1.1.0/24") + vn_fixt = self.useFixture(VirtualNetworkTestFixtureGen(self._vnc_lib, + network_ipam_ref_infos=[(ipam_fixt.getObj(), vnsn_data)])) + vn_fixt.getObj().set_router_external(True) + self._vnc_lib.virtual_network_update(vn_fixt.getObj()) + + logger.info("Fetching floating-ip-pool") + fip_pool_fixt = self.useFixture( + FloatingIpPoolTestFixtureGen(self._vnc_lib, 'floating-ip-pool', + parent_fixt=vn_fixt)) + + logger.info("Creating auto-alloc floating-ip") + fip_fixt = self.useFixture( + FloatingIpTestFixtureGen( + self._vnc_lib, 'fip1', parent_fixt=fip_pool_fixt, + project_refs=[project_fixt.getObj()])) + ip_allocated = fip_fixt.getObj().floating_ip_address + + logger.info("Creating auto-alloc instance-ip, expecting an error") + with self.assertRaises(cfgm_common.exceptions.PermissionDenied): + iip_fixt = self.useFixture( + InstanceIpTestFixtureGen( + self._vnc_lib, 'iip1', auto_prop_val=False, + instance_ip_address=ip_allocated, + virtual_network_refs=[vn_fixt.getObj()])) + # end test_floatingip_as_instanceip # end class TestVncCfgApiServer class TestLocalAuth(test_case.ApiServerTestCase): diff --git a/src/config/api-server/vnc_cfg_types.py b/src/config/api-server/vnc_cfg_types.py index e9d40946694..31fc89cd94f 100644 --- a/src/config/api-server/vnc_cfg_types.py +++ b/src/config/api-server/vnc_cfg_types.py @@ -168,6 +168,17 @@ def _get_subnet_name(cls, vn_dict, subnet_uuid): subnet_dict['ip_prefix_len']) return subnet_name + @classmethod + def _is_gateway_ip(cls, vn_dict, ip_addr): + ipam_refs = vn_dict.get('network_ipam_refs', []) + for ipam in ipam_refs: + ipam_subnets = ipam['attr'].get('ipam_subnets', []) + for subnet in ipam_subnets: + if subnet['default_gateway'] == ip_addr: + return True + + return False + @classmethod def http_post_collection(cls, tenant_name, obj_dict, db_conn): vn_fq_name = obj_dict['virtual_network_refs'][0]['to'] @@ -190,6 +201,15 @@ def http_post_collection(cls, tenant_name, obj_dict, db_conn): sub = cls._get_subnet_name(vn_dict, subnet_uuid) if subnet_uuid else None if subnet_uuid and not sub: return (False, (404, "Subnet id " + subnet_uuid + " not found")) + + # If its an external network, check whether floating IP equivalent to + # requested fixed-IP is already reserved. + router_external = vn_dict.get('router_external', None) + if req_ip and router_external and \ + not cls._is_gateway_ip(vn_dict, req_ip) and \ + cls.addr_mgmt.is_ip_allocated(req_ip, vn_fq_name): + return (False, (403, 'Ip address already in use')) + try: ip_addr = cls.addr_mgmt.ip_alloc_req( vn_fq_name, sub=sub, asked_ip_addr=req_ip, diff --git a/src/config/common/tests/test_utils.py b/src/config/common/tests/test_utils.py index f917509d83d..fb578ee50d4 100644 --- a/src/config/common/tests/test_utils.py +++ b/src/config/common/tests/test_utils.py @@ -813,6 +813,10 @@ def create(self, path, value='', *args, **kwargs): self._values[path] = value # end create + def get(self, path): + return self._values[path] + # end get + def delete(self, path, recursive=False): if not recursive: try: