diff --git a/netbox/dcim/api/serializers.py b/netbox/dcim/api/serializers.py index a0d33d004..9c134bc94 100644 --- a/netbox/dcim/api/serializers.py +++ b/netbox/dcim/api/serializers.py @@ -461,10 +461,11 @@ class DeviceWithConfigContextSerializer(DeviceSerializer): class ConsoleServerPortSerializer(ValidatedModelSerializer): device = NestedDeviceSerializer() + tags = TagField(queryset=Tag.objects.all(), required=False, many=True) class Meta: model = ConsoleServerPort - fields = ['id', 'device', 'name', 'connected_console'] + fields = ['id', 'device', 'name', 'connected_console', 'tags'] read_only_fields = ['connected_console'] @@ -484,10 +485,11 @@ class NestedConsoleServerPortSerializer(WritableNestedSerializer): class ConsolePortSerializer(ValidatedModelSerializer): device = NestedDeviceSerializer() cs_port = NestedConsoleServerPortSerializer(required=False, allow_null=True) + tags = TagField(queryset=Tag.objects.all(), required=False, many=True) class Meta: model = ConsolePort - fields = ['id', 'device', 'name', 'cs_port', 'connection_status'] + fields = ['id', 'device', 'name', 'cs_port', 'connection_status', 'tags'] # @@ -496,10 +498,11 @@ class ConsolePortSerializer(ValidatedModelSerializer): class PowerOutletSerializer(ValidatedModelSerializer): device = NestedDeviceSerializer() + tags = TagField(queryset=Tag.objects.all(), required=False, many=True) class Meta: model = PowerOutlet - fields = ['id', 'device', 'name', 'connected_port'] + fields = ['id', 'device', 'name', 'connected_port', 'tags'] read_only_fields = ['connected_port'] @@ -519,10 +522,11 @@ class NestedPowerOutletSerializer(WritableNestedSerializer): class PowerPortSerializer(ValidatedModelSerializer): device = NestedDeviceSerializer() power_outlet = NestedPowerOutletSerializer(required=False, allow_null=True) + tags = TagField(queryset=Tag.objects.all(), required=False, many=True) class Meta: model = PowerPort - fields = ['id', 'device', 'name', 'power_outlet', 'connection_status'] + fields = ['id', 'device', 'name', 'power_outlet', 'connection_status', 'tags'] # @@ -580,12 +584,14 @@ class InterfaceSerializer(ValidatedModelSerializer): required=False, many=True ) + tags = TagField(queryset=Tag.objects.all(), required=False, many=True) class Meta: model = Interface fields = [ 'id', 'device', 'name', 'form_factor', 'enabled', 'lag', 'mtu', 'mac_address', 'mgmt_only', 'description', 'is_connected', 'interface_connection', 'circuit_termination', 'mode', 'untagged_vlan', 'tagged_vlans', + 'tags', ] def validate(self, data): @@ -637,10 +643,11 @@ class InterfaceSerializer(ValidatedModelSerializer): class DeviceBaySerializer(ValidatedModelSerializer): device = NestedDeviceSerializer() installed_device = NestedDeviceSerializer(required=False, allow_null=True) + tags = TagField(queryset=Tag.objects.all(), required=False, many=True) class Meta: model = DeviceBay - fields = ['id', 'device', 'name', 'installed_device'] + fields = ['id', 'device', 'name', 'installed_device', 'tags'] class NestedDeviceBaySerializer(WritableNestedSerializer): @@ -660,12 +667,13 @@ class InventoryItemSerializer(ValidatedModelSerializer): # Provide a default value to satisfy UniqueTogetherValidator parent = serializers.PrimaryKeyRelatedField(queryset=InventoryItem.objects.all(), allow_null=True, default=None) manufacturer = NestedManufacturerSerializer() + tags = TagField(queryset=Tag.objects.all(), required=False, many=True) class Meta: model = InventoryItem fields = [ 'id', 'device', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'discovered', - 'description', + 'description', 'tags', ] @@ -712,10 +720,11 @@ class ContextualInterfaceConnectionSerializer(serializers.ModelSerializer): class VirtualChassisSerializer(ValidatedModelSerializer): master = NestedDeviceSerializer() + tags = TagField(queryset=Tag.objects.all(), required=False, many=True) class Meta: model = VirtualChassis - fields = ['id', 'master', 'domain'] + fields = ['id', 'master', 'domain', 'tags'] class NestedVirtualChassisSerializer(WritableNestedSerializer): diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index d617c6c04..a159e19e4 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -1180,10 +1180,11 @@ class DeviceBulkAddInterfaceForm(DeviceBulkAddComponentForm): # class ConsolePortForm(BootstrapMixin, forms.ModelForm): + tags = TagField(required=False) class Meta: model = ConsolePort - fields = ['device', 'name'] + fields = ['device', 'name', 'tags'] widgets = { 'device': forms.HiddenInput(), } @@ -1349,10 +1350,11 @@ class ConsolePortConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelF # class ConsoleServerPortForm(BootstrapMixin, forms.ModelForm): + tags = TagField(required=False) class Meta: model = ConsoleServerPort - fields = ['device', 'name'] + fields = ['device', 'name', 'tags'] widgets = { 'device': forms.HiddenInput(), } @@ -1445,10 +1447,11 @@ class ConsoleServerPortBulkDisconnectForm(ConfirmationForm): # class PowerPortForm(BootstrapMixin, forms.ModelForm): + tags = TagField(required=False) class Meta: model = PowerPort - fields = ['device', 'name'] + fields = ['device', 'name', 'tags'] widgets = { 'device': forms.HiddenInput(), } @@ -1614,10 +1617,11 @@ class PowerPortConnectionForm(BootstrapMixin, ChainedFieldsMixin, forms.ModelFor # class PowerOutletForm(BootstrapMixin, forms.ModelForm): + tags = TagField(required=False) class Meta: model = PowerOutlet - fields = ['device', 'name'] + fields = ['device', 'name', 'tags'] widgets = { 'device': forms.HiddenInput(), } @@ -1710,12 +1714,13 @@ class PowerOutletBulkDisconnectForm(ConfirmationForm): # class InterfaceForm(BootstrapMixin, forms.ModelForm): + tags = TagField(required=False) class Meta: model = Interface fields = [ 'device', 'name', 'form_factor', 'enabled', 'lag', 'mac_address', 'mtu', 'mgmt_only', 'description', - 'mode', 'untagged_vlan', 'tagged_vlans', + 'mode', 'untagged_vlan', 'tagged_vlans', 'tags', ] widgets = { 'device': forms.HiddenInput(), @@ -2082,10 +2087,11 @@ class InterfaceConnectionCSVForm(forms.ModelForm): # class DeviceBayForm(BootstrapMixin, forms.ModelForm): + tags = TagField(required=False) class Meta: model = DeviceBay - fields = ['device', 'name'] + fields = ['device', 'name', 'tags'] widgets = { 'device': forms.HiddenInput(), } @@ -2143,10 +2149,11 @@ class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form): # class InventoryItemForm(BootstrapMixin, forms.ModelForm): + tags = TagField(required=False) class Meta: model = InventoryItem - fields = ['name', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description'] + fields = ['name', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'description', 'tags'] class InventoryItemCSVForm(forms.ModelForm): @@ -2202,10 +2209,11 @@ class DeviceSelectionForm(forms.Form): class VirtualChassisForm(BootstrapMixin, forms.ModelForm): + tags = TagField(required=False) class Meta: model = VirtualChassis - fields = ['master', 'domain'] + fields = ['master', 'domain', 'tags'] widgets = { 'master': SelectWithPK, } diff --git a/netbox/dcim/migrations/0057_tags.py b/netbox/dcim/migrations/0057_tags.py index 04db38d5d..b0cccfdf3 100644 --- a/netbox/dcim/migrations/0057_tags.py +++ b/netbox/dcim/migrations/0057_tags.py @@ -34,4 +34,44 @@ class Migration(migrations.Migration): name='tags', field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), ), + migrations.AddField( + model_name='consoleport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='consoleserverport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='devicebay', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='interface', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='inventoryitem', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='poweroutlet', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='powerport', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), + migrations.AddField( + model_name='virtualchassis', + name='tags', + field=taggit.managers.TaggableManager(help_text='A comma-separated list of tags.', through='taggit.TaggedItem', to='taggit.Tag', verbose_name='Tags'), + ), ] diff --git a/netbox/dcim/models.py b/netbox/dcim/models.py index c2b471e89..a7e5c9ee7 100644 --- a/netbox/dcim/models.py +++ b/netbox/dcim/models.py @@ -1584,6 +1584,8 @@ class ConsolePort(ComponentModel): default=CONNECTION_STATUS_CONNECTED ) + tags = TaggableManager() + csv_headers = ['console_server', 'cs_port', 'device', 'console_port', 'connection_status'] class Meta: @@ -1638,6 +1640,7 @@ class ConsoleServerPort(ComponentModel): ) objects = ConsoleServerPortManager() + tags = TaggableManager() class Meta: unique_together = ['device', 'name'] @@ -1692,6 +1695,8 @@ class PowerPort(ComponentModel): default=CONNECTION_STATUS_CONNECTED ) + tags = TaggableManager() + csv_headers = ['pdu', 'power_outlet', 'device', 'power_port', 'connection_status'] class Meta: @@ -1746,6 +1751,7 @@ class PowerOutlet(ComponentModel): ) objects = PowerOutletManager() + tags = TaggableManager() class Meta: unique_together = ['device', 'name'] @@ -1853,6 +1859,7 @@ class Interface(ComponentModel): ) objects = InterfaceQuerySet.as_manager() + tags = TaggableManager() serializer = 'dcim.api.serializers.InterfaceSerializer' @@ -2114,6 +2121,8 @@ class DeviceBay(ComponentModel): null=True ) + tags = TaggableManager() + class Meta: ordering = ['device', 'name'] unique_together = ['device', 'name'] @@ -2200,6 +2209,8 @@ class InventoryItem(ComponentModel): blank=True ) + tags = TaggableManager() + csv_headers = [ 'device', 'name', 'manufacturer', 'part_id', 'serial', 'asset_tag', 'discovered', 'description', ] @@ -2249,6 +2260,8 @@ class VirtualChassis(ChangeLoggedModel): blank=True ) + tags = TaggableManager() + serializer = 'dcim.api.serializers.VirtualChassisSerializer' class Meta: