Compare commits

..

24 commits

Author SHA1 Message Date
Grégoire Compagnon
7d268ea0e8
Return 0 if everything ok as excepted in a shell 2024-10-21 12:30:09 +02:00
Grégoire Compagnon
9d496c6854
Check if it's a VM before running lldp related actions 2024-10-21 12:30:09 +02:00
Grégoire Compagnon
6ef23eae4d
Add missing prtint debug 2024-10-21 12:30:09 +02:00
12ceea413c Merge pull request 'Replaced deprecated module pkg_resources' (#311) from ribetm/py312 into master
Reviewed-on: #311
2024-10-21 10:18:18 +02:00
7a968deee9 Merge pull request 'Make lshw scrpping more resilient' (#292) from sinavir/fix_gpu_without_vendor into master
Reviewed-on: #292
2024-10-21 10:15:27 +02:00
d55cbd62fc Merge pull request 'Fix not working tag with VM' (#293) from sinavir/fix_vm_tags into master
Reviewed-on: #293
2024-10-21 10:15:11 +02:00
59ce76fc29 Merge pull request 'feat(network): Batch requests when filtering on interfaces' (#297) from Tom-Hubrecht/master into master
Reviewed-on: #297
2024-10-21 10:01:35 +02:00
Mathis Ribet
c3d3e6857a
Replaced deprecated module pkg_resources
Removed in py3.12
2024-10-17 20:52:28 +02:00
CllaudiaB
8dde35dd31
Merge pull request #306 from CllaudiaB/netifaces2
netifaces2
2024-10-17 11:01:22 +02:00
clbu
de88ca85b9
fix(network): use netifaces2 2024-10-17 10:46:05 +02:00
CllaudiaB
514627aa72
Merge pull request #305 from CllaudiaB/version
Support Netbox 3
2024-10-17 10:37:09 +02:00
CllaudiaB
4b54a0a3db
fix: typo
Co-authored-by: n1nj4- <39305378+n1nj444@users.noreply.github.com>
2024-10-17 10:26:41 +02:00
clbu
e44fd2fe78
fix(network): retrieve switch interface using id instead of name 2024-10-16 10:44:08 +02:00
clbu
1429fedb9d
fix(network): cable
https://github.com/netbox-community/netbox/issues/9102
2024-10-10 23:15:55 +02:00
clbu
818c835711
fix(requirements): update dependencies version 2024-10-09 15:45:07 +02:00
clbu
40af19e801
fix(readme): required Netbox version 2024-10-09 15:32:25 +02:00
clbu
1d69f4e2f0
python version compatible with dependencies 2024-10-09 15:12:39 +02:00
clbu
a7104b6b94
updating dependencies 2024-08-07 12:29:19 +02:00
clbu
ee41fb4fc2
replace device_role with role 2024-08-07 12:24:49 +02:00
Tom Hubrecht
e04d0c6d59 feat(network): Batch requests when filtering on interfaces
This avoids an issue where the requested URI is too long when many
interfaces are present
2024-05-07 13:54:27 +02:00
sinavir
c9a57de843 fix: vm tags 2024-03-28 12:07:17 +01:00
sinavir
f512e7a0a9 fix: replace list.push by list.append 2024-03-27 18:49:05 +01:00
sinavir
116334be2f fix: make lshw props finding more resilient 2024-03-27 17:12:48 +01:00
Oleg Zagrebelsky
ba4cdb217b
fix lldp.py (#280)
Co-authored-by: kszd487 <kszd487@ukc02dd0ylp3ywui.lan>
2023-08-28 18:54:53 +02:00
10 changed files with 69 additions and 58 deletions

1
.gitignore vendored
View file

@ -181,3 +181,4 @@ dmypy.json
# End of https://www.gitignore.io/api/emacs,python
netbox-docker
/.vscode

View file

@ -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)

View file

@ -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

View file

@ -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 \

View file

@ -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, {})

View file

@ -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:

View file

@ -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,

View file

@ -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,

View file

@ -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

View file

@ -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