Skip to content

Commit

Permalink
Renamed Module to InventoryItem (prep for #824)
Browse files Browse the repository at this point in the history
  • Loading branch information
jeremystretch committed Mar 21, 2017
1 parent 122526a commit 22768ff
Show file tree
Hide file tree
Showing 18 changed files with 192 additions and 200 deletions.
10 changes: 5 additions & 5 deletions docs/data-model/dcim.md
Original file line number Diff line number Diff line change
Expand Up @@ -93,9 +93,12 @@ A device's platform is used to denote the type of software running on it. This c

The assignment of platforms to devices is an optional feature, and may be disregarded if not desired.

### Modules
### Inventory Items

A device can be assigned modules which represent internal components. Currently, these are used merely for inventory tracking, although future development might see their functionality expand. Each module can optionally be assigned to a manufacturer.
Inventory items represent hardware components installed within a device, such as a power supply or CPU. Currently, these are used merely for inventory tracking, although future development might see their functionality expand. Each item can optionally be assigned a manufacturer.

!!! note
Prior to version 2.0, inventory items were called modules.

### Components

Expand All @@ -113,6 +116,3 @@ Console ports connect only to console server ports, and power ports connect only
Each interface is a assigned a form factor denoting its physical properties. Two special form factors exist: the "virtual" form factor can be used to designate logical interfaces (such as SVIs), and the "LAG" form factor can be used to desinate link aggregation groups to which physical interfaces can be assigned. Each interface can also be designated as management-only (for out-of-band management) and assigned a short description.

Device bays represent the ability of a device to house child devices. For example, you might install four blade servers into a 2U chassis. The chassis would appear in the rack elevation as a 2U device with four device bays. Each server within it would be defined as a 0U device installed in one of the device bays. Child devices do not appear on rack elevations, but they are included in the "Non-Racked Devices" list within the rack view.

!!! note
Child devices differ from modules in that they are still treated as independent devices, with their own console/power/data components, modules, and IP addresses. Modules, on the other hand, are parts within a device, such as a hard disk or power supply, which do not provide their own management plane.
8 changes: 4 additions & 4 deletions netbox/dcim/admin.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

from .models import (
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceTemplate, Manufacturer, Module, Platform,
DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceTemplate, Manufacturer, InventoryItem, Platform,
PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, Region,
Site,
)
Expand Down Expand Up @@ -183,8 +183,8 @@ class DeviceBayAdmin(admin.TabularInline):
readonly_fields = ['installed_device']


class ModuleAdmin(admin.TabularInline):
model = Module
class InventoryItemAdmin(admin.TabularInline):
model = InventoryItem
readonly_fields = ['parent', 'discovered']


Expand All @@ -197,7 +197,7 @@ class DeviceAdmin(admin.ModelAdmin):
PowerOutletAdmin,
InterfaceAdmin,
DeviceBayAdmin,
ModuleAdmin,
InventoryItemAdmin,
]
list_display = ['display_name', 'device_type_full_name', 'device_role', 'primary_ip', 'rack', 'position', 'asset_tag',
'serial']
Expand Down
12 changes: 6 additions & 6 deletions netbox/dcim/api/serializers.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
from dcim.models import (
CONNECTION_STATUS_CHOICES, ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device,
DeviceBay, DeviceBayTemplate, DeviceType, DeviceRole, IFACE_FF_CHOICES, IFACE_ORDERING_CHOICES, Interface,
InterfaceConnection, InterfaceTemplate, Manufacturer, Module, Platform, PowerOutlet, PowerOutletTemplate, PowerPort,
InterfaceConnection, InterfaceTemplate, Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort,
PowerPortTemplate, Rack, RackGroup, RackReservation, RackRole, RACK_FACE_CHOICES, RACK_TYPE_CHOICES,
RACK_WIDTH_CHOICES, Region, Site, STATUS_CHOICES, SUBDEVICE_ROLE_CHOICES,
)
Expand Down Expand Up @@ -642,22 +642,22 @@ class Meta:


#
# Modules
# Inventory items
#

class ModuleSerializer(serializers.ModelSerializer):
class InventoryItemSerializer(serializers.ModelSerializer):
device = NestedDeviceSerializer()
manufacturer = NestedManufacturerSerializer()

