class ConfigContextForm(BootstrapMixin, forms.ModelForm): data = JSONField() class Meta: model = ConfigContext fields = [ 'name', 'weight', 'description', 'is_active', 'regions', 'sites', 'roles', 'platforms', 'tenant_groups', 'tenants', 'data', ] widgets = { 'regions': APISelectMultiple(api_url="/api/dcim/regions/"), 'sites': APISelectMultiple(api_url="/api/dcim/sites/"), 'roles': APISelectMultiple(api_url="/api/dcim/device-roles/"), 'platforms': APISelectMultiple(api_url="/api/dcim/platforms/"), 'tenant_groups': APISelectMultiple(api_url="/api/tenancy/tenant-groups/"), 'tenants': APISelectMultiple(api_url="/api/tenancy/tenants/") }
class ConfigContextForm(BootstrapMixin, forms.ModelForm): regions = DynamicModelMultipleChoiceField( queryset=Region.objects.all(), required=False ) site_groups = DynamicModelMultipleChoiceField( queryset=SiteGroup.objects.all(), required=False ) sites = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False ) device_types = DynamicModelMultipleChoiceField( queryset=DeviceType.objects.all(), required=False ) roles = DynamicModelMultipleChoiceField( queryset=DeviceRole.objects.all(), required=False ) platforms = DynamicModelMultipleChoiceField( queryset=Platform.objects.all(), required=False ) cluster_groups = DynamicModelMultipleChoiceField( queryset=ClusterGroup.objects.all(), required=False ) clusters = DynamicModelMultipleChoiceField( queryset=Cluster.objects.all(), required=False ) tenant_groups = DynamicModelMultipleChoiceField( queryset=TenantGroup.objects.all(), required=False ) tenants = DynamicModelMultipleChoiceField( queryset=Tenant.objects.all(), required=False ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False ) data = JSONField( label='' ) class Meta: model = ConfigContext fields = ( 'name', 'weight', 'description', 'is_active', 'regions', 'site_groups', 'sites', 'roles', 'device_types', 'platforms', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', 'data', )
class ConfigContextForm(BootstrapMixin, forms.ModelForm): regions = TreeNodeMultipleChoiceField( queryset=Region.objects.all(), required=False ) data = JSONField() class Meta: model = ConfigContext fields = [ 'name', 'weight', 'description', 'is_active', 'regions', 'sites', 'roles', 'platforms', 'tenant_groups', 'tenants', 'data', ]
class ConfigContextForm(BootstrapMixin, forms.ModelForm): tags = forms.ModelMultipleChoiceField( queryset=Tag.objects.all(), to_field_name='slug', required=False, widget=APISelectMultiple(api_url="/api/extras/tags/")) data = JSONField(label='') class Meta: model = ConfigContext fields = [ 'name', 'weight', 'description', 'is_active', 'regions', 'sites', 'roles', 'platforms', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', 'data', ] widgets = { 'regions': APISelectMultiple(api_url="/api/dcim/regions/"), 'sites': APISelectMultiple(api_url="/api/dcim/sites/"), 'roles': APISelectMultiple(api_url="/api/dcim/device-roles/"), 'platforms': APISelectMultiple(api_url="/api/dcim/platforms/"), 'cluster_groups': APISelectMultiple(api_url="/api/virtualization/cluster-groups/"), 'clusters': APISelectMultiple(api_url="/api/virtualization/clusters/"), 'tenant_groups': APISelectMultiple(api_url="/api/tenancy/tenant-groups/"), 'tenants': APISelectMultiple(api_url="/api/tenancy/tenants/"), }
class DeviceForm(TenancyForm, CustomFieldModelForm): region = DynamicModelChoiceField(queryset=Region.objects.all(), required=False, initial_params={'sites': '$site'}) site_group = DynamicModelChoiceField(queryset=SiteGroup.objects.all(), required=False, initial_params={'sites': '$site'}) site = DynamicModelChoiceField(queryset=Site.objects.all(), query_params={ 'region_id': '$region', 'group_id': '$site_group', }) location = DynamicModelChoiceField(queryset=Location.objects.all(), required=False, query_params={'site_id': '$site'}, initial_params={'racks': '$rack'}) rack = DynamicModelChoiceField(queryset=Rack.objects.all(), required=False, query_params={ 'site_id': '$site', 'location_id': '$location', }) position = forms.IntegerField( required=False, help_text="The lowest-numbered unit occupied by the device", widget=APISelect(api_url='/api/dcim/racks/{{rack}}/elevation/', attrs={ 'disabled-indicator': 'device', 'data-dynamic-params': '[{"fieldName":"face","queryParam":"face"}]' })) manufacturer = DynamicModelChoiceField( queryset=Manufacturer.objects.all(), required=False, initial_params={'device_types': '$device_type'}) device_type = DynamicModelChoiceField( queryset=DeviceType.objects.all(), query_params={'manufacturer_id': '$manufacturer'}) device_role = DynamicModelChoiceField(queryset=DeviceRole.objects.all()) platform = DynamicModelChoiceField( queryset=Platform.objects.all(), required=False, query_params={'manufacturer_id': ['$manufacturer', 'null']}) cluster_group = DynamicModelChoiceField( queryset=ClusterGroup.objects.all(), required=False, null_option='None', initial_params={'clusters': '$cluster'}) cluster = DynamicModelChoiceField( queryset=Cluster.objects.all(), required=False, query_params={'group_id': '$cluster_group'}) comments = CommentField() local_context_data = JSONField(required=False, label='') tags = DynamicModelMultipleChoiceField(queryset=Tag.objects.all(), required=False) class Meta: model = Device fields = [ 'name', 'device_role', 'device_type', 'serial', 'asset_tag', 'region', 'site_group', 'site', 'rack', 'location', 'position', 'face', 'status', 'airflow', 'platform', 'primary_ip4', 'primary_ip6', 'cluster_group', 'cluster', 'tenant_group', 'tenant', 'comments', 'tags', 'local_context_data' ] help_texts = { 'device_role': "The function this device serves", 'serial': "Chassis serial number", 'local_context_data': "Local config context data overwrites all source contexts in the final rendered " "config context", } widgets = { 'face': StaticSelect(), 'status': StaticSelect(), 'airflow': StaticSelect(), 'primary_ip4': StaticSelect(), 'primary_ip6': StaticSelect(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.instance.pk: # Compile list of choices for primary IPv4 and IPv6 addresses for family in [4, 6]: ip_choices = [(None, '---------')] # Gather PKs of all interfaces belonging to this Device or a peer VirtualChassis member interface_ids = self.instance.vc_interfaces( if_master=False).values_list('pk', flat=True) # Collect interface IPs interface_ips = IPAddress.objects.filter( address__family=family, assigned_object_type=ContentType.objects.get_for_model( Interface), assigned_object_id__in=interface_ids).prefetch_related( 'assigned_object') if interface_ips: ip_list = [(ip.id, f'{ip.address} ({ip.assigned_object})') for ip in interface_ips] ip_choices.append(('Interface IPs', ip_list)) # Collect NAT IPs nat_ips = IPAddress.objects.prefetch_related( 'nat_inside').filter( address__family=family, nat_inside__assigned_object_type=ContentType.objects. get_for_model(Interface), nat_inside__assigned_object_id__in=interface_ids ).prefetch_related('assigned_object') if nat_ips: ip_list = [(ip.id, f'{ip.address} (NAT)') for ip in nat_ips] ip_choices.append(('NAT IPs', ip_list)) self.fields['primary_ip{}'.format(family)].choices = ip_choices # If editing an existing device, exclude it from the list of occupied rack units. This ensures that a device # can be flipped from one face to another. self.fields['position'].widget.add_query_param( 'exclude', self.instance.pk) # Limit platform by manufacturer self.fields['platform'].queryset = Platform.objects.filter( Q(manufacturer__isnull=True) | Q(manufacturer=self.instance.device_type.manufacturer)) # Disable rack assignment if this is a child device installed in a parent device if self.instance.device_type.is_child_device and hasattr( self.instance, 'parent_bay'): self.fields['site'].disabled = True self.fields['rack'].disabled = True self.initial['site'] = self.instance.parent_bay.device.site_id self.initial['rack'] = self.instance.parent_bay.device.rack_id else: # An object that doesn't exist yet can't have any IPs assigned to it self.fields['primary_ip4'].choices = [] self.fields['primary_ip4'].widget.attrs['readonly'] = True self.fields['primary_ip6'].choices = [] self.fields['primary_ip6'].widget.attrs['readonly'] = True # Rack position position = self.data.get('position') or self.initial.get('position') if position: self.fields['position'].widget.choices = [(position, f'U{position}')]
class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): cluster_group = DynamicModelChoiceField( queryset=ClusterGroup.objects.all(), required=False, widget=APISelect(filter_for={ "cluster": "group_id", }, attrs={ 'nullable': 'true', })) cluster = DynamicModelChoiceField(queryset=Cluster.objects.all()) role = DynamicModelChoiceField( queryset=DeviceRole.objects.all(), required=False, widget=APISelect(additional_query_params={"vm_role": "True"})) platform = DynamicModelChoiceField(queryset=Platform.objects.all(), required=False) tags = TagField(required=False) local_context_data = JSONField(required=False, label='') class Meta: model = VirtualMachine fields = [ 'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant_group', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'vcpus', 'memory', 'disk', 'comments', 'tags', 'local_context_data', ] help_texts = { 'local_context_data': "Local config context data overwrites all sources contexts in the final rendered " "config context", } widgets = { "status": StaticSelect2(), 'primary_ip4': StaticSelect2(), 'primary_ip6': StaticSelect2(), } def __init__(self, *args, **kwargs): # Initialize helper selector instance = kwargs.get('instance') if instance.pk and instance.cluster is not None: initial = kwargs.get('initial', {}).copy() initial['cluster_group'] = instance.cluster.group kwargs['initial'] = initial super().__init__(*args, **kwargs) if self.instance.pk: # Compile list of choices for primary IPv4 and IPv6 addresses for family in [4, 6]: ip_choices = [(None, '---------')] # Collect interface IPs interface_ips = IPAddress.objects.prefetch_related( 'interface').filter( family=family, interface__virtual_machine=self.instance) if interface_ips: ip_choices.append(('Interface IPs', [ (ip.id, '{} ({})'.format(ip.address, ip.interface)) for ip in interface_ips ])) # Collect NAT IPs nat_ips = IPAddress.objects.prefetch_related( 'nat_inside').filter( family=family, nat_inside__interface__virtual_machine=self.instance) if nat_ips: ip_choices.append(('NAT IPs', [ (ip.id, '{} ({})'.format(ip.address, ip.nat_inside.address)) for ip in nat_ips ])) self.fields['primary_ip{}'.format(family)].choices = ip_choices else: # An object that doesn't exist yet can't have any IPs assigned to it self.fields['primary_ip4'].choices = [] self.fields['primary_ip4'].widget.attrs['readonly'] = True self.fields['primary_ip6'].choices = [] self.fields['primary_ip6'].widget.attrs['readonly'] = True
class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldModelForm): cluster_group = DynamicModelChoiceField( queryset=ClusterGroup.objects.all(), required=False, null_option='None', initial_params={ 'clusters': '$cluster' } ) cluster = DynamicModelChoiceField( queryset=Cluster.objects.all(), query_params={ 'group_id': '$cluster_group' } ) role = DynamicModelChoiceField( queryset=DeviceRole.objects.all(), required=False, query_params={ "vm_role": "True" } ) platform = DynamicModelChoiceField( queryset=Platform.objects.all(), required=False ) local_context_data = JSONField( required=False, label='' ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), required=False ) class Meta: model = VirtualMachine fields = [ 'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant_group', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'vcpus', 'memory', 'disk', 'comments', 'tags', 'local_context_data', ] help_texts = { 'local_context_data': "Local config context data overwrites all sources contexts in the final rendered " "config context", } widgets = { "status": StaticSelect2(), 'primary_ip4': StaticSelect2(), 'primary_ip6': StaticSelect2(), } def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) if self.instance.pk: # Compile list of choices for primary IPv4 and IPv6 addresses for family in [4, 6]: ip_choices = [(None, '---------')] # Gather PKs of all interfaces belonging to this VM interface_ids = self.instance.interfaces.values_list('pk', flat=True) # Collect interface IPs interface_ips = IPAddress.objects.filter( address__family=family, assigned_object_type=ContentType.objects.get_for_model(VMInterface), assigned_object_id__in=interface_ids ) if interface_ips: ip_list = [(ip.id, f'{ip.address} ({ip.assigned_object})') for ip in interface_ips] ip_choices.append(('Interface IPs', ip_list)) # Collect NAT IPs nat_ips = IPAddress.objects.prefetch_related('nat_inside').filter( address__family=family, nat_inside__assigned_object_type=ContentType.objects.get_for_model(VMInterface), nat_inside__assigned_object_id__in=interface_ids ) if nat_ips: ip_list = [(ip.id, f'{ip.address} (NAT)') for ip in nat_ips] ip_choices.append(('NAT IPs', ip_list)) self.fields['primary_ip{}'.format(family)].choices = ip_choices else: # An object that doesn't exist yet can't have any IPs assigned to it self.fields['primary_ip4'].choices = [] self.fields['primary_ip4'].widget.attrs['readonly'] = True self.fields['primary_ip6'].choices = [] self.fields['primary_ip6'].widget.attrs['readonly'] = True
class VirtualMachineForm(BootstrapMixin, TenancyForm, CustomFieldForm): cluster_group = forms.ModelChoiceField( queryset=ClusterGroup.objects.all(), required=False, widget=forms.Select(attrs={ 'filter-for': 'cluster', 'nullable': 'true' })) cluster = ChainedModelChoiceField( queryset=Cluster.objects.all(), chains=(('group', 'cluster_group'), ), widget=APISelect( api_url='/api/virtualization/clusters/?group_id={{cluster_group}}') ) tags = TagField(required=False) local_context_data = JSONField(required=False) class Meta: model = VirtualMachine fields = [ 'name', 'status', 'cluster_group', 'cluster', 'role', 'tenant', 'platform', 'primary_ip4', 'primary_ip6', 'vcpus', 'memory', 'disk', 'comments', 'tags', 'local_context_data', ] help_texts = { 'local_context_data': "Local config context data overwrites all sources contexts in the final rendered config context", } def __init__(self, *args, **kwargs): # Initialize helper selector instance = kwargs.get('instance') if instance.pk and instance.cluster is not None: initial = kwargs.get('initial', {}).copy() initial['cluster_group'] = instance.cluster.group kwargs['initial'] = initial super(VirtualMachineForm, self).__init__(*args, **kwargs) if self.instance.pk: # Compile list of choices for primary IPv4 and IPv6 addresses for family in [4, 6]: ip_choices = [(None, '---------')] # Collect interface IPs interface_ips = IPAddress.objects.select_related( 'interface').filter( family=family, interface__virtual_machine=self.instance) if interface_ips: ip_choices.append(('Interface IPs', [ (ip.id, '{} ({})'.format(ip.address, ip.interface)) for ip in interface_ips ])) # Collect NAT IPs nat_ips = IPAddress.objects.select_related( 'nat_inside').filter( family=family, nat_inside__interface__virtual_machine=self.instance) if nat_ips: ip_choices.append(('NAT IPs', [ (ip.id, '{} ({})'.format(ip.address, ip.nat_inside.address)) for ip in nat_ips ])) self.fields['primary_ip{}'.format(family)].choices = ip_choices else: # An object that doesn't exist yet can't have any IPs assigned to it self.fields['primary_ip4'].choices = [] self.fields['primary_ip4'].widget.attrs['readonly'] = True self.fields['primary_ip6'].choices = [] self.fields['primary_ip6'].widget.attrs['readonly'] = True
class ConfigContextForm(BootstrapMixin, forms.ModelForm): regions = TreeNodeMultipleChoiceField( queryset=Region.objects.all(), required=False, widget=StaticSelect2Multiple() ) sites = DynamicModelMultipleChoiceField( queryset=Site.objects.all(), required=False, widget=APISelectMultiple( api_url="/api/dcim/sites/" ) ) roles = DynamicModelMultipleChoiceField( queryset=DeviceRole.objects.all(), required=False, widget=APISelectMultiple( api_url="/api/dcim/device-roles/" ) ) platforms = DynamicModelMultipleChoiceField( queryset=Platform.objects.all(), required=False, widget=APISelectMultiple( api_url="/api/dcim/platforms/" ) ) cluster_groups = DynamicModelMultipleChoiceField( queryset=ClusterGroup.objects.all(), required=False, widget=APISelectMultiple( api_url="/api/virtualization/cluster-groups/" ) ) clusters = DynamicModelMultipleChoiceField( queryset=Cluster.objects.all(), required=False, widget=APISelectMultiple( api_url="/api/virtualization/clusters/" ) ) tenant_groups = DynamicModelMultipleChoiceField( queryset=TenantGroup.objects.all(), required=False, widget=APISelectMultiple( api_url="/api/tenancy/tenant-groups/" ) ) tenants = DynamicModelMultipleChoiceField( queryset=Tenant.objects.all(), required=False, widget=APISelectMultiple( api_url="/api/tenancy/tenants/" ) ) tags = DynamicModelMultipleChoiceField( queryset=Tag.objects.all(), to_field_name='slug', required=False, widget=APISelectMultiple( api_url="/api/extras/tags/" ) ) data = JSONField( label='' ) class Meta: model = ConfigContext fields = ( 'name', 'weight', 'description', 'is_active', 'regions', 'sites', 'roles', 'platforms', 'cluster_groups', 'clusters', 'tenant_groups', 'tenants', 'tags', 'data', )