@@ -2802,6 +2802,24 @@ class InterfaceFilterForm(DeviceComponentFilterForm):
2802
2802
2803
2803
2804
2804
class InterfaceForm (BootstrapMixin , InterfaceCommonForm , CustomFieldModelForm ):
2805
+ parent = DynamicModelChoiceField (
2806
+ queryset = Interface .objects .all (),
2807
+ required = False ,
2808
+ label = 'Parent interface' ,
2809
+ display_field = 'display_name' ,
2810
+ query_params = {
2811
+ 'kind' : 'physical' ,
2812
+ }
2813
+ )
2814
+ lag = DynamicModelChoiceField (
2815
+ queryset = Interface .objects .all (),
2816
+ required = False ,
2817
+ label = 'LAG interface' ,
2818
+ display_field = 'display_name' ,
2819
+ query_params = {
2820
+ 'type' : 'lag' ,
2821
+ }
2822
+ )
2805
2823
untagged_vlan = DynamicModelChoiceField (
2806
2824
queryset = VLAN .objects .all (),
2807
2825
required = False ,
@@ -2830,13 +2848,12 @@ class InterfaceForm(BootstrapMixin, InterfaceCommonForm, CustomFieldModelForm):
2830
2848
class Meta :
2831
2849
model = Interface
2832
2850
fields = [
2833
- 'device' , 'name' , 'label' , 'type' , 'enabled' , 'lag ' , 'mac_address ' , 'mtu ' , 'mgmt_only ' , 'mark_connected ' ,
2834
- 'description' , 'mode' , 'untagged_vlan' , 'tagged_vlans' , 'tags' ,
2851
+ 'device' , 'name' , 'label' , 'type' , 'enabled' , 'parent ' , 'lag ' , 'mac_address ' , 'mtu ' , 'mgmt_only ' ,
2852
+ 'mark_connected' , ' description' , 'mode' , 'untagged_vlan' , 'tagged_vlans' , 'tags' ,
2835
2853
]
2836
2854
widgets = {
2837
2855
'device' : forms .HiddenInput (),
2838
2856
'type' : StaticSelect2 (),
2839
- 'lag' : StaticSelect2 (),
2840
2857
'mode' : StaticSelect2 (),
2841
2858
}
2842
2859
labels = {
@@ -2849,19 +2866,11 @@ class Meta:
2849
2866
def __init__ (self , * args , ** kwargs ):
2850
2867
super ().__init__ (* args , ** kwargs )
2851
2868
2852
- if self .is_bound :
2853
- device = Device .objects .get (pk = self .data ['device' ])
2854
- else :
2855
- device = self .instance .device
2869
+ device = Device .objects .get (pk = self .data ['device' ]) if self .is_bound else self .instance .device
2856
2870
2857
- # Limit LAG choices to interfaces belonging to this device or a peer VC member
2858
- device_query = Q (device = device )
2859
- if device .virtual_chassis :
2860
- device_query |= Q (device__virtual_chassis = device .virtual_chassis )
2861
- self .fields ['lag' ].queryset = Interface .objects .filter (
2862
- device_query ,
2863
- type = InterfaceTypeChoices .TYPE_LAG
2864
- ).exclude (pk = self .instance .pk )
2871
+ # Restrict parent/LAG interface assignment by device
2872
+ self .fields ['parent' ].widget .add_query_param ('device_id' , device .pk )
2873
+ self .fields ['lag' ].widget .add_query_param ('device_id' , device .pk )
2865
2874
2866
2875
# Add current site to VLANs query params
2867
2876
self .fields ['untagged_vlan' ].widget .add_query_param ('site_id' , device .site .pk )
@@ -2878,11 +2887,23 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm):
2878
2887
required = False ,
2879
2888
initial = True
2880
2889
)
2881
- lag = forms . ModelChoiceField (
2890
+ parent = DynamicModelChoiceField (
2882
2891
queryset = Interface .objects .all (),
2883
2892
required = False ,
2884
- label = 'Parent LAG' ,
2885
- widget = StaticSelect2 (),
2893
+ display_field = 'display_name' ,
2894
+ query_params = {
2895
+ 'device_id' : '$device' ,
2896
+ 'kind' : 'physical' ,
2897
+ }
2898
+ )
2899
+ lag = DynamicModelChoiceField (
2900
+ queryset = Interface .objects .all (),
2901
+ required = False ,
2902
+ display_field = 'display_name' ,
2903
+ query_params = {
2904
+ 'device_id' : '$device' ,
2905
+ 'type' : 'lag' ,
2906
+ }
2886
2907
)
2887
2908
mtu = forms .IntegerField (
2888
2909
required = False ,
@@ -2923,23 +2944,17 @@ class InterfaceCreateForm(ComponentCreateForm, InterfaceCommonForm):
2923
2944
}
2924
2945
)
2925
2946
field_order = (
2926
- 'device' , 'name_pattern' , 'label_pattern' , 'type' , 'enabled' , 'lag ' , 'mtu ' , 'mac_address ' , 'description ' ,
2927
- 'mgmt_only' , 'mark_connected' , 'mode' , 'untagged_vlan' , 'tagged_vlans' , 'tags'
2947
+ 'device' , 'name_pattern' , 'label_pattern' , 'type' , 'enabled' , 'parent ' , 'lag ' , 'mtu ' , 'mac_address ' ,
2948
+ 'description' , ' mgmt_only' , 'mark_connected' , 'mode' , 'untagged_vlan' , 'tagged_vlans' , 'tags'
2928
2949
)
2929
2950
2930
2951
def __init__ (self , * args , ** kwargs ):
2931
2952
super ().__init__ (* args , ** kwargs )
2932
2953
2933
- # Limit LAG choices to interfaces belonging to this device or a peer VC member
2954
+ # Add current site to VLANs query params
2934
2955
device = Device .objects .get (
2935
2956
pk = self .initial .get ('device' ) or self .data .get ('device' )
2936
2957
)
2937
- device_query = Q (device = device )
2938
- if device .virtual_chassis :
2939
- device_query |= Q (device__virtual_chassis = device .virtual_chassis )
2940
- self .fields ['lag' ].queryset = Interface .objects .filter (device_query , type = InterfaceTypeChoices .TYPE_LAG )
2941
-
2942
- # Add current site to VLANs query params
2943
2958
self .fields ['untagged_vlan' ].widget .add_query_param ('site_id' , device .site .pk )
2944
2959
self .fields ['tagged_vlans' ].widget .add_query_param ('site_id' , device .site .pk )
2945
2960
@@ -2956,7 +2971,7 @@ class InterfaceBulkCreateForm(
2956
2971
2957
2972
class InterfaceBulkEditForm (
2958
2973
form_from_model (Interface , [
2959
- 'label' , 'type' , 'lag' , 'mac_address' , 'mtu' , 'mgmt_only' , 'mark_connected' , 'description' , 'mode'
2974
+ 'label' , 'type' , 'parent' , ' lag' , 'mac_address' , 'mtu' , 'mgmt_only' , 'mark_connected' , 'description' , 'mode' ,
2960
2975
]),
2961
2976
BootstrapMixin ,
2962
2977
AddRemoveTagsForm ,
@@ -2976,6 +2991,22 @@ class InterfaceBulkEditForm(
2976
2991
required = False ,
2977
2992
widget = BulkEditNullBooleanSelect
2978
2993
)
2994
+ parent = DynamicModelChoiceField (
2995
+ queryset = Interface .objects .all (),
2996
+ required = False ,
2997
+ display_field = 'display_name' ,
2998
+ query_params = {
2999
+ 'kind' : 'physical' ,
3000
+ }
3001
+ )
3002
+ lag = DynamicModelChoiceField (
3003
+ queryset = Interface .objects .all (),
3004
+ required = False ,
3005
+ display_field = 'display_name' ,
3006
+ query_params = {
3007
+ 'type' : 'lag' ,
3008
+ }
3009
+ )
2979
3010
mgmt_only = forms .NullBooleanField (
2980
3011
required = False ,
2981
3012
widget = BulkEditNullBooleanSelect ,
@@ -3006,25 +3037,24 @@ class InterfaceBulkEditForm(
3006
3037
3007
3038
class Meta :
3008
3039
nullable_fields = [
3009
- 'label' , 'lag' , 'mac_address' , 'mtu' , 'description' , 'mode' , 'untagged_vlan' , 'tagged_vlans'
3040
+ 'label' , 'parent' , ' lag' , 'mac_address' , 'mtu' , 'description' , 'mode' , 'untagged_vlan' , 'tagged_vlans'
3010
3041
]
3011
3042
3012
3043
def __init__ (self , * args , ** kwargs ):
3013
3044
super ().__init__ (* args , ** kwargs )
3014
-
3015
- # Limit LAG choices to interfaces which belong to the parent device (or VC master)
3016
3045
if 'device' in self .initial :
3017
3046
device = Device .objects .filter (pk = self .initial ['device' ]).first ()
3018
- self . fields [ 'lag' ]. queryset = Interface . objects . filter (
3019
- device__in = [ device , device . get_vc_master ()],
3020
- type = InterfaceTypeChoices . TYPE_LAG
3021
- )
3047
+
3048
+ # Restrict parent/LAG interface assignment by device
3049
+ self . fields [ 'parent' ]. widget . add_query_param ( 'device_id' , device . pk )
3050
+ self . fields [ 'lag' ]. widget . add_query_param ( 'device_id' , device . pk )
3022
3051
3023
3052
# Add current site to VLANs query params
3024
3053
self .fields ['untagged_vlan' ].widget .add_query_param ('site_id' , device .site .pk )
3025
3054
self .fields ['tagged_vlans' ].widget .add_query_param ('site_id' , device .site .pk )
3055
+
3026
3056
else :
3027
- # See 4523
3057
+ # See # 4523
3028
3058
if 'pk' in self .initial :
3029
3059
site = None
3030
3060
interfaces = Interface .objects .filter (pk__in = self .initial ['pk' ]).prefetch_related ('device__site' )
@@ -3042,6 +3072,8 @@ def __init__(self, *args, **kwargs):
3042
3072
self .fields ['untagged_vlan' ].widget .add_query_param ('site_id' , site .pk )
3043
3073
self .fields ['tagged_vlans' ].widget .add_query_param ('site_id' , site .pk )
3044
3074
3075
+ self .fields ['parent' ].choices = ()
3076
+ self .fields ['parent' ].widget .attrs ['disabled' ] = True
3045
3077
self .fields ['lag' ].choices = ()
3046
3078
self .fields ['lag' ].widget .attrs ['disabled' ] = True
3047
3079
@@ -3064,6 +3096,12 @@ class InterfaceCSVForm(CustomFieldModelCSVForm):
3064
3096
queryset = Device .objects .all (),
3065
3097
to_field_name = 'name'
3066
3098
)
3099
+ parent = CSVModelChoiceField (
3100
+ queryset = Interface .objects .all (),
3101
+ required = False ,
3102
+ to_field_name = 'name' ,
3103
+ help_text = 'Parent interface'
3104
+ )
3067
3105
lag = CSVModelChoiceField (
3068
3106
queryset = Interface .objects .all (),
3069
3107
required = False ,
0 commit comments