Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Scripts are not increasing counter for device components like power ports and inventory items #14446

Closed
cichutkiii opened this issue Dec 6, 2023 · 7 comments
Labels
type: bug A confirmed report of unexpected behavior in the application

Comments

@cichutkiii
Copy link

NetBox version

v3.6.4

Python version

3.8

Steps to Reproduce

  1. create 1 random items for power ports and inventory items.
  2. run script which will create items in inventory items and power ports
  3. delete manually items

Expected Behavior

counter should count newly added items by script

Observed Behavior

counter is not working while running script
And while removing items I'm getting to the situation when I have counter below 0

image

@cichutkiii cichutkiii added the type: bug A confirmed report of unexpected behavior in the application label Dec 6, 2023
@jeremystretch
Copy link
Member

  1. run script which will create items in inventory items and power ports

Please share the script that someone else can run locally to reproduce the reported behavior.

@jeremystretch jeremystretch added the status: revisions needed This issue requires additional information to be actionable label Dec 6, 2023
@cichutkiii
Copy link
Author

Sure, Jeremy
I made some testing and debugging and found out that this is happening because I'm updating device after creating inv items.
When the update is before creation of inv item, then this will not occur.

from django.utils.text import slugify

from dcim.choices import DeviceStatusChoices, SiteStatusChoices
from dcim.models import Device, Interface,InventoryItem,Rack, InventoryItemRole, PowerPort
from dcim.models import Manufacturer,Site,DeviceType,DeviceRole
from ipam.models import IPAddress
from extras.scripts import *
from pathlib import Path
from django.forms import PasswordInput
import ansible_runner
import json
import datetime

class UpdateDataScript(Script):

    class Meta:
        name = "Update device"
        description = "Update device with basic information"
    
    device = ObjectVar(
        model=Device,
        required=False
    )
    IP = StringVar(
        description="ip to connect to device",
        required=True
    )
    login = StringVar(
        description="Login to device",
        required=False
    )

    password = StringVar(
        widget=PasswordInput,
        required=False)
        
    hostname = BooleanVar(
        description="Check if you want to update hostname in Netbox"
        )
    serial = BooleanVar(
        description="Check if you want to update serial number in Netbox"
        )
    gln = BooleanVar(
        
        description="Check if device is in GLN"
        )
    
    
    def run(self, data, commit):
        device = data['device']
        
        DEFAULT_USER = data['login']
        DEFAULT_PASS = data['password']

        inv_role = InventoryItemRole.objects.get(name='Ethernet Card')
        inv_item = InventoryItem(
           name = "nane",
           label = "label",
           device_id = device.id,
           serial = "serial",
           role = inv_role,
           
        )
        self.log_success("adding new inventory item")
        inv_item.full_clean()
        inv_item.save()
        inv_item = InventoryItem(
           name = "nane2",
           label = "labe2l",
           device_id = device.id,
           serial = "seri2al",
           role = inv_role,
           
        )
        self.log_success("adding new inventory item")
        inv_item.full_clean()
        inv_item.save()
        inv_item = InventoryItem(
           name = "nane44",
           label = "label44",
           device_id = device.id,
           serial = "serial44",
           role = inv_role,
           
        )
        self.log_success("adding new inventory item")
        inv_item.full_clean()
        inv_item.save()
        device.asset_tag = "test"
        device.full_clean()
        device.save()

@jeremystretch jeremystretch added status: under review Further discussion is needed to determine this issue's scope and/or implementation and removed status: revisions needed This issue requires additional information to be actionable labels Dec 7, 2023
@jeremystretch
Copy link
Member

I'm not able to reproduce the reported behavior on NetBox v3.6.7. It has likely been addressed in the latest release by #14081. Please try upgrading, and ask that this issue be re-opened if you find that the bug persists.

@jeremystretch jeremystretch closed this as not planned Won't fix, can't repro, duplicate, stale Dec 26, 2023
@jeremystretch jeremystretch removed the status: under review Further discussion is needed to determine this issue's scope and/or implementation label Dec 26, 2023
@rizlas
Copy link
Contributor

rizlas commented Dec 28, 2023

The bug persists. I just upgraded to v3.6.8 and inventory items count still wrong. I'm also updating via scripts.

def create_inventory_item(component: dict, parent: InventoryItem = None):
    nb_item, _ = InventoryItem.objects.get_or_create(
        device=self.device_object,
        name=component["name"],
    )

    self.obj_snapshot(nb_item)

    nb_item.description = component["description"]
    nb_item.part_id = component["part_number"]
    nb_item.serial = component["serial_number"]

    if parent:
        nb_item.parent = parent

    nb_item.tags.add(self.inventory_common_tag)

    nb_item.full_clean()
    nb_item.save()

    return nb_item

Even if I remove all the inventory items before creation, counter remains wrong.

InventoryItem.objects.filter(device=self.device_object).delete()

@kkthxbye-code
Copy link
Contributor

kkthxbye-code commented Dec 28, 2023

@rizlas - The issue is, at least in @cichutkiii example, that the device is saved after the inventoryitem is added.

So a script like this (simplified from the earlier example) will make the count bug:

inv_role = InventoryItemRole.objects.get(name='Ethernet Card')
inv_item = InventoryItem(
   name = "nane",
   label = "label",
   device_id = device.id,
   serial = "serial",
   role = inv_role,
)

inv_item.full_clean()
inv_item.save()

# Everything is fine here

device.asset_tag = "test"
device.full_clean()

# This device is stale, as when the above inventory item was created, the device _inventory_item_count (or whatever it's called) was modified by netbox.
device.save() 

Instead the end would have to be:

device.refresh_from_db() # Get the non-stale device
device.asset_tag = "test"
device.full_clean()
device.save() 

I guess another option would be to use the update_fields argument to the save call, to omit updating the count fields.

This is not a bug in netbox, however it is bad practice and not intuitive to modify fields on other objects in a non-obvious way like it was done when the cached item counts were added. I wouldn't count on it changing, so you have to update your scripts.

@rizlas
Copy link
Contributor

rizlas commented Dec 28, 2023

I wasn't aware of refresh_from_db. Fine to me, make sense. But, I just tested your suggestion and the counter it still wrong.

This was my approach before testing your solution:

  • Device creation, update his attributes and save
  • Create other netbox objects (e.g. inventory items) referencing the entire device object (e.g. device=self.device_object)

After your suggestion:

  • Device creation, update his attributes
  • Create other netbox objects (e.g. inventory items) referencing the entire device object (e.g. device=self.device_object)
  • Saving the object this way:
self.device_object.refresh_from_db()
self.device_object.full_clean()
self.device_object.save()

Nothing changed

@rizlas
Copy link
Contributor

rizlas commented Dec 28, 2023

Thats my situation, as you can see I've inventory items but no "Inventory Items" tab.

image psd

If I add an item manually the tab appear.

immagine

Only deleting the entire device object seems to fix the problem.

@github-actions github-actions bot locked as resolved and limited conversation to collaborators Mar 28, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
type: bug A confirmed report of unexpected behavior in the application
Projects
None yet
Development

No branches or pull requests

4 participants