Compare commits
24 commits
76b2d253ce
...
7d268ea0e8
Author | SHA1 | Date | |
---|---|---|---|
|
7d268ea0e8 | ||
|
9d496c6854 | ||
|
6ef23eae4d | ||
12ceea413c | |||
7a968deee9 | |||
d55cbd62fc | |||
59ce76fc29 | |||
|
c3d3e6857a | ||
|
8dde35dd31 | ||
|
de88ca85b9 | ||
|
514627aa72 | ||
|
4b54a0a3db | ||
|
e44fd2fe78 | ||
|
1429fedb9d | ||
|
818c835711 | ||
|
40af19e801 | ||
|
1d69f4e2f0 | ||
|
a7104b6b94 | ||
|
ee41fb4fc2 | ||
|
e04d0c6d59 | ||
|
c9a57de843 | ||
|
f512e7a0a9 | ||
|
116334be2f | ||
|
ba4cdb217b |
10 changed files with 69 additions and 58 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
@ -181,3 +181,4 @@ dmypy.json
|
|||
# End of https://www.gitignore.io/api/emacs,python
|
||||
|
||||
netbox-docker
|
||||
/.vscode
|
||||
|
|
|
@ -20,8 +20,8 @@ The goal is to generate an existing infrastructure on Netbox and have the abilit
|
|||
|
||||
# Requirements
|
||||
|
||||
- Netbox >= 2.6
|
||||
- Python >= 3.4
|
||||
- Netbox >= 3.7
|
||||
- Python >= 3.7
|
||||
- [pynetbox](https://github.com/digitalocean/pynetbox/)
|
||||
- [python3-netaddr](https://github.com/drkjam/netaddr)
|
||||
- [python3-netifaces](https://github.com/al45tair/netifaces)
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from pkg_resources import DistributionNotFound, get_distribution
|
||||
from importlib.metadata import version as _get_version, PackageNotFoundError
|
||||
|
||||
try:
|
||||
__version__ = get_distribution(__name__).version
|
||||
except DistributionNotFound:
|
||||
__version__ = _get_version(__name__)
|
||||
except PackageNotFoundError:
|
||||
pass
|
||||
|
|
|
@ -34,8 +34,8 @@ def run(config):
|
|||
except KeyError:
|
||||
server = GenericHost(dmi=dmi)
|
||||
|
||||
if version.parse(nb.version) < version.parse('2.9'):
|
||||
print('netbox-agent is not compatible with Netbox prior to verison 2.9')
|
||||
if version.parse(nb.version) < version.parse('3.7'):
|
||||
print('netbox-agent is not compatible with Netbox prior to version 3.7')
|
||||
return False
|
||||
|
||||
if config.register or config.update_all or config.update_network or \
|
||||
|
|
|
@ -31,8 +31,9 @@ class LLDP():
|
|||
vlans[interface] = {}
|
||||
|
||||
for path_component in path_components:
|
||||
current_dict[path_component] = current_dict.get(path_component, {})
|
||||
current_dict = current_dict[path_component]
|
||||
if not isinstance(current_dict.get(path_component), dict):
|
||||
current_dict[path_component] = {}
|
||||
current_dict = current_dict.get(path_component)
|
||||
if 'vlan-id' in path:
|
||||
vid = value
|
||||
vlans[interface][value] = vlans[interface].get(vid, {})
|
||||
|
|
|
@ -77,20 +77,20 @@ class LSHW():
|
|||
# newer versions of lshw can return a list of names, see issue #227
|
||||
if not isinstance(i["name"], list):
|
||||
if i["name"].startswith("unknown"):
|
||||
unkn_intfs.push(i)
|
||||
unkn_intfs.append(i)
|
||||
else:
|
||||
for j in i["name"]:
|
||||
if j.startswith("unknown"):
|
||||
unkn_intfs.push(j)
|
||||
unkn_intfs.append(j)
|
||||
|
||||
unkn_name = "unknown{}".format(len(unkn_intfs))
|
||||
self.interfaces.append({
|
||||
"name": obj.get("logicalname", unkn_name),
|
||||
"macaddress": obj.get("serial", ""),
|
||||
"serial": obj.get("serial", ""),
|
||||
"product": obj["product"],
|
||||
"vendor": obj["vendor"],
|
||||
"description": obj["description"],
|
||||
"product": obj.get("product", "Unknown NIC"),
|
||||
"vendor": obj.get("vendor", "Unknown"),
|
||||
"description": obj.get("description", ""),
|
||||
})
|
||||
|
||||
def find_storage(self, obj):
|
||||
|
@ -135,10 +135,10 @@ class LSHW():
|
|||
def find_cpus(self, obj):
|
||||
if "product" in obj:
|
||||
self.cpus.append({
|
||||
"product": obj["product"],
|
||||
"vendor": obj["vendor"],
|
||||
"description": obj["description"],
|
||||
"location": obj["slot"],
|
||||
"product": obj.get("product", "Unknown CPU"),
|
||||
"vendor": obj.get("vendor", "Unknown vendor"),
|
||||
"description": obj.get("description", ""),
|
||||
"location": obj.get("slot", ""),
|
||||
})
|
||||
|
||||
def find_memories(self, obj):
|
||||
|
@ -162,11 +162,12 @@ class LSHW():
|
|||
|
||||
def find_gpus(self, obj):
|
||||
if "product" in obj:
|
||||
self.gpus.append({
|
||||
"product": obj["product"],
|
||||
"vendor": obj["vendor"],
|
||||
"description": obj["description"],
|
||||
})
|
||||
infos = {
|
||||
"product": obj.get("product", "Unknown GPU"),
|
||||
"vendor": obj.get("vendor", "Unknown"),
|
||||
"description": obj.get("description", ""),
|
||||
}
|
||||
self.gpus.append(infos)
|
||||
|
||||
def walk_bridge(self, obj):
|
||||
if "children" not in obj:
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import logging
|
||||
import os
|
||||
import re
|
||||
from itertools import chain
|
||||
from itertools import chain, islice
|
||||
|
||||
import netifaces
|
||||
from netaddr import IPAddress
|
||||
|
@ -413,11 +413,16 @@ class Network(object):
|
|||
|
||||
# delete IP on netbox that are not known on this server
|
||||
if len(nb_nics):
|
||||
netbox_ips = nb.ipam.ip_addresses.filter(
|
||||
**{self.intf_type: [x.id for x in nb_nics]}
|
||||
)
|
||||
def batched(it, n):
|
||||
while batch := tuple(islice(it, n)):
|
||||
yield batch
|
||||
|
||||
netbox_ips = []
|
||||
for ids in batched((x.id for x in nb_nics), 25):
|
||||
netbox_ips += list(
|
||||
nb.ipam.ip_addresses.filter(**{self.intf_type: ids})
|
||||
)
|
||||
|
||||
netbox_ips = list(netbox_ips)
|
||||
all_local_ips = list(chain.from_iterable([
|
||||
x['ip'] for x in self.nics if x['ip'] is not None
|
||||
]))
|
||||
|
@ -544,7 +549,7 @@ class ServerNetwork(Network):
|
|||
|
||||
switch_interface = self.lldp.get_switch_port(nb_server_interface.name)
|
||||
nb_switch_interface = nb.dcim.interfaces.get(
|
||||
device=nb_switch,
|
||||
device_id=nb_switch.id,
|
||||
name=switch_interface,
|
||||
)
|
||||
if nb_switch_interface is None:
|
||||
|
@ -556,10 +561,12 @@ class ServerNetwork(Network):
|
|||
switch_ip,
|
||||
))
|
||||
cable = nb.dcim.cables.create(
|
||||
termination_a_id=nb_server_interface.id,
|
||||
termination_a_type="dcim.interface",
|
||||
termination_b_id=nb_switch_interface.id,
|
||||
termination_b_type="dcim.interface",
|
||||
a_terminations=[
|
||||
{"object_type": "dcim.interface", "object_id": nb_server_interface.id},
|
||||
],
|
||||
b_terminations=[
|
||||
{"object_type": "dcim.interface", "object_id": nb_switch_interface.id},
|
||||
],
|
||||
)
|
||||
nb_server_interface.cable = cable
|
||||
logging.info(
|
||||
|
@ -579,7 +586,7 @@ class ServerNetwork(Network):
|
|||
switch_ip, switch_interface, nb_server_interface
|
||||
)
|
||||
else:
|
||||
nb_sw_int = nb_server_interface.cable.termination_b
|
||||
nb_sw_int = nb_server_interface.cable.b_terminations[0]
|
||||
nb_sw = nb_sw_int.device
|
||||
nb_mgmt_int = nb.dcim.interfaces.get(
|
||||
device_id=nb_sw.id,
|
||||
|
|
|
@ -199,7 +199,7 @@ class ServerBase():
|
|||
name=self.get_chassis_name(),
|
||||
device_type=device_type.id,
|
||||
serial=serial,
|
||||
device_role=device_role.id,
|
||||
role=device_role.id,
|
||||
site=datacenter.id if datacenter else None,
|
||||
tenant=tenant.id if tenant else None,
|
||||
rack=rack.id if rack else None,
|
||||
|
@ -220,7 +220,7 @@ class ServerBase():
|
|||
new_blade = nb.dcim.devices.create(
|
||||
name=hostname,
|
||||
serial=serial,
|
||||
device_role=device_role.id,
|
||||
role=device_role.id,
|
||||
device_type=device_type.id,
|
||||
parent_device=chassis.id,
|
||||
site=datacenter.id if datacenter else None,
|
||||
|
@ -243,7 +243,7 @@ class ServerBase():
|
|||
new_blade = nb.dcim.devices.create(
|
||||
name=hostname,
|
||||
serial=serial,
|
||||
device_role=device_role.id,
|
||||
role=device_role.id,
|
||||
device_type=device_type.id,
|
||||
parent_device=chassis.id,
|
||||
site=datacenter.id if datacenter else None,
|
||||
|
@ -272,7 +272,7 @@ class ServerBase():
|
|||
new_server = nb.dcim.devices.create(
|
||||
name=hostname,
|
||||
serial=serial,
|
||||
device_role=device_role.id,
|
||||
role=device_role.id,
|
||||
device_type=device_type.id,
|
||||
platform=self.device_platform.id,
|
||||
site=datacenter.id if datacenter else None,
|
||||
|
|
|
@ -43,8 +43,7 @@ class VirtualMachine(object):
|
|||
self.device_platform = get_device_platform(config.device.platform)
|
||||
|
||||
self.tags = list(set(config.device.tags.split(','))) if config.device.tags else []
|
||||
if self.tags and len(self.tags):
|
||||
create_netbox_tags(self.tags)
|
||||
self.nb_tags = create_netbox_tags(self.tags)
|
||||
|
||||
def get_memory(self):
|
||||
mem_bytes = os.sysconf('SC_PAGE_SIZE') * os.sysconf('SC_PHYS_PAGES') # e.g. 4015976448
|
||||
|
@ -108,7 +107,7 @@ class VirtualMachine(object):
|
|||
vcpus=vcpus,
|
||||
memory=memory,
|
||||
tenant=tenant.id if tenant else None,
|
||||
tags=self.tags,
|
||||
tags=[{'name': x} for x in self.tags],
|
||||
)
|
||||
created = True
|
||||
|
||||
|
@ -122,9 +121,18 @@ class VirtualMachine(object):
|
|||
if vm.memory != memory:
|
||||
vm.memory = memory
|
||||
updated += 1
|
||||
if sorted(set(vm.tags)) != sorted(set(self.tags)):
|
||||
vm.tags = self.tags
|
||||
|
||||
vm_tags = sorted(set([x.name for x in vm.tags]))
|
||||
tags = sorted(set(self.tags))
|
||||
if vm_tags != tags:
|
||||
new_tags_ids = [x.id for x in self.nb_tags]
|
||||
if not config.preserve_tags:
|
||||
vm.tags = new_tags_ids
|
||||
else:
|
||||
vm_tags_ids = [x.id for x in vm.tags]
|
||||
vm.tags = sorted(set(new_tags_ids + vm_tags_ids))
|
||||
updated += 1
|
||||
|
||||
if vm.platform != self.device_platform:
|
||||
vm.platform = self.device_platform
|
||||
updated += 1
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
certifi==2023.7.22
|
||||
charset-normalizer==3.2.0
|
||||
distro==1.8.0
|
||||
idna==3.4
|
||||
jsonargparse==4.23.1
|
||||
netaddr==0.8.0
|
||||
netifaces2==0.0.18
|
||||
packaging==23.1
|
||||
pynetbox==7.0.1
|
||||
python-slugify==8.0.1
|
||||
PyYAML==6.0.1
|
||||
requests==2.31.0
|
||||
text-unidecode==1.3
|
||||
typing_extensions==4.7.1
|
||||
urllib3==2.0.4
|
||||
pynetbox==7.3.4
|
||||
netaddr==1.3.0
|
||||
netifaces2==0.0.22
|
||||
pyyaml==6.0.1
|
||||
jsonargparse==4.32.0
|
||||
python-slugify==8.0.4
|
||||
packaging==23.2
|
||||
distro==1.9.0
|
||||
|
|
Loading…
Add table
Reference in a new issue