diff --git a/netbox/dcim/filters.py b/netbox/dcim/filters.py index 00b227f97..9d9425f9c 100644 --- a/netbox/dcim/filters.py +++ b/netbox/dcim/filters.py @@ -441,6 +441,10 @@ class InterfaceFilter(DeviceComponentFilterSet): method='filter_type', label='Interface type', ) + mac_address = django_filters.CharFilter( + method='_mac_address', + label='MAC address', + ) class Meta: model = Interface @@ -456,6 +460,15 @@ class InterfaceFilter(DeviceComponentFilterSet): return queryset.filter(form_factor=IFACE_FF_LAG) return queryset + def _mac_address(self, queryset, name, value): + value = value.strip() + if not value: + return queryset + try: + return queryset.filter(mac_address=value) + except AddrFormatError: + return queryset.none() + class DeviceBayFilter(DeviceComponentFilterSet): @@ -476,42 +489,58 @@ class ConsoleConnectionFilter(django_filters.FilterSet): method='filter_site', label='Site (slug)', ) - - class Meta: - model = ConsoleServerPort - fields = [] + device = django_filters.CharFilter( + method='filter_device', + label='Device', + ) def filter_site(self, queryset, name, value): if not value.strip(): return queryset return queryset.filter(cs_port__device__site__slug=value) + def filter_device(self, queryset, name, value): + if not value.strip(): + return queryset + return queryset.filter( + Q(device__name__icontains=value) | + Q(cs_port__device__name__icontains=value) + ) + class PowerConnectionFilter(django_filters.FilterSet): site = django_filters.CharFilter( method='filter_site', label='Site (slug)', ) - - class Meta: - model = PowerOutlet - fields = [] + device = django_filters.CharFilter( + method='filter_device', + label='Device', + ) def filter_site(self, queryset, name, value): if not value.strip(): return queryset return queryset.filter(power_outlet__device__site__slug=value) + def filter_device(self, queryset, name, value): + if not value.strip(): + return queryset + return queryset.filter( + Q(device__name__icontains=value) | + Q(power_outlet__device__name__icontains=value) + ) + class InterfaceConnectionFilter(django_filters.FilterSet): site = django_filters.CharFilter( method='filter_site', label='Site (slug)', ) - - class Meta: - model = InterfaceConnection - fields = [] + device = django_filters.CharFilter( + method='filter_device', + label='Device', + ) def filter_site(self, queryset, name, value): if not value.strip(): @@ -520,3 +549,11 @@ class InterfaceConnectionFilter(django_filters.FilterSet): Q(interface_a__device__site__slug=value) | Q(interface_b__device__site__slug=value) ) + + def filter_device(self, queryset, name, value): + if not value.strip(): + return queryset + return queryset.filter( + Q(interface_a__device__name__icontains=value) | + Q(interface_b__device__name__icontains=value) + ) diff --git a/netbox/dcim/forms.py b/netbox/dcim/forms.py index c8e88f16b..8f3e73e04 100644 --- a/netbox/dcim/forms.py +++ b/netbox/dcim/forms.py @@ -23,7 +23,7 @@ from .models import ( Interface, IFACE_FF_CHOICES, IFACE_FF_LAG, IFACE_ORDERING_CHOICES, InterfaceConnection, InterfaceTemplate, Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, RACK_TYPE_CHOICES, RACK_WIDTH_CHOICES, Rack, RackGroup, RackReservation, RackRole, Region, Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHILD, - VIRTUAL_IFACE_TYPES + SUBDEVICE_ROLE_PARENT, VIRTUAL_IFACE_TYPES ) @@ -375,6 +375,21 @@ class DeviceTypeFilterForm(BootstrapMixin, CustomFieldFilterForm): queryset=Manufacturer.objects.annotate(filter_count=Count('device_types')), to_field_name='slug' ) + is_console_server = forms.BooleanField( + required=False, label='Is a console server', widget=forms.CheckboxInput(attrs={'value': 'True'})) + is_pdu = forms.BooleanField( + required=False, label='Is a PDU', widget=forms.CheckboxInput(attrs={'value': 'True'}) + ) + is_network_device = forms.BooleanField( + required=False, label='Is a network device', widget=forms.CheckboxInput(attrs={'value': 'True'}) + ) + subdevice_role = forms.NullBooleanField( + required=False, label='Subdevice role', widget=forms.Select(choices=( + ('', '---------'), + (SUBDEVICE_ROLE_PARENT, 'Parent'), + (SUBDEVICE_ROLE_CHILD, 'Child'), + )) + ) # @@ -1643,14 +1658,17 @@ class PopulateDeviceBayForm(BootstrapMixin, forms.Form): class ConsoleConnectionFilterForm(BootstrapMixin, forms.Form): site = forms.ModelChoiceField(required=False, queryset=Site.objects.all(), to_field_name='slug') + device = forms.CharField(required=False, label='Device name') class PowerConnectionFilterForm(BootstrapMixin, forms.Form): site = forms.ModelChoiceField(required=False, queryset=Site.objects.all(), to_field_name='slug') + device = forms.CharField(required=False, label='Device name') class InterfaceConnectionFilterForm(BootstrapMixin, forms.Form): site = forms.ModelChoiceField(required=False, queryset=Site.objects.all(), to_field_name='slug') + device = forms.CharField(required=False, label='Device name') # diff --git a/netbox/dcim/tables.py b/netbox/dcim/tables.py index afe527ab7..c4c7c5b73 100644 --- a/netbox/dcim/tables.py +++ b/netbox/dcim/tables.py @@ -100,6 +100,10 @@ DEVICE_PRIMARY_IP = """ {{ record.primary_ip4.address.ip|default:"" }} """ +SUBDEVICE_ROLE_TEMPLATE = """ +{% if record.subdevice_role == True %}Parent{% elif record.subdevice_role == False %}Child{% else %}—{% endif %} +""" + UTILIZATION_GRAPH = """ {% load helpers %} {% utilization_graph value %} @@ -249,11 +253,18 @@ class DeviceTypeTable(BaseTable): model = tables.LinkColumn('dcim:devicetype', args=[Accessor('pk')], verbose_name='Device Type') part_number = tables.Column(verbose_name='Part Number') is_full_depth = tables.BooleanColumn(verbose_name='Full Depth') + is_console_server = tables.BooleanColumn(verbose_name='CS') + is_pdu = tables.BooleanColumn(verbose_name='PDU') + is_network_device = tables.BooleanColumn(verbose_name='Net') + subdevice_role = tables.TemplateColumn(SUBDEVICE_ROLE_TEMPLATE, verbose_name='Subdevice Role') instance_count = tables.Column(verbose_name='Instances') class Meta(BaseTable.Meta): model = DeviceType - fields = ('pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'instance_count') + fields = ( + 'pk', 'model', 'manufacturer', 'part_number', 'u_height', 'is_full_depth', 'is_console_server', 'is_pdu', + 'is_network_device', 'subdevice_role', 'instance_count' + ) # diff --git a/netbox/netbox/settings.py b/netbox/netbox/settings.py index c738d88aa..aeec93f06 100644 --- a/netbox/netbox/settings.py +++ b/netbox/netbox/settings.py @@ -13,7 +13,7 @@ except ImportError: ) -VERSION = '2.0-beta1' +VERSION = '2.0.0-dev' # Import local configuration ALLOWED_HOSTS = DATABASE = SECRET_KEY = None diff --git a/netbox/templates/dcim/device_import.html b/netbox/templates/dcim/device_import.html index c3915b9c3..50d2f81db 100644 --- a/netbox/templates/dcim/device_import.html +++ b/netbox/templates/dcim/device_import.html @@ -73,7 +73,7 @@