class Meta:
model = Module
model = InventoryItem
fields = ['id', 'device', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']


class WritableModuleSerializer(serializers.ModelSerializer):
class WritableInventoryItemSerializer(serializers.ModelSerializer):

class Meta:
model = Module
model = InventoryItem
fields = ['id', 'device', 'parent', 'name', 'manufacturer', 'part_id', 'serial', 'discovered']


Expand Down
2 changes: 1 addition & 1 deletion netbox/dcim/api/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@ def get_view_name(self):
router.register(r'power-outlets', views.PowerOutletViewSet)
router.register(r'interfaces', views.InterfaceViewSet)
router.register(r'device-bays', views.DeviceBayViewSet)
router.register(r'modules', views.ModuleViewSet)
router.register(r'inventory-items', views.InventoryItemViewSet)

# Interface connections
router.register(r'interface-connections', views.InterfaceConnectionViewSet)
Expand Down
12 changes: 6 additions & 6 deletions netbox/dcim/api/views.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

from dcim.models import (
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceConnection, InterfaceTemplate, Manufacturer, Module,
DeviceBayTemplate, DeviceRole, DeviceType, Interface, InterfaceConnection, InterfaceTemplate, Manufacturer, InventoryItem,
Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup, RackReservation,
RackRole, Region, Site,
)
Expand Down Expand Up @@ -294,11 +294,11 @@ class DeviceBayViewSet(WritableSerializerMixin, ModelViewSet):
filter_class = filters.DeviceBayFilter


class ModuleViewSet(WritableSerializerMixin, ModelViewSet):
queryset = Module.objects.select_related('device', 'manufacturer')
serializer_class = serializers.ModuleSerializer
write_serializer_class = serializers.WritableModuleSerializer
filter_class = filters.ModuleFilter
class InventoryItemViewSet(WritableSerializerMixin, ModelViewSet):
queryset = InventoryItem.objects.select_related('device', 'manufacturer')
serializer_class = serializers.InventoryItemSerializer
write_serializer_class = serializers.WritableInventoryItemSerializer
filter_class = filters.InventoryItemFilter


#
Expand Down
8 changes: 4 additions & 4 deletions netbox/dcim/filters.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
from .models import (
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
DeviceBayTemplate, DeviceRole, DeviceType, IFACE_FF_LAG, Interface, InterfaceConnection, InterfaceTemplate,
Manufacturer, Module, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup,
Manufacturer, InventoryItem, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, Rack, RackGroup,
RackReservation, RackRole, Region, Site, VIRTUAL_IFACE_TYPES,
)

Expand Down Expand Up @@ -359,7 +359,7 @@ def search(self, queryset, name, value):
return queryset.filter(
Q(name__icontains=value) |
Q(serial__icontains=value.strip()) |
Q(modules__serial__icontains=value.strip()) |
Q(inventory_items__serial__icontains=value.strip()) |
Q(asset_tag=value.strip()) |
Q(comments__icontains=value)
).distinct()
Expand Down Expand Up @@ -444,10 +444,10 @@ class Meta:
fields = ['name']


class ModuleFilter(DeviceComponentFilterSet):
class InventoryItemFilter(DeviceComponentFilterSet):

class Meta:
model = Module
model = InventoryItem
fields = ['name']


Expand Down
8 changes: 4 additions & 4 deletions netbox/dcim/forms.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@
DeviceBay, DeviceBayTemplate, CONNECTION_STATUS_CHOICES, CONNECTION_STATUS_PLANNED, CONNECTION_STATUS_CONNECTED,
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceRole, DeviceType,
Interface, IFACE_FF_CHOICES, IFACE_FF_LAG, IFACE_ORDERING_CHOICES, InterfaceConnection, InterfaceTemplate,
Manufacturer, Module, Platform, PowerOutlet, PowerOutletTemplate, PowerPort, PowerPortTemplate, RACK_TYPE_CHOICES,
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
)
Expand Down Expand Up @@ -1684,11 +1684,11 @@ def __init__(self, device, *args, **kwargs):


#
# Modules
# Inventory items
#

class ModuleForm(BootstrapMixin, forms.ModelForm):
class InventoryItemForm(BootstrapMixin, forms.ModelForm):

class Meta:
model = Module
model = InventoryItem
fields = ['name', 'manufacturer', 'part_id', 'serial']
35 changes: 35 additions & 0 deletions netbox/dcim/migrations/0034_rename_module_to_inventoryitem.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# -*- coding: utf-8 -*-
# Generated by Django 1.10.6 on 2017-03-21 14:55
from __future__ import unicode_literals

from django.db import migrations, models
import django.db.models.deletion


class Migration(migrations.Migration):

dependencies = [
('dcim', '0033_rackreservation_rack_editable'),
]

