NetBox Inventory Plugin

repository·master·Indexed 43 days ago

https://github.com/arnessi/netbox-inventory

A hardware inventory management tool for NetBox (version 2.6.1) used to track assets such as devices, modules, inventory items, and racks. It features bulk asset tag generation, automated status management for 'in use' and 'in storage' states, and Audit Flows to verify the physical presence of objects at specific sites or locations.

Tokens
14.8K
Snippets
40
Records
55
Agent score
56%

What's inside NetBox Inventory

  1. Enable netbox-inventory in NetBox configuration

    master

    After installation, you must register the plugin in your NetBox configuration.

    For standard installations, edit /opt/netbox/netbox/netbox/configuration.py. For netbox-docker users, edit /configuration/plugins.py.

    You must add 'netbox_inventory' to the PLUGINS list and define a PLUGINS_CONFIG dictionary.

    PLUGINS = [
        'netbox_inventory'
    ]
    
    PLUGINS_CONFIG = {
        "netbox_inventory": {},
    }
  2. Bulk add assets with generated asset tags

    master

    When creating multiple assets via Assets > Add multiple, you can automatically generate asset_tag values using a pattern. The pattern must expand to the same number of values as the specified count.

    • Use the Asset tag pattern field (e.g., ASSET-[1-3]).
    • Pattern expansion follows NetBox's alphanumeric expansion behavior.

    Example: ASSET-[001-003] expands to ASSET-1, ASSET-2, and ASSET-3.

  3. Install the netbox-inventory plugin

    master

    To install the plugin in a standard NetBox environment, activate your NetBox virtual environment and use pip to install the package from PyPI.

    If you are using netbox-docker, you can add the GitHub URL to your local_requirements.txt or plugin_requirements.txt files.

    After installation, you must apply database migrations and update the search index manually if you are not using Docker.

    # Standard installation
    $ source /opt/netbox/venv/bin/activate
    (venv) $ pip install netbox-inventory
    
    # Apply migrations and reindex
    (venv) $ cd /opt/netbox/netbox/
    (venv) $ python3 manage.py migrate
    (venv) $ python3 manage.py reindex --lazy
  4. Use Audit Flows to verify inventory on site

    master

    Audit Flows allow users to verify that objects (like Assets) are physically present at a specific Location or Site.

    Core Components

    • Audit Flow Pages: User views that list specific NetBox objects, filterable by type and field values.
    • Audit Flows: A collection of Audit Flow Pages. Initiated via the [Audit] button on a Location or Site detail page.
    • Audit Trails: Records documenting when an object was verified. Created by clicking the button in an Audit Flow page or via API/Import.
    • Audit Trail Sources: Optional identifiers for the source of an audit trail (available via API/Import).

    Permissions Required

    • To run a flow: run permission on the Audit Flow object and view permission on the parent Site or Location.
    • To view audited objects: No additional permissions required.
    • To create/edit audit trails: add and delete permissions on the audit trail model.

    Workflow Tips

    • Quick Search: The search input on audit pages is auto-focused. Using it with [Enter] triggers the object's filterset.
    • Automatic Marking: If a filter results in exactly one object, that object is automatically marked as seen.
    • Redirect on Mismatch: If a filter results in exactly one object across all types, the user is redirected to its edit form (useful if an object was moved).
  5. Extend Asset status choices

    master

    To add custom statuses to the Asset model, use the NetBox FIELD_CHOICES setting. If you add new statuses, ensure you also update used_additional_status_names and stored_additional_status_names in the plugin configuration so the plugin correctly identifies the asset state.

    FIELD_CHOICES = {
        'netbox_inventory.Asset.status+': (
            ('repair', 'In repair', 'orange'),
        ),
    }
  6. Prevent unwanted changes for tagged assets using Custom Validation

    master

    Since version 2.5.1, protecting assets from accidental changes in the NetBox web interface is handled via NetBox's Custom Validation rules. This allows you to restrict modifications to specific fields (like serial or asset_tag) for assets carrying a specific tag (e.g., no-edit).

    Note: These restrictions apply only to the web interface. Deletions and modifications via the API or Import form remain possible.

    from extras.validators import CustomValidator
    from utilities.data import shallow_compare_dict
    
    
    class TagEditProtector(CustomValidator):
        def __init__(self, protection_tag, protected_fields=None):
            super().__init__(validation_rules=None)
            self.protection_tag = protection_tag
            self.protected_fields = protected_fields
    
        def validate(self, instance, request):
            # permit changes via API
            if request and request.path.startswith('/api/'):
                return
            # permit changes via import
            if request and '/import/' in request.path:
                return
            # see ChangeLoggingMixin.snapshot()
            exclude = [
                'last_updated',
            ]
            if not instance.pk:
                # creating new object
                return
            if self.protection_tag not in instance.tags.all().values_list('slug', flat=True):
                # if not tagged with protection_tag, no limitations
                return
            fail_msg = f'Cannot change {instance}. Protected by tag {self.protection_tag}'
            violation = None
            if not self.protected_fields:
                # consider all fields protected
                violation = fail_msg
            else:
                # Get fields that were changed
                prechange_data = instance._prechange_snapshot
                postchange_data = instance.serialize_object(exclude=exclude)
                diff = shallow_compare_dict(prechange_data, postchange_data)
                violated_fields = set(diff.keys()).intersection(self.protected_fields)
                if violated_fields:
                    violation = dict(map(lambda f: (f, fail_msg), violated_fields))
            if violation:
                self.fail(violation)
    
    
    class TagDeleteProtector(CustomValidator):
        def __init__(self, protection_tag):
            super().__init__(validation_rules=None)
            self.protection_tag = protection_tag
    
        def validate(self, instance, request):
            if request and request.path.startswith('/api/'):
                return
            if self.protection_tag not in instance.tags.all().values_list('slug', flat=True):
                # if not tagged with protection_tag, no limitations
                return
            self.fail(f'Cannot delete {instance}. Protected by tag {self.protection_tag}')
    
    
    CUSTOM_VALIDATORS = {
        'netbox_inventory.asset': [
            TagEditProtector('no-edit', ('serial', 'asset_tag')),
        ],
    }
    
    PROTECTION_RULES = {
        'netbox_inventory.asset': [
            TagDeleteProtector('no-edit'),
        ]
    }
  7. Configure automatic management of asset status

    master

    The plugin can automatically update an asset's status based on its assignment to a device, module, or inventory item.

    • To set status to 'in use': Configure used_status_name in your settings. The status will be updated when an asset is assigned to a device, module, or inventory item.
    • To set status to 'in storage': Configure stored_status_name in your settings. The status will be updated when an asset is removed from a device, module, or inventory item.
    • To disable automatic status changes: Set both used_status_name and stored_status_name to None in your configuration.
  8. Configure netbox-inventory settings

    master

    You can customize the plugin behavior by adding keys to the netbox_inventory dictionary within PLUGINS_CONFIG.

    Common settings include defining which statuses represent 'in use' or 'in storage', enabling automatic synchronization of serial numbers and asset tags, and controlling automatic creation of related objects (like manufacturers or tenants) during asset imports.

    PLUGINS_CONFIG = {
        "netbox_inventory": {
            "used_status_name": "used",
            "stored_status_name": "stored",
            "sync_hardware_serial_asset_tag": True,
        },
    }
  9. Generate Audit Reports using NetBox Scripts

    master

    The plugin does not include built-in reporting for current audit status. Instead, you can use NetBox Custom Scripts to identify missing audit trails.

    Below is an example script that checks for Asset objects that do not have a recent AuditTrail entry, including checks for the asset's assigned Device or Module.

    from django.db.models import OuterRef, Q
    
    from core.models import ObjectType
    from dcim.models import Device, Module
    from extras.scripts import Script
    
    from netbox_inventory.models import Asset, AuditTrail
    
    
    class AuditReportMissing(Script):
        description = 'Check for missing audit trails of assets'
    
        def test_missing_audit_assets(self) -> None:
            queryset = Asset.objects.annotate(
                last_audit_date=Subquery(
                    AuditTrail.objects.filter(
                        Q(
                            object_type=ObjectType.objects.get_for_model(Asset),
                            object_id=OuterRef('pk'),
                        )
                        # Also, check for the assigned device or module of an Asset.
                        | Q(
                            object_type=ObjectType.objects.get_for_model(Device),
                            object_id=OuterRef('device__pk'),
                        )
                        | Q(
                            object_type=ObjectType.objects.get_for_model(Module),
                            object_id=OuterRef('module__pk'),
                        )
                    )
                    .order_by('-created')
                    .values_list('created', flat=True)[:1]
                )
            )
    
            for asset in queryset.filter(last_audit_date__isnull=True):
                self.log_warning('No recent audit for object found.', obj=asset)
  10. Attach documents to inventory objects using netbox-attachments

    master

    The netbox-inventory plugin has limited support for file attachments (images for assets and inventory item types only). To attach documents to models like supplier, purchase, or delivery, it is recommended to use the netbox-attachments plugin.

    Below is an example configuration to enable attachments for these specific inventory models.

    PLUGINS = [
        'netbox_inventory',
        'netbox_attachments',
    ]
    
    PLUGINS_CONFIG = {
        'netbox_attachments': {
            'applied_scope': 'model',
            'scope_filter': [
                'netbox_inventory.supplier',
                'netbox_inventory.purchase',
                'netbox_inventory.delivery',
            ],
            'display_setting': {
                "netbox_inventory.supplier": "left_page",
                "netbox_inventory.purchase": "full_width_page",
                "netbox_inventory.delivery": "righ_page",
            },
        },
    }
  11. Configure the NetBox Inventory plugin

    master

    The NetBoxInventoryConfig class defines the plugin's configuration and default settings. You can override these settings in your configuration.py file to customize plugin behavior, such as status management, import behaviors, and audit windows.

    Key configuration options include:

    • top_level_menu: Boolean determining if the plugin appears in the top-level menu.
    • used_status_name: The primary status name for 'used' assets.
    • used_additional_status_names: A list of additional status names considered 'used'.
    • stored_status_name: The primary status name for 'stored' assets.
    • stored_additional_status_names: A list of additional status names considered 'stored' (e.g., ['retired']).
    • sync_hardware_serial_asset_tag: Boolean to sync hardware serials to asset tags.
    • asset_import_*: Various boolean flags to control whether the import process automatically creates objects like purchase, device_type, module_type, inventoryitem_type, rack_type, or tenant.
    • asset_custom_fields_search_filters: A dictionary for defining search filters on asset custom fields.
    • asset_warranty_expire_warning_days: Integer defining the warning threshold for expiring warranties.
    • prefill_*: Boolean flags to control whether certain fields are prefilled during InventoryItem creation.
    • audit_window: Integer representing the audit window in minutes (default is 240 minutes/4 hours).
    # Example configuration in NetBox configuration.py
    PLUGINS = [
        'netbox_inventory',
    ]
    
    PLUGINS_CONFIG = {
        'netbox_inventory': {
            'used_status_name': 'active',
            'used_additional_status_names': ['deployed'],
            'stored_additional_status_names': ['retired', 'broken'],
            'asset_import_create_device_type': True,
            'audit_window': 1440,  # 24 hours
        }
    }