Skip to content

Commit

Permalink
Config check for bridge domain creation and VMI linking
Browse files Browse the repository at this point in the history
1. Allow only one bridge domain to be created in a VN(B-Comp)
2. Allow VMI to Bridge domain link only if VN and Bridge domain belongs
to same virtual network.
3. Add tests cases for validating the above config checks

Related-bug: #1645092

Change-Id: I283479e39e3787e948557d83d432354a49e15b15
  • Loading branch information
bailkeri committed Feb 20, 2017
1 parent dae0614 commit 4440a83
Show file tree
Hide file tree
Showing 2 changed files with 120 additions and 21 deletions.
94 changes: 77 additions & 17 deletions src/config/api-server/tests/test_crud_basic.py
Expand Up @@ -416,7 +416,7 @@ def test_physical_router_credentials(self):
raise Exception("ERROR: physical-router: password should be hidden")
#end test_physical_router_credentials

def test_bridge_domain_with_vmi_ref_multiple_bd(self):
def test_bridge_domain_with_multiple_bd_in_vn(self):
vn1_name = self.id() + '-vn-1'
vn1 = VirtualNetwork(vn1_name)
logger.info('Creating VN %s', vn1_name)
Expand All @@ -438,25 +438,85 @@ def test_bridge_domain_with_vmi_ref_multiple_bd(self):
bd2 = BridgeDomain(bd2_name, parent_obj=vn1)
bd2.set_isid(300300)
logger.info('Creating Bridge Domain %s', bd2_name)
self._vnc_lib.bridge_domain_create(bd2)
with ExpectedException(BadRequest) as e:
self._vnc_lib.bridge_domain_create(bd2)
# end test_bridge_domain_with_multiple_bd_in_vn

def test_bridge_domain_link_vmi_and_bd_in_different_vn(self):
vn1_name = self.id() + '-vn-1'
vn1 = VirtualNetwork(vn1_name)
logger.info('Creating VN %s', vn1_name)
self._vnc_lib.virtual_network_create(vn1)

vn2_name = self.id() + '-vn-2'
vn2 = VirtualNetwork(vn2_name)
logger.info('Creating VN %s', vn2_name)
self._vnc_lib.virtual_network_create(vn2)

vmi1_name = self.id() + '-port-1'
logger.info('Creating port %s', vmi1_name)
vmi1 = VirtualMachineInterface(vmi1_name, parent_obj=Project())
vmi1.add_virtual_network(vn1)
self._vnc_lib.virtual_machine_interface_create(vmi1)

bd_ref_data1 = BridgeDomainMembershipType();
bd_ref_data1.set_vlan_tag(0);
vmi2_name = self.id() + '-port-2'
logger.info('Creating port %s', vmi2_name)
vmi2 = VirtualMachineInterface(vmi2_name, parent_obj=Project())
vmi2.add_virtual_network(vn2)
self._vnc_lib.virtual_machine_interface_create(vmi2)

bd1_name = self.id() + '-bd-1'
bd1 = BridgeDomain(bd1_name, parent_obj=vn1)
bd1.set_isid(200200)
logger.info('Creating Bridge Domain %s', bd1_name)
self._vnc_lib.bridge_domain_create(bd1)

# VMI is referring to two bridge domain(bd1 and bd2) for vlan tag = 0
vmi.add_bridge_domain(bd1, bd_ref_data1);
vmi.add_bridge_domain(bd2, bd_ref_data1);
bd_ref_data1 = BridgeDomainMembershipType(vlan_tag=0)
vmi2.add_bridge_domain(bd1, bd_ref_data1)
with ExpectedException(BadRequest) as e:
self._vnc_lib.virtual_machine_interface_update(vmi)

# Link the VMI to two bridge domain for different vlan tags(0, 1)
vmi_obj = self._vnc_lib.virtual_machine_interface_read(id=vmi.uuid)
bd_ref_data1 = BridgeDomainMembershipType(vlan_tag=1);
bd_ref_data2 = BridgeDomainMembershipType(vlan_tag=2);
vmi_obj.add_bridge_domain(bd1, bd_ref_data1);
vmi_obj.add_bridge_domain(bd2, bd_ref_data2);
self._vnc_lib.virtual_machine_interface_update(vmi_obj)
# end test_bridge_domain_with_vmi_ref_multiple_bd
self._vnc_lib.virtual_machine_interface_update(vmi2)

bd_ref_data2 = BridgeDomainMembershipType(vlan_tag=0)
vmi1.add_bridge_domain(bd1, bd_ref_data2)
self._vnc_lib.virtual_machine_interface_update(vmi1)
# end test_bridge_domain_link_vmi_and_bd_in_different_vn

def test_bridge_domain_delete_vn_ref_with_bd_link(self):
vn1_name = self.id() + '-vn-1'
vn1 = VirtualNetwork(vn1_name)
logger.info('Creating VN %s', vn1_name)
self._vnc_lib.virtual_network_create(vn1)