operations = [
migrations.RenameModel(
old_name='Module',
new_name='InventoryItem',
),
migrations.AlterField(
model_name='inventoryitem',
name='device',
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='inventory_items', to='dcim.Device'),
),
migrations.AlterField(
model_name='inventoryitem',
name='parent',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.CASCADE, related_name='child_items', to='dcim.InventoryItem'),
),
migrations.AlterField(
model_name='inventoryitem',
name='manufacturer',
field=models.ForeignKey(blank=True, null=True, on_delete=django.db.models.deletion.PROTECT, related_name='inventory_items', to='dcim.Manufacturer'),
),
]
14 changes: 7 additions & 7 deletions netbox/dcim/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -1397,19 +1397,19 @@ def clean(self):


#
# Modules
# Inventory items
#

@python_2_unicode_compatible
class Module(models.Model):
class InventoryItem(models.Model):
"""
A Module represents a piece of hardware within a Device, such as a line card or power supply. Modules are used only
for inventory purposes.
An InventoryItem represents a serialized piece of hardware within a Device, such as a line card or power supply.
InventoryItems are used only for inventory purposes.
"""
device = models.ForeignKey('Device', related_name='modules', on_delete=models.CASCADE)
parent = models.ForeignKey('self', related_name='submodules', blank=True, null=True, on_delete=models.CASCADE)
device = models.ForeignKey('Device', related_name='inventory_items', on_delete=models.CASCADE)
parent = models.ForeignKey('self', related_name='child_items', blank=True, null=True, on_delete=models.CASCADE)
name = models.CharField(max_length=50, verbose_name='Name')
manufacturer = models.ForeignKey('Manufacturer', related_name='modules', blank=True, null=True,
manufacturer = models.ForeignKey('Manufacturer', related_name='inventory_items', blank=True, null=True,
on_delete=models.PROTECT)
part_id = models.CharField(max_length=50, verbose_name='Part ID', blank=True)
serial = models.CharField(max_length=50, verbose_name='Serial number', blank=True)
Expand Down
66 changes: 33 additions & 33 deletions netbox/dcim/tests/test_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
from dcim.models import (
ConsolePort, ConsolePortTemplate, ConsoleServerPort, ConsoleServerPortTemplate, Device, DeviceBay,
DeviceBayTemplate, DeviceRole, DeviceType, IFACE_FF_LAG, Interface, InterfaceConnection, InterfaceTemplate,
Manufacturer, Module, Platform, PowerPort, PowerPortTemplate, PowerOutlet, PowerOutletTemplate, Rack, RackGroup,
Manufacturer, InventoryItem, Platform, PowerPort, PowerPortTemplate, PowerOutlet, PowerOutletTemplate, Rack, RackGroup,
RackReservation, RackRole, Region, Site, SUBDEVICE_ROLE_CHILD, SUBDEVICE_ROLE_PARENT,
)
from extras.models import Graph, GRAPH_TYPE_INTERFACE, GRAPH_TYPE_SITE
Expand Down Expand Up @@ -1847,7 +1847,7 @@ def test_delete_devicebay(self):
self.assertEqual(DeviceBay.objects.count(), 2)


class ModuleTest(HttpStatusMixin, APITestCase):
class InventoryItemTest(HttpStatusMixin, APITestCase):

def setUp(self):

Expand All @@ -1866,71 +1866,71 @@ def setUp(self):
self.device = Device.objects.create(
device_type=devicetype, device_role=devicerole, name='Test Device 1', site=site
)
self.module1 = Module.objects.create(device=self.device, name='Test Module 1')
self.module2 = Module.objects.create(device=self.device, name='Test Module 2')
self.module3 = Module.objects.create(device=self.device, name='Test Module 3')
self.inventoryitem1 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 1')
self.inventoryitem2 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 2')
self.inventoryitem3 = InventoryItem.objects.create(device=self.device, name='Test Inventory Item 3')

def test_get_module(self):
def test_get_inventoryitem(self):

url = reverse('dcim-api:module-detail', kwargs={'pk': self.module1.pk})
url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk})
response = self.client.get(url, **self.header)

self.assertEqual(response.data['name'], self.module1.name)
self.assertEqual(response.data['name'], self.inventoryitem1.name)

def test_list_modules(self):
def test_list_inventoryitems(self):

url = reverse('dcim-api:module-list')
url = reverse('dcim-api:inventoryitem-list')
response = self.client.get(url, **self.header)

self.assertEqual(response.data['count'], 3)

def test_create_module(self):
def test_create_inventoryitem(self):

data = {
'device': self.device.pk,
'parent': self.module1.pk,
'name': 'Test Module 4',
'parent': self.inventoryitem1.pk,
'name': 'Test Inventory Item 4',
'manufacturer': self.manufacturer.pk,
}

