ninech / netbox-client-ruby

A ruby client library for Netbox v2.
MIT License
24 stars 21 forks source link

can't access an interface's virtual_machine #24

Closed bleything closed 6 years ago

bleything commented 6 years ago

For various reason I'm iterating over IP address's interfaces and trying to find their related devices or VMs. Devices work okay, but VMs don't:

$nb.ipam.ip_addresses.first.interface.virtual_machine
NoMethodError: undefined method `virtual_machine' for #<NetboxClientRuby::DCIM::Interface:0x00007f80c512e5b0>
    from /Users/bleything/.chefdk/gem/ruby/2.4.0/gems/netbox-client-ruby-0.4.6/lib/netbox_client_ruby/entity.rb:207:in `method_missing'
    from (irb):9
    from /opt/chefdk/embedded/bin/irb:11:in `<main>'

I tried editing lib/netbox_client_ruby/api/dcim/interface.rb:

require 'netbox_client_ruby/entity'
require 'netbox_client_ruby/api/dcim/device'
require 'netbox_client_ruby/api/virtualization/virtual_machine'

module NetboxClientRuby
  module DCIM
    class Interface
      include Entity

      id id: :id
      deletable true
      path 'dcim/interfaces/:id.json'
      creation_path 'dcim/interfaces/'
      object_fields device: proc { |raw_data| Device.new raw_data['id'] },
                    virtual_machine: proc { |raw_data| Virtualization::VirtualMachine.new raw_data['id'] }
    end
  end
end

and that makes the NoMethodError go away but it returns nil, even when there's a virtual_machine attached. I assume that I'm just doing something wrong but I don't understand the code well enough to figure out how to resolve it.

bleything commented 6 years ago

Might've found a clue! If I look at the IP Address object:

pp $nb.ipam.ip_addresses.first
#<NetboxClientRuby::IPAM::IpAddress:0x00007fa05b802480
 @data=
  {"id"=>311,
   "family"=>4,
   "address"=>"[REDACTED]/24",
   "vrf"=>
    {"id"=>1,
     "url"=>"http://[REDACTED]/api/ipam/vrfs/1.json",
     "name"=>"[REDACTED]",
     "rd"=>"[REDACTED]"},
   "tenant"=>nil,
   "status"=>{"label"=>"Active", "value"=>1},
   "role"=>nil,
   "interface"=>
    {"id"=>1408,
     "url"=>
      "http://[REDACTED]/api/virtualization/interfaces/1408/",
     "device"=>nil,
     "virtual_machine"=>
      {"id"=>62,
       "url"=>
        "http://[REDACTED]/api/virtualization/virtual-machines/62.json",
       "name"=>"[REDACTED]"},
     "name"=>"eth0"},
   "description"=>"",
   "nat_inside"=>nil,
   "nat_outside"=>nil,
   "custom_fields"=>{},
   "created"=>"2017-10-17",
   "last_updated"=>"2017-10-17T00:17:08.804666Z"},
 @id=311>

I see that interface has a virtual_machine. If I look at that object's #raw_data! I see the same thing. But if I do $nb.ipam.ip_addresses.first.interface.raw_data! the virtual_machine is not in there. If I fetch the interface directly from the API, the info is there. Same if I get the IP address.

cimnine commented 6 years ago

The problem is that interfaces of virtual machines are different from interfaces of physical devices in the API:

http://netbox/api/dcim/interfaces/ vs. http://netbox/api/virtualization/interfaces/

I'm working on an improved implementation that detects whether it's the interface of a VM or one of a physical device.

cimnine commented 6 years ago

Thank you for raising the issue!

bleything commented 6 years ago

ah ha! That makes a lot of sense and thanks for fixing it!