vmi_name = self.id() + '-port'
logger.info('Creating port %s', vmi_name)
vmi = VirtualMachineInterface(vmi_name, parent_obj=Project())
vmi.add_virtual_network(vn1)
self._vnc_lib.virtual_machine_interface_create(vmi)

bd1_name = self.id() + '-bd-1'
bd1 = BridgeDomain(bd1_name, parent_obj=vn1)
bd1.set_isid(200200)
logger.info('Creating Bridge Domain %s', bd1_name)
self._vnc_lib.bridge_domain_create(bd1)

bd_ref_data = BridgeDomainMembershipType(vlan_tag=0)
vmi.add_bridge_domain(bd1, bd_ref_data)
self._vnc_lib.virtual_machine_interface_update(vmi)

# Try to delete the VN link with BD ref
vmi_temp = vmi
vmi_temp.del_virtual_network(vn1)
with ExpectedException(BadRequest) as e:
self._vnc_lib.virtual_machine_interface_update(vmi_temp)

# Delete the BD ref
vmi.del_bridge_domain(bd1)
self._vnc_lib.virtual_machine_interface_update(vmi)

vmi.del_virtual_network(vn1)
self._vnc_lib.virtual_machine_interface_update(vmi)
# end test_bridge_domain_with_multiple_bd_in_vn


# end class TestCrud

Expand Down
47 changes: 43 additions & 4 deletions src/config/api-server/vnc_cfg_types.py
Expand Up @@ -777,12 +777,29 @@ def _check_vrouter_link(cls, vmi_data, kvp_dict, obj_dict, db_conn):
# end _check_vrouter_link

@classmethod
def _check_bridge_domain_vmi_association(cls, obj_dict,
db_conn, create):
def _check_bridge_domain_vmi_association(cls, obj_dict, db_conn, vn_uuid,
create):
vn_fq_name = []
if vn_uuid:
vn_fq_name = db_conn.uuid_to_fq_name(vn_uuid)

bridge_domain_links = {}
bd_refs = obj_dict.get('bridge_domain_refs') or []

vn_refs = obj_dict.get('virtual_network_refs') or []
if len(vn_refs) == 0 and len(bd_refs):
msg = "Virtual network can not be updated on virtual machine "\
"interface(%s) while it refers a bridge domain"\
%(obj_dict['uuid'])
return (False, msg)

for bd in bd_refs:
bd_fq_name = bd['to']
if bd_fq_name[0:3] != vn_fq_name:
msg = "Virtual machine interface(%s) can only refer to bridge "\
"domain belonging to virtual network(%s)"\
%(obj_dict['uuid'], vn_uuid)
return (False, msg)
bd_uuid = bd.get('uuid')
if not bd_uuid:
bd_uuid = db_conn.fq_name_to_uuid('bridge_domain', bd_fq_name)
Expand Down Expand Up @@ -820,7 +837,7 @@ def pre_dbe_create(cls, tenant_name, obj_dict, db_conn):
vn_dict = result

(ok, error) = cls._check_bridge_domain_vmi_association(obj_dict,
db_conn, True)
db_conn, vn_uuid, True)
if not ok:
return (False, (400, error))

Expand Down Expand Up @@ -911,8 +928,11 @@ def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn,
if not ok:
return ok, read_result

vn_uuid = None
if 'virtual_network_refs' in read_result:
vn_uuid = read_result['virtual_network_refs'][0].get('uuid')
(ok, error) = cls._check_bridge_domain_vmi_association(obj_dict,
db_conn, False)
db_conn, vn_uuid, False)
if not ok:
return (False, (400, error))

Expand Down Expand Up @@ -1005,6 +1025,25 @@ def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn, **kwargs):
# end pre_dbe_update
# end class ServiceApplianceSetServer


class BridgeDomainServer(Resource, BridgeDomain):
@classmethod
def pre_dbe_create(cls, tenant_name, obj_dict, db_conn):
vn_uuid = obj_dict.get('parent_uuid')
if vn_uuid is None:
vn_uuid = db_conn.fq_name_to_uuid('virtual_network', obj_dict['fq_name'][0:3])
ok, result = cls.dbe_read(db_conn, 'virtual_network', vn_uuid, obj_fields=['bridge_domains'])
if not ok:
return ok, result
if 'bridge_domains' in result and len(result['bridge_domains']) == 1:
msg = "Virtual network(%s) can have only one bridge domain. Bridge"\
" domain(%s) is already created under this virtual network" %\
(vn_uuid, result['bridge_domains'][0]['uuid'])
return (False, (400, msg))
return True, ""
# end pre_dbe_create
# end class BridgeDomainServer

class VirtualNetworkServer(Resource, VirtualNetwork):

@classmethod
Expand Down

0 comments on commit 4440a83

Please sign in to comment.