@@ -564,6 +564,82 @@ def test_prefix_import_with_vlan_group(self):
564564 self .assertEqual (prefix .vlan .vid , 102 )
565565 self .assertEqual (prefix .scope , site )
566566
567+ @override_settings (EXEMPT_VIEW_PERMISSIONS = ['*' ])
568+ def test_prefix_import_with_vlan_site_multiple_vlans_same_vid (self ):
569+ """
570+ Test import when multiple VLANs exist with the same vid but different sites.
571+ Ref: #20560
572+ """
573+ site1 = Site .objects .get (name = 'Site 1' )
574+ site2 = Site .objects .get (name = 'Site 2' )
575+
576+ # Create VLANs with the same vid but different sites
577+ vlan1 = VLAN .objects .create (vid = 1 , name = 'VLAN1-Site1' , site = site1 )
578+ VLAN .objects .create (vid = 1 , name = 'VLAN1-Site2' , site = site2 ) # Create ambiguity
579+
580+ # Import prefix with vlan_site specified
581+ IMPORT_DATA = f"""
582+ prefix: 10.11.0.0/22
583+ status: active
584+ scope_type: dcim.site
585+ scope_id: { site1 .pk }
586+ vlan_site: { site1 .name }
587+ vlan: 1
588+ description: LOC02-MGMT
589+ """
590+
591+ # Add all required permissions to the test user
592+ self .add_permissions ('ipam.view_prefix' , 'ipam.add_prefix' )
593+
594+ form_data = {
595+ 'data' : IMPORT_DATA ,
596+ 'format' : 'yaml'
597+ }
598+ response = self .client .post (reverse ('ipam:prefix_bulk_import' ), data = form_data , follow = True )
599+ self .assertHttpStatus (response , 200 )
600+
601+ # Verify the prefix was created with the correct VLAN
602+ prefix = Prefix .objects .get (prefix = '10.11.0.0/22' )
603+ self .assertEqual (prefix .vlan , vlan1 )
604+
605+ @override_settings (EXEMPT_VIEW_PERMISSIONS = ['*' ])
606+ def test_prefix_import_with_vlan_site_and_global_vlan (self ):
607+ """
608+ Test import when a global VLAN (no site) and site-specific VLAN exist with same vid.
609+ When vlan_site is specified, should prefer the site-specific VLAN.
610+ Ref: #20560
611+ """
612+ site1 = Site .objects .get (name = 'Site 1' )
613+
614+ # Create a global VLAN (no site) and a site-specific VLAN with the same vid
615+ VLAN .objects .create (vid = 10 , name = 'VLAN10-Global' , site = None ) # Create ambiguity
616+ vlan_site = VLAN .objects .create (vid = 10 , name = 'VLAN10-Site1' , site = site1 )
617+
618+ # Import prefix with vlan_site specified
619+ IMPORT_DATA = f"""
620+ prefix: 10.12.0.0/22
621+ status: active
622+ scope_type: dcim.site
623+ scope_id: { site1 .pk }
624+ vlan_site: { site1 .name }
625+ vlan: 10
626+ description: Test Site-Specific VLAN
627+ """
628+
629+ # Add all required permissions to the test user
630+ self .add_permissions ('ipam.view_prefix' , 'ipam.add_prefix' )
631+
632+ form_data = {
633+ 'data' : IMPORT_DATA ,
634+ 'format' : 'yaml'
635+ }
636+ response = self .client .post (reverse ('ipam:prefix_bulk_import' ), data = form_data , follow = True )
637+ self .assertHttpStatus (response , 200 )
638+
639+ # Verify the prefix was created with the site-specific VLAN (not the global one)
640+ prefix = Prefix .objects .get (prefix = '10.12.0.0/22' )
641+ self .assertEqual (prefix .vlan , vlan_site )
642+
567643
568644class IPRangeTestCase (ViewTestCases .PrimaryObjectViewTestCase ):
569645 model = IPRange
0 commit comments