Skip to content

Commit

Permalink
Merge "Report 409(conflict) instead of 400(bad request) from vnc_cfg_…
Browse files Browse the repository at this point in the history
…types when requested address is already in use. Raise 'Conflict' exception from neutron_plugin_db.py:port_create as this is what is expected by tempest API test. Tests to reflect change." into R3.2
  • Loading branch information
Zuul authored and opencontrail-ci-admin committed Feb 21, 2017
2 parents 707b466 + 4087f18 commit 3f71d69
Show file tree
Hide file tree
Showing 7 changed files with 90 additions and 30 deletions.
1 change: 1 addition & 0 deletions src/config/api-server/db_manage.py
Expand Up @@ -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
Expand Down
4 changes: 2 additions & 2 deletions src/config/api-server/tests/test_crud_basic.py
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down
34 changes: 17 additions & 17 deletions src/config/api-server/tests/test_ip_alloc.py
Expand Up @@ -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)
Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -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)

Expand Down Expand Up @@ -2179,59 +2179,59 @@ 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)

# allocate floating-ip clashing with existing floating-ip
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)

# allocate alias-ip clashing with existing alias-ip
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)

Expand Down
4 changes: 3 additions & 1 deletion src/config/api-server/tests/test_logical_router.py
Expand Up @@ -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
Expand Down Expand Up @@ -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)
Expand Down
8 changes: 4 additions & 4 deletions src/config/api-server/vnc_cfg_types.py
Expand Up @@ -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,
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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'))
Expand Down Expand Up @@ -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
Expand Down
33 changes: 27 additions & 6 deletions src/config/vnc_openstack/vnc_openstack/neutron_plugin_db.py
Expand Up @@ -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
Expand All @@ -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,
Expand All @@ -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
Expand Down
36 changes: 36 additions & 0 deletions 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
Expand Down Expand Up @@ -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):
Expand Down

0 comments on commit 3f71d69

Please sign in to comment.