diff --git a/src/config/api-server/tests/test_crud_basic.py b/src/config/api-server/tests/test_crud_basic.py
index 7ab4075d6df..3e0452c8792 100644
--- a/src/config/api-server/tests/test_crud_basic.py
+++ b/src/config/api-server/tests/test_crud_basic.py
@@ -415,6 +415,49 @@ def test_physical_router_credentials(self):
if user_cred_read.password != '**Password Hidden**':
raise Exception("ERROR: physical-router: password should be hidden")
#end test_physical_router_credentials
+
+ def test_bridge_domain_with_vmi_ref_multiple_bd(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)
+
+ bd2_name = self.id() + '-bd-2'
+ 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)
+
+ bd_ref_data1 = BridgeDomainMembershipType();
+ bd_ref_data1.set_vlan_tag(0);
+
+ # 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);
+ 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
+
# end class TestCrud
class TestVncCfgApiServer(test_case.ApiServerTestCase):
diff --git a/src/config/api-server/vnc_cfg_types.py b/src/config/api-server/vnc_cfg_types.py
index f545d2da4aa..5813f3e3914 100644
--- a/src/config/api-server/vnc_cfg_types.py
+++ b/src/config/api-server/vnc_cfg_types.py
@@ -776,6 +776,30 @@ 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):
+ bridge_domain_links = {}
+ bd_refs = obj_dict.get('bridge_domain_refs') or []
+ for bd in bd_refs:
+ bd_fq_name = bd['to']
+ bd_uuid = bd.get('uuid')
+ if not bd_uuid:
+ bd_uuid = db_conn.fq_name_to_uuid('bridge_domain', bd_fq_name)
+
+ bdmt = bd['attr']
+ vlan_tag = bdmt['vlan_tag']
+ if vlan_tag in bridge_domain_links:
+ msg = "Virtual machine interface(%s) already refers to bridge "\
+ "domain(%s) for vlan tag %d"\
+ %(obj_dict['uuid'], bd_uuid, vlan_tag)
+ return (False, msg)
+
+ bridge_domain_links[vlan_tag] = bd_uuid
+
+ return (True, '')
+ # end _check_bridge_domain_vmi_association
+
@classmethod
def pre_dbe_create(cls, tenant_name, obj_dict, db_conn):
vn_dict = obj_dict['virtual_network_refs'][0]
@@ -795,6 +819,11 @@ 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)
+ if not ok:
+ return (False, (400, error))
+
inmac = None
if 'virtual_machine_interface_mac_addresses' in obj_dict:
mc = obj_dict['virtual_machine_interface_mac_addresses']
@@ -882,6 +911,11 @@ def pre_dbe_update(cls, id, fq_name, obj_dict, db_conn,
if not ok:
return ok, read_result
+ (ok, error) = cls._check_bridge_domain_vmi_association(obj_dict,
+ db_conn, False)
+ if not ok:
+ return (False, (400, error))
+
# check if the vmi is a internal interface of a logical
# router
if (read_result.get('logical_router_back_refs') and
diff --git a/src/schema/vnc_cfg.xsd b/src/schema/vnc_cfg.xsd
index c3c15ce1232..ca263b24803 100644
--- a/src/schema/vnc_cfg.xsd
+++ b/src/schema/vnc_cfg.xsd
@@ -3030,8 +3030,8 @@ targetNamespace="http://www.contrailsystems.com/2012/VNC-CONFIG/0">
+ 'virtual-network', 'bridge-domain', ['has'], 'optional', 'CRUD',
+ 'bridge-domains configured in a virtual network') -->