We have a NetBox instance which we use to store information about virtual machines. The Config Context tab for a virtual machine object is populated with a YAML file structured as such:
stuff:
- hostname: myserver
os: Linux
os_version: RHEL 8.1
network:
- ip_address: 192.168.2.3
network: ABC
gateway: 192.168.2.1
server_type: XYZ
other_data: Foobar
The same data is also available in JSON format.
I am doing extraction of the standard NetBox fields to a CSV file via the following Python script:
config = configparser.ConfigParser()
netbox_token = config.get('NetBox', 'token')
netbox_api_base_url = config.get('NetBox', 'api_base_url')
netbox_devices_endpoint = config.get('NetBox', 'devices_endpoint')
nb = pynetbox.api(netbox_api_base_url, token=netbox_token)
nb.http_session.verify = True
vms = nb.virtualization.virtual_machines.all()
csv_file_vms = 'netbox_vms.csv'
with open(csv_file_vms, mode='w', newline='') as csv_file:
csv_writer = csv.writer(csv_file)
csv_writer.writerow(['Name', 'Status', 'Site', 'VCPUs', 'Memory (MB)', 'Disk (GB)', 'IP Address'])
for vm in vms:
csv_writer.writerow([vm.name, vm.status, vm.site, vm.vcpus, vm.memory, vm.disk, vm.primary_ip])
How do I modify the writerow() function to add the data stored in the Config Context, e.g. the os_version field?
Preface
You will need to add a dedicated column in the first call to
writerow, and access the relevant VM attribute in consecutive calls inside theforloop. As I assume your question revolves more around attribute access rather than how to write CSVs - I'll dive deeper into the former;Config Context
The Config Context can be accessed via the
vm.config_contextattribute. The provided YAML example translates to a dictionary with one keystuff, which points to a list of items. Each item in that list is a dictionary having keys such ashostname,os_version, andnetwork. The values of the first keys mentioned are strings, but the value ofnetworkis yet another list. Following is a practical demonstration for accessing such attributes for the given example, while assuming that all list types have one (and only one) item:Solution
A complete answer to your question would include the adaptations required for writing the CSV, so here goes:
Additional thoughts
If you can change the YAML structure, removing the first dash
-(from in front of thehostnamefield in your example) can make attribute access simpler, and also represent the reality more accurately; consider the following YAML as a config context for a router:Handling such case in code can look like this:
You may not have to deal with multiple IP addresses in your situation, but you won't need to handle the possibility of a single VM configured (probably erroneously) with multiple OSes.
Note: This question involves interoperability between client and server functions. I've tested this on python 3.9.18, netbox 3.6.5, and pynetbox 7.2.0. Other versions may behave differently.