diff --git a/src/config/api-server/db_manage.py b/src/config/api-server/db_manage.py index 059b84d9b6b..ca34a7ebe4b 100644 --- a/src/config/api-server/db_manage.py +++ b/src/config/api-server/db_manage.py @@ -4,6 +4,7 @@ import socket import re import logging +import time from cfgm_common import jsonutils as json from netaddr import IPAddress, IPNetwork import argparse diff --git a/src/config/api-server/tests/test_crud_basic.py b/src/config/api-server/tests/test_crud_basic.py index d61375d47f8..1621a7ba7c2 100644 --- a/src/config/api-server/tests/test_crud_basic.py +++ b/src/config/api-server/tests/test_crud_basic.py @@ -1187,7 +1187,7 @@ def test_floatingip_as_instanceip(self): ip_allocated = fip_fixt.getObj().floating_ip_address logger.info("Creating auto-alloc instance-ip, expecting an error") - with ExpectedException(BadRequest) as e: + with ExpectedException(RefsExistError) as e: iip_fixt = self.useFixture( InstanceIpTestFixtureGen( self._vnc_lib, 'iip1', auto_prop_val=False, @@ -1223,7 +1223,7 @@ def test_aliasip_as_instanceip(self): ip_allocated = aip_fixt.getObj().alias_ip_address logger.info("Creating auto-alloc instance-ip, expecting an error") - with ExpectedException(BadRequest) as e: + with ExpectedException(RefsExistError) as e: iip_fixt = self.useFixture( InstanceIpTestFixtureGen( self._vnc_lib, 'iip1', auto_prop_val=False, diff --git a/src/config/api-server/tests/test_ip_alloc.py b/src/config/api-server/tests/test_ip_alloc.py index 7c837e9ff35..a5ccb541500 100644 --- a/src/config/api-server/tests/test_ip_alloc.py +++ b/src/config/api-server/tests/test_ip_alloc.py @@ -663,14 +663,14 @@ def test_flat_subnet_ipam_flat_subnet_network(self): if ipv4_addr2 != '11.1.1.4': logger.debug('Allocation failed, expected v4 IP Address 11.1.1.4') - #Remove ipam_subnets from ipam, update should fail with - #RefExistError + #Remove ipam_subnets from ipam, update should fail with + #RefsExistError ipam.set_ipam_subnets(IpamSubnets([])) with ExpectedException(cfgm_common.exceptions.RefsExistError) as e: self._vnc_lib.network_ipam_update(ipam) #Change ipam by removing one and adding another, update should fail - # with RefExistError + # with RefsExistError ipam.set_ipam_subnets(IpamSubnets([ipam2_sn_v4])) with ExpectedException(cfgm_common.exceptions.RefsExistError) as e: self._vnc_lib.network_ipam_update(ipam) @@ -740,7 +740,7 @@ def test_flat_subnet_ipam_flat_subnet_network(self): ipv4_obj2.uuid = ipv4_obj2.name ipv4_obj2.set_virtual_network(net_obj) logger.debug('Created Instance IPv4 object 2 %s', ipv4_obj2.uuid) - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: ipv4_id2 = self._vnc_lib.instance_ip_create(ipv4_obj2) @@ -878,7 +878,7 @@ def test_hybrid_subnet_ipam_flat_subnet_network(self): #try allocating specific ip, which has been assigned already ipv4_obj5.set_instance_ip_address('12.1.1.4') - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: ipv4_id5 = self._vnc_lib.instance_ip_create(ipv4_obj5) @@ -1026,7 +1026,7 @@ def test_hybrid_subnet_ipam_user_subnet_network(self): #try allocating specific ip, which has been assigned already ipv4_obj5.set_instance_ip_address('14.1.1.8') - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: ipv4_id5 = self._vnc_lib.instance_ip_create(ipv4_obj5) @@ -1141,7 +1141,7 @@ def test_hybrid_subnet_ipam_ask_ip(self): # of ip in use ipv4_obj2.set_virtual_network(net_obj) ipv4_obj2.set_instance_ip_address('13.1.1.8') - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: ipv4_id2 = self._vnc_lib.instance_ip_create(ipv4_obj2) @@ -1178,7 +1178,7 @@ def test_hybrid_subnet_ipam_ask_ip(self): # of ip in use. ipv4_obj4.set_virtual_network(net_obj) ipv4_obj4.set_instance_ip_address('11.1.1.8') - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: ipv4_id4 = self._vnc_lib.instance_ip_create(ipv4_obj4) @@ -2179,13 +2179,13 @@ def test_ip_alloc_clash(self): iip2_obj = InstanceIp('clashing-iip-%s' %(self.id()), instance_ip_address=iip_obj.instance_ip_address) iip2_obj.add_virtual_network(vn_obj) - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.instance_ip_create(iip2_obj) # allocate instance-ip clashing with existing floating-ip iip2_obj.set_instance_ip_address(fip_obj.floating_ip_address) - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.instance_ip_create(iip2_obj) @@ -2193,7 +2193,7 @@ def test_ip_alloc_clash(self): fip2_obj = FloatingIp('clashing-fip-%s' %(self.id()), fip_pool_obj, floating_ip_address=fip_obj.floating_ip_address) fip2_obj.add_project(proj_obj) - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.floating_ip_create(fip2_obj) @@ -2201,37 +2201,37 @@ def test_ip_alloc_clash(self): aip2_obj = AliasIp('clashing-aip-%s' %(self.id()), aip_pool_obj, alias_ip_address=aip_obj.alias_ip_address) aip2_obj.add_project(proj_obj) - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.alias_ip_create(aip2_obj) # allocate floating-ip clashing with existing instance-ip fip2_obj.set_floating_ip_address(iip_obj.instance_ip_address) - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.floating_ip_create(fip2_obj) # allocate alias-ip clashing with existing instance-ip aip2_obj.set_alias_ip_address(iip_obj.instance_ip_address) - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.alias_ip_create(aip2_obj) # allocate alias-ip clashing with existing floating-ip aip2_obj.set_alias_ip_address(fip_obj.floating_ip_address) - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.alias_ip_create(aip2_obj) # allocate floating-ip with gateway ip and verify failure fip2_obj.set_floating_ip_address('11.1.1.254') - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.floating_ip_create(fip2_obj) # allocate alias-ip with gateway ip and verify failure aip2_obj.set_alias_ip_address('11.1.1.254') - with ExpectedException(cfgm_common.exceptions.BadRequest, + with ExpectedException(cfgm_common.exceptions.RefsExistError, 'Ip address already in use') as e: self._vnc_lib.alias_ip_create(aip2_obj) diff --git a/src/config/api-server/tests/test_logical_router.py b/src/config/api-server/tests/test_logical_router.py index 0f6d3ee1743..ba509501f38 100644 --- a/src/config/api-server/tests/test_logical_router.py +++ b/src/config/api-server/tests/test_logical_router.py @@ -2,6 +2,8 @@ # Copyright (c) 2013,2014 Juniper Networks, Inc. All rights reserved. # import gevent +import gevent.monkey +gevent.monkey.patch_all() import os import sys import socket @@ -432,7 +434,7 @@ def test_vm_port_not_added_to_lr(self): # Add Router Interface lr.add_virtual_machine_interface(vm_port_obj) logger.debug("Trying to Link VM's VMI object and LR object") - with ExpectedException(cfgm_common.exceptions.BadRequest) as e: + with ExpectedException(cfgm_common.exceptions.RefsExistError) as e: self._vnc_lib.logical_router_update(lr) logger.debug("Linking VM's VMI object and LR object failed as expected") lr.del_virtual_machine_interface(vm_port_obj) diff --git a/src/config/api-server/vnc_cfg_types.py b/src/config/api-server/vnc_cfg_types.py index 34c573082d8..d6118656359 100644 --- a/src/config/api-server/vnc_cfg_types.py +++ b/src/config/api-server/vnc_cfg_types.py @@ -227,7 +227,7 @@ def pre_dbe_create(cls, tenant_name, obj_dict, db_conn): vn_fq_name = obj_dict['fq_name'][:-2] req_ip = obj_dict.get("floating_ip_address") if req_ip and cls.addr_mgmt.is_ip_allocated(req_ip, vn_fq_name): - return (False, (400, 'Ip address already in use')) + return (False, (409, 'Ip address already in use')) try: fip_addr = cls.addr_mgmt.ip_alloc_req(vn_fq_name, asked_ip_addr=req_ip, @@ -297,7 +297,7 @@ def pre_dbe_create(cls, tenant_name, obj_dict, db_conn): vn_fq_name = obj_dict['fq_name'][:-2] req_ip = obj_dict.get("alias_ip_address") if req_ip and cls.addr_mgmt.is_ip_allocated(req_ip, vn_fq_name): - return (False, (400, 'Ip address already in use')) + return (False, (409, 'Ip address already in use')) try: aip_addr = cls.addr_mgmt.ip_alloc_req(vn_fq_name, asked_ip_addr=req_ip, @@ -427,7 +427,7 @@ def pre_dbe_create(cls, tenant_name, obj_dict, db_conn): if req_ip and cls.addr_mgmt.is_ip_allocated(req_ip, vn_fq_name, vn_uuid=vn_id): if not cls.addr_mgmt.is_gateway_ip(vn_dict, req_ip): - return (False, (400, 'Ip address already in use')) + return (False, (409, 'Ip address already in use')) elif cls._vmi_has_vm_ref(db_conn, obj_dict): return (False, (400, 'Gateway IP cannot be used by VM port')) @@ -557,7 +557,7 @@ def is_port_in_use_by_vm(cls, obj_dict, db_conn): read_result.get('virtual_machine_refs')): msg = "Port(%s) already in use by virtual-machine(%s)" %\ (vmi_id, read_result['parent_uuid']) - return (False, (400, msg)) + return (False, (409, msg)) return (True, '') @classmethod diff --git a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py index 262846445b0..7f764cd8429 100644 --- a/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py +++ b/src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py @@ -3720,16 +3720,27 @@ def port_create(self, context, port_q): self._vnc_lib.chown(port_id, tenant_id) # add support, nova boot --nic subnet-id=subnet_uuid subnet_id = port_q.get('subnet_id') - net_fq_name = net_obj.get_fq_name() - net_fq_name_str = str([str(a) for a in net_fq_name]) if 'fixed_ips' in port_q: + exception = None + exception_kwargs = {} try: self._port_create_instance_ip(net_obj, port_obj, port_q) + except RefsExistError as e: + # failure in creating the instance ip. Roll back + exception = 'Conflict' + exception_kwargs = {'message': str(e)} except BadRequest as e: + exception = 'BadRequest' + exception_kwargs = {'resource': 'port', 'msg': str(e)} + except vnc_exc.HttpError: # failure in creating the instance ip. Roll back - self._virtual_machine_interface_delete(port_id=port_id) - self._raise_contrail_exception('BadRequest', resource='port', - msg=str(e)) + exception = 'IpAddressGenerationFailure' + exception_kwargs = {'net_id': net_obj.uuid} + finally: + if exception: + # failure in creating the instance ip. Roll back + self._virtual_machine_interface_delete(port_id=port_id) + self._raise_contrail_exception(exception, **exception_kwargs) elif net_obj.get_network_ipam_refs(): ipv4_port_delete = False ipv6_port_delete = False @@ -3743,7 +3754,12 @@ def port_create(self, context, port_q): ipv4_port_delete = True v4_msg_str = "v4:"+ str(e) err_msg_str += v4_msg_str - + except vnc_exc.HttpError as e: + # failure in creating the instance ip. Roll back + self._virtual_machine_interface_delete(port_id=port_id) + self._raise_contrail_exception('IpAddressGenerationFailure', + resource='port', msg=str(e)) + try: self._port_create_instance_ip(net_obj, port_obj, {'fixed_ips':[{'ip_address': None, @@ -3753,6 +3769,11 @@ def port_create(self, context, port_q): ipv6_port_delete = True v6_msg_str = " v6:"+ str(e) err_msg_str += v6_msg_str + except vnc_exc.HttpError as e: + # failure in creating the instance ip. Roll back + self._virtual_machine_interface_delete(port_id=port_id) + self._raise_contrail_exception('IpAddressGenerationFailure', + resource='port', msg=str(e)) # if if bad request is for both ipv4 and ipv6 # delete the port and Roll back diff --git a/src/config/vnc_openstack/vnc_openstack/tests/test_basic.py b/src/config/vnc_openstack/vnc_openstack/tests/test_basic.py index 3cb2e6d80bd..48012ed84b8 100644 --- a/src/config/vnc_openstack/vnc_openstack/tests/test_basic.py +++ b/src/config/vnc_openstack/vnc_openstack/tests/test_basic.py @@ -1,5 +1,6 @@ import sys import json +import re from testtools.matchers import Equals, Contains from testtools import ExpectedException @@ -473,6 +474,41 @@ def test_update_port_with_security_group_and_port_security_disabled(self): sg_q = self.create_resource('security_group', proj_obj.uuid) with ExpectedException(webtest.app.AppError): self.update_resource('port', port_q['id'], proj_obj.uuid, extra_res_fields={'security_groups': [sg_q['id']]}) + + def test_fixed_ip_conflicts_with_floating_ip(self): + proj_obj = self._vnc_lib.project_read(fq_name=['default-domain', 'default-project']) + sg_q = self.create_resource('security_group', proj_obj.uuid) + net_q = self.create_resource('network', proj_obj.uuid, + extra_res_fields={'router:external': True}) + subnet_q = self.create_resource('subnet', proj_obj.uuid, + extra_res_fields={ + 'network_id': net_q['id'], + 'cidr': '1.1.1.0/24', + 'ip_version': 4, + }) + fip_q = self.create_resource('floatingip', proj_obj.uuid, + extra_res_fields={'floating_network_id': net_q['id']}) + + try: + self.create_resource('port', proj_obj.uuid, + extra_res_fields={ + 'network_id': net_q['id'], + 'fixed_ips': [{'ip_address': fip_q['floating_ip_address']}], + 'security_groups': [sg_q['id']], + }) + self.assertTrue(False, + 'Create with fixed-ip conflicting with floating-ip passed') + except webtest.app.AppError as e: + self.assertIsNot(re.search('Conflict', str(e)), None) + self.assertIsNot(re.search('Ip address already in use', str(e)), + None) + + # cleanup + self.delete_resource('floatingip', proj_obj.uuid, fip_q['id']) + self.delete_resource('subnet', proj_obj.uuid, subnet_q['id']) + self.delete_resource('network', proj_obj.uuid, net_q['id']) + self.delete_resource('security_group', proj_obj.uuid, sg_q['id']) + # end test_fixed_ip_conflicts_with_floating_ip # end class TestBasic class TestExtraFieldsPresenceByKnob(test_case.NeutronBackendTestCase):