url = reverse('dcim-api:module-list')
url = reverse('dcim-api:inventoryitem-list')
response = self.client.post(url, data, **self.header)

self.assertHttpStatus(response, status.HTTP_201_CREATED)
self.assertEqual(Module.objects.count(), 4)
module4 = Module.objects.get(pk=response.data['id'])
self.assertEqual(module4.device_id, data['device'])
self.assertEqual(module4.parent_id, data['parent'])
self.assertEqual(module4.name, data['name'])
self.assertEqual(module4.manufacturer_id, data['manufacturer'])
self.assertEqual(InventoryItem.objects.count(), 4)
inventoryitem4 = InventoryItem.objects.get(pk=response.data['id'])
self.assertEqual(inventoryitem4.device_id, data['device'])
self.assertEqual(inventoryitem4.parent_id, data['parent'])
self.assertEqual(inventoryitem4.name, data['name'])
self.assertEqual(inventoryitem4.manufacturer_id, data['manufacturer'])

def test_update_module(self):
def test_update_inventoryitem(self):

data = {
'device': self.device.pk,
'parent': self.module1.pk,
'name': 'Test Module X',
'parent': self.inventoryitem1.pk,
'name': 'Test Inventory Item X',
'manufacturer': self.manufacturer.pk,
}

url = reverse('dcim-api:module-detail', kwargs={'pk': self.module1.pk})
url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk})
response = self.client.put(url, data, **self.header)

self.assertHttpStatus(response, status.HTTP_200_OK)
self.assertEqual(Module.objects.count(), 3)
module1 = Module.objects.get(pk=response.data['id'])
self.assertEqual(module1.device_id, data['device'])
self.assertEqual(module1.parent_id, data['parent'])
self.assertEqual(module1.name, data['name'])
self.assertEqual(module1.manufacturer_id, data['manufacturer'])
self.assertEqual(InventoryItem.objects.count(), 3)
inventoryitem1 = InventoryItem.objects.get(pk=response.data['id'])
self.assertEqual(inventoryitem1.device_id, data['device'])
self.assertEqual(inventoryitem1.parent_id, data['parent'])
self.assertEqual(inventoryitem1.name, data['name'])
self.assertEqual(inventoryitem1.manufacturer_id, data['manufacturer'])

def test_delete_module(self):
def test_delete_inventoryitem(self):

url = reverse('dcim-api:module-detail', kwargs={'pk': self.module1.pk})
url = reverse('dcim-api:inventoryitem-detail', kwargs={'pk': self.inventoryitem1.pk})
response = self.client.delete(url, **self.header)

self.assertHttpStatus(response, status.HTTP_204_NO_CONTENT)
self.assertEqual(Module.objects.count(), 2)
self.assertEqual(InventoryItem.objects.count(), 2)


class InterfaceConnectionTest(HttpStatusMixin, APITestCase):
Expand Down
10 changes: 5 additions & 5 deletions netbox/dcim/urls.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,11 @@
url(r'^device-bays/(?P<pk>\d+)/populate/$', views.devicebay_populate, name='devicebay_populate'),
url(r'^device-bays/(?P<pk>\d+)/depopulate/$', views.devicebay_depopulate, name='devicebay_depopulate'),

# Inventory items
url(r'^devices/(?P<device>\d+)/inventory-items/add/$', views.InventoryItemEditView.as_view(), name='inventoryitem_add'),
url(r'^inventory-items/(?P<pk>\d+)/edit/$', views.InventoryItemEditView.as_view(), name='inventoryitem_edit'),
url(r'^inventory-items/(?P<pk>\d+)/delete/$', views.InventoryItemDeleteView.as_view(), name='inventoryitem_delete'),

# Console/power/interface connections
url(r'^console-connections/$', views.ConsoleConnectionsListView.as_view(), name='console_connections_list'),
url(r'^console-connections/import/$', views.ConsoleConnectionsBulkImportView.as_view(), name='console_connections_import'),
Expand All @@ -181,9 +186,4 @@
url(r'^interface-connections/$', views.InterfaceConnectionsListView.as_view(), name='interface_connections_list'),
url(r'^interface-connections/import/$', views.InterfaceConnectionsBulkImportView.as_view(), name='interface_connections_import'),

# Modules
url(r'^devices/(?P<device>\d+)/modules/add/$', views.ModuleEditView.as_view(), name='module_add'),
url(r'^modules/(?P<pk>\d+)/edit/$', views.ModuleEditView.as_view(), name='module_edit'),
url(r'^modules/(?P<pk>\d+)/delete/$', views.ModuleDeleteView.as_view(), name='module_delete'),

]
Loading

0 comments on commit 22768ff

Please sign in to comment.