ansible_modules icon indicating copy to clipboard operation
ansible_modules copied to clipboard

[Bug]: netbox_module returns error "More than one result returned for module_bay"

Open LoneSnowMonkey opened this issue 1 year ago • 3 comments

Ansible NetBox Collection version

v3.19.1

Ansible version

ansible [core 2.17.0]
  config file = /etc/ansible/ansible.cfg
  configured module search path = ['/home/foouser/.ansible/plugins/modules', '/usr/share/ansible/plugins/modules']
  ansible python module location = /home/foouser/ansible/lib/python3.10/site-packages/ansible
  ansible collection location = /home/foouser/.ansible/collections:/usr/share/ansible/collections
  executable location = /home/foouser/ansible/bin/ansible
  python version = 3.10.12 (main, Nov 20 2023, 15:14:05) [GCC 11.4.0] (/home/foouser/ansible/bin/python3)
  jinja version = 3.1.2
  libyaml = True

NetBox version

v3.7.3

Python version

3.10

Steps to Reproduce

I hope this is not a misunderstanding. In the past I've wanted to use netbox ansible modules to 'insert' a module into a module bay on a device. And while we could create a module_bay and a module_type, there wasn't such functionality. I did it using the URI module, but it of course required some additional logic and was not idempotent without further steps. I perused updates and see the new (to me) netbox_module.

I spin up a playbook to test this as I am doing more of this sort of work this week. I've been modeling my Dell servers with a module bay called network card bay. This allows me to have the same model of server but to account for the fact that one might have been ordered with an installed 4 port Gb integrated NIC, whilst another might have pair of 10Gb SFP+ ports and a pair of gigabit. I poll the host during discovery, add the correct module, which then populates the appropriate network interfaces and such. Example playbook sanitized of details:

- name: Update network card module in host
  hosts: localhost
  gather_facts: false

  tasks:
    - name: Set facts
      set_fact:
        netbox_url: https://netbox.host
        netbox_token: redactedTokenStringfoobar

    - name: Update network bay module
      netbox.netbox.netbox_module:
        netbox_url: "{{ netbox_url }}"
        netbox_token: "{{ netbox_token }}"
        data:
          device:
            name: foo-device
          module_bay:
            name: network card bay
          module_type:
            manufacturer: Dell
            model: 4Gb NIC
          status: active
        state: present

Expected Behavior

I expected to see a Changed outcome to my playbook results and foo-device updated in network to now have a 4-port gigabit integrated network card, along with the new network interfaces.

Observed Behavior

My original problem was that I got state is present but all of the following are missing: status. I found this odd as I needed to have state present in my playbook to indicate whether or not the module should be in the given module bay. Status was not listed as a required field so I left it out originally. In Netbox 3.X there is no status to a module. I put the status as active and re-ran the playbook. Now I get the error More than one result returned for module_bay. This took me a bit to understand as I interpreted it to mean it searched all of the modules bays in foo-device and it found multiple with the name network card bay. That wasn't the case, of course. It wasn't until later that I realized looking through my nginx logs that theres a search for device with name foo-device and then a search for all module_bays with the name network card bay.

::ffff:192.168.1.1 - - [DATESTAMP] "GET /api/dcim/devices/?name=foo-dev&limit=0 HTTP/1.1" 200 2562 "-" "python-requests/2.31.0"
::ffff:192.168.1.1 - - [DATESTAMP] "GET /api/dcim/module-bays/?name=network+card+bay&limit=0 HTTP/1.1" 200 80993 "-" "python-requests/2.31.0"

I find this odd because, at least this is how I do it, I add module bays to device templates. I have one for iDRAC, a network card bay for the integrated NIC ordered for the machine. PCI slots. PSU slots. But they all have the same names in every device of that device type. Its network card bay not hostname's network card bay.

But that appears to be the source of the error, it's returning hundreds of results because I use that same module bay naming on every Dell server, regardless of model. But I've given it the host I am using.

I am unable to test against a Netbox 4.x server because of a different problem I am having. There I get Failed to establish connection to NetBox API when I talk to my 4.x dev server. Not sure why, the same token works from Postman. Added my $.02 to another open issue about this.

LoneSnowMonkey avatar Jun 15 '24 20:06 LoneSnowMonkey

To add to my earlier comment, I noticed module status in my 3.x installation, just not as 'up front' as it is in 4.x. The module documentation should be updated to say its a required field. Original, main issue of the module not working remains.

LoneSnowMonkey avatar Jun 17 '24 16:06 LoneSnowMonkey

Here to report the same issue. I have all my module bays listed the same for easy automation.

But found out that the module plugin searches all module bays before checking which device.

Timewarrener avatar Aug 13 '24 15:08 Timewarrener

So messing around with netbox's API I figured a way to get netbox to use a device specific module bay.

Not sure if this will work in the ansible galaxy collection

      module_bay:
        name: network card bay
        device__name: foo-device

Timewarrener avatar Aug 13 '24 21:08 Timewarrener

I have an identical scenario - adding modules to a Dell server and experience the same error using collection netbox.netbox:3.20.0 The workaround for adding the device__name to the module_bay does not work for me. Netbox v4.1.6

flyboyjon avatar Dec 17 '24 22:12 flyboyjon

But passing the device rather than the device__name into the module_bay did work:

  module_bay:
    name: network card bay
    device: foo-device

flyboyjon avatar Dec 18 '24 13:12 flyboyjon

But passing the device rather than the device__name into the module_bay did work:

  module_bay:
    name: network card bay
    device: foo-device

Well, it worked also in ansible, thank you. The question is, if this is expected behavior. For those using ansible:

Not working:

patch_modules:
  - {status: active, device: testpatch, module_bay: Slot, module_type: MOD-MM-24LC-2, description: , comments: , asset_tag: , serial: } 

Working yaml.

patch_modules:
  - {status: active, device: testpatch, module_bay: {device: testpatch, name: Slot}, module_type: MOD-MM-24LC-2, description: , comments: , asset_tag: , serial: }

pehan-dotcom avatar Feb 14 '25 10:02 pehan-dotcom

Not sure if someone can give me a working example ?

I have this and it returns the error of More than one result returned for module_bay:

    - name: Update module bay information
      netbox.netbox.netbox_module:
        netbox_url: "{{ lookup('env', 'NETBOX_URL') }}"
        netbox_token: "{{ lookup('env', 'NETBOX_TOKEN') }}"
        data:
          device: "{{ item.server_name }}" # device name
          module_bay: "{{ item.bay_number }}" # name of module bay
          module_type: "{{ item.module_type }}" # # the type eg Add-on Card AOC... 
          status: "active"
        state: present
      loop: "{{ module_bays_list }}"

knfoo avatar Apr 08 '25 15:04 knfoo

I found a way to make it work for me, I needed the device name as part of the module_bay information.

Like this:

    - name: Update module bay information
      netbox.netbox.netbox_module:
        netbox_url: "{{ lookup('env', 'NETBOX_URL') }}"
        netbox_token: "{{ lookup('env', 'NETBOX_TOKEN') }}"
        data:
          device: "{{ item.server_name }}"
          module_bay: 
            name: "{{ item.bay_number }}"
            device: "{{ item.server_name }}"
          module_type: "{{ item.module_type }}"
          status: "active"
        state: present
      loop: "{{ module_bays_list }}"

knfoo avatar Apr 09 '25 08:04 knfoo