annet 0.13.3__py3-none-any.whl → 0.13.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of annet might be problematic. Click here for more details.
- annet/adapters/netbox/common/models.py +32 -1
- annet/adapters/netbox/v37/storage.py +77 -12
- annet/annlib/netdev/views/hardware.py +4 -0
- annet/gen.py +11 -9
- {annet-0.13.3.dist-info → annet-0.13.4.dist-info}/METADATA +1 -1
- {annet-0.13.3.dist-info → annet-0.13.4.dist-info}/RECORD +11 -11
- {annet-0.13.3.dist-info → annet-0.13.4.dist-info}/AUTHORS +0 -0
- {annet-0.13.3.dist-info → annet-0.13.4.dist-info}/LICENSE +0 -0
- {annet-0.13.3.dist-info → annet-0.13.4.dist-info}/WHEEL +0 -0
- {annet-0.13.3.dist-info → annet-0.13.4.dist-info}/entry_points.txt +0 -0
- {annet-0.13.3.dist-info → annet-0.13.4.dist-info}/top_level.txt +0 -0
|
@@ -39,6 +39,22 @@ class DeviceIp:
|
|
|
39
39
|
family: int
|
|
40
40
|
|
|
41
41
|
|
|
42
|
+
@dataclass
|
|
43
|
+
class Prefix:
|
|
44
|
+
id: int
|
|
45
|
+
prefix: str
|
|
46
|
+
site: Entity | None
|
|
47
|
+
vrf: Entity | None
|
|
48
|
+
tenant: Entity | None
|
|
49
|
+
vlan: Entity | None
|
|
50
|
+
role: Entity | None
|
|
51
|
+
status: Label
|
|
52
|
+
is_pool: bool
|
|
53
|
+
custom_fields: dict[str, Any]
|
|
54
|
+
created: datetime
|
|
55
|
+
last_updated: datetime
|
|
56
|
+
|
|
57
|
+
|
|
42
58
|
@dataclass
|
|
43
59
|
class IpAddress:
|
|
44
60
|
id: int
|
|
@@ -50,12 +66,27 @@ class IpAddress:
|
|
|
50
66
|
tags: List[Entity]
|
|
51
67
|
created: datetime
|
|
52
68
|
last_updated: datetime
|
|
69
|
+
prefix: Optional[Prefix] = None
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
@dataclass
|
|
73
|
+
class InterfaceConnectedEndpoint(Entity):
|
|
74
|
+
device: Entity
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
@dataclass
|
|
78
|
+
class InterfaceType:
|
|
79
|
+
value: str
|
|
80
|
+
label: str
|
|
53
81
|
|
|
54
82
|
|
|
55
83
|
@dataclass
|
|
56
84
|
class Interface(Entity):
|
|
57
85
|
device: Entity
|
|
58
86
|
enabled: bool
|
|
87
|
+
description: str
|
|
88
|
+
type: InterfaceType
|
|
89
|
+
connected_endpoints: Optional[list[InterfaceConnectedEndpoint]]
|
|
59
90
|
display: str = ""
|
|
60
91
|
ip_addresses: List[IpAddress] = field(default_factory=list)
|
|
61
92
|
|
|
@@ -64,7 +95,6 @@ class Interface(Entity):
|
|
|
64
95
|
class NetboxDevice(Entity):
|
|
65
96
|
url: str
|
|
66
97
|
storage: Storage
|
|
67
|
-
neighbours_ids: List[int]
|
|
68
98
|
|
|
69
99
|
display: str
|
|
70
100
|
device_type: DeviceType
|
|
@@ -92,6 +122,7 @@ class NetboxDevice(Entity):
|
|
|
92
122
|
breed: str
|
|
93
123
|
|
|
94
124
|
interfaces: List[Interface]
|
|
125
|
+
neighbours: Optional[List["NetboxDevice"]]
|
|
95
126
|
|
|
96
127
|
# compat
|
|
97
128
|
|
|
@@ -1,5 +1,7 @@
|
|
|
1
1
|
from logging import getLogger
|
|
2
|
-
from typing import Optional, List, Union
|
|
2
|
+
from typing import Optional, List, Union, Dict
|
|
3
|
+
from ipaddress import ip_interface
|
|
4
|
+
from collections import defaultdict
|
|
3
5
|
|
|
4
6
|
from adaptix import P
|
|
5
7
|
from adaptix.conversion import impl_converter, link
|
|
@@ -28,18 +30,21 @@ def extend_device_base(
|
|
|
28
30
|
interfaces: List[models.Interface],
|
|
29
31
|
hw: Optional[HardwareView],
|
|
30
32
|
breed: str,
|
|
33
|
+
neighbours: Optional[List[models.NetboxDevice]],
|
|
31
34
|
storage: Storage,
|
|
32
|
-
neighbours_ids: List[int],
|
|
33
35
|
) -> models.NetboxDevice:
|
|
34
36
|
...
|
|
35
37
|
|
|
36
38
|
|
|
37
39
|
def extend_device(
|
|
38
|
-
device: api_models.Device,
|
|
40
|
+
device: api_models.Device,
|
|
41
|
+
interfaces: List[models.Interface],
|
|
42
|
+
neighbours: Optional[List[models.NetboxDevice]],
|
|
43
|
+
storage: Storage,
|
|
39
44
|
) -> models.NetboxDevice:
|
|
40
45
|
return extend_device_base(
|
|
41
46
|
device=device,
|
|
42
|
-
interfaces=
|
|
47
|
+
interfaces=interfaces,
|
|
43
48
|
breed=get_breed(
|
|
44
49
|
device.device_type.manufacturer.name,
|
|
45
50
|
device.device_type.model,
|
|
@@ -48,7 +53,7 @@ def extend_device(
|
|
|
48
53
|
device.device_type.manufacturer.name,
|
|
49
54
|
device.device_type.model,
|
|
50
55
|
),
|
|
51
|
-
|
|
56
|
+
neighbours=neighbours,
|
|
52
57
|
storage=storage,
|
|
53
58
|
)
|
|
54
59
|
|
|
@@ -61,6 +66,13 @@ def extend_interface(
|
|
|
61
66
|
...
|
|
62
67
|
|
|
63
68
|
|
|
69
|
+
@impl_converter
|
|
70
|
+
def extend_ip_address(
|
|
71
|
+
ip_address: models.IpAddress, prefix: Optional[models.Prefix],
|
|
72
|
+
) -> models.IpAddress:
|
|
73
|
+
...
|
|
74
|
+
|
|
75
|
+
|
|
64
76
|
class NetboxStorageV37(Storage):
|
|
65
77
|
def __init__(self, opts: Optional[NetboxStorageOpts] = None):
|
|
66
78
|
self.netbox = NetboxV37(
|
|
@@ -95,15 +107,29 @@ class NetboxStorageV37(Storage):
|
|
|
95
107
|
if isinstance(query, list):
|
|
96
108
|
query = NetboxQuery.new(query)
|
|
97
109
|
device_ids = {
|
|
98
|
-
device.id: extend_device(
|
|
110
|
+
device.id: extend_device(
|
|
111
|
+
device=device,
|
|
112
|
+
interfaces=[],
|
|
113
|
+
neighbours=[],
|
|
114
|
+
storage=self,
|
|
115
|
+
)
|
|
99
116
|
for device in self._load_devices(query)
|
|
100
117
|
}
|
|
101
118
|
if not device_ids:
|
|
102
119
|
return []
|
|
103
120
|
|
|
104
121
|
interfaces = self._load_interfaces(list(device_ids))
|
|
122
|
+
neighbours = {x.id: x for x in self._load_neighbours(interfaces)}
|
|
123
|
+
neighbours_seen = defaultdict(set)
|
|
124
|
+
|
|
105
125
|
for interface in interfaces:
|
|
106
126
|
device_ids[interface.device.id].interfaces.append(interface)
|
|
127
|
+
for e in interface.connected_endpoints or []:
|
|
128
|
+
neighbour = neighbours[e.device.id]
|
|
129
|
+
if neighbour.id not in neighbours_seen[interface.device.id]:
|
|
130
|
+
neighbours_seen[interface.device.id].add(neighbour.id)
|
|
131
|
+
device_ids[interface.device.id].neighbours.append(neighbour)
|
|
132
|
+
|
|
107
133
|
return list(device_ids.values())
|
|
108
134
|
|
|
109
135
|
def _load_devices(self, query: NetboxQuery) -> List[api_models.Device]:
|
|
@@ -118,26 +144,65 @@ class NetboxStorageV37(Storage):
|
|
|
118
144
|
if is_supported(device.device_type.manufacturer.name)
|
|
119
145
|
]
|
|
120
146
|
|
|
121
|
-
def
|
|
122
|
-
models.Interface]:
|
|
123
|
-
interfaces = self.netbox.dcim_all_interfaces(device_id=device_ids)
|
|
147
|
+
def _extend_interfaces(self, interfaces: List[models.Interface]) -> List[models.Interface]:
|
|
124
148
|
extended_ifaces = {
|
|
125
149
|
interface.id: extend_interface(interface, [])
|
|
126
|
-
for interface in interfaces
|
|
150
|
+
for interface in interfaces
|
|
127
151
|
}
|
|
128
152
|
|
|
129
153
|
ips = self.netbox.ipam_all_ip_addresses(interface_id=list(extended_ifaces))
|
|
154
|
+
ip_to_cidrs: Dict[str, str] = {ip.address: str(ip_interface(ip.address).network) for ip in ips.results}
|
|
155
|
+
prefixes = self.netbox.ipam_all_prefixes(prefix=list(ip_to_cidrs.values()))
|
|
156
|
+
cidr_to_prefix: Dict[str, models.Prefix] = {x.prefix: x for x in prefixes.results}
|
|
157
|
+
|
|
130
158
|
for ip in ips.results:
|
|
159
|
+
cidr = ip_to_cidrs[ip.address]
|
|
160
|
+
ip = extend_ip_address(ip, prefix=cidr_to_prefix.get(cidr))
|
|
131
161
|
extended_ifaces[ip.assigned_object_id].ip_addresses.append(ip)
|
|
132
162
|
return list(extended_ifaces.values())
|
|
133
163
|
|
|
164
|
+
def _load_interfaces(self, device_ids: List[int]) -> List[
|
|
165
|
+
models.Interface]:
|
|
166
|
+
interfaces = self.netbox.dcim_all_interfaces(device_id=device_ids)
|
|
167
|
+
return self._extend_interfaces(interfaces.results)
|
|
168
|
+
|
|
169
|
+
def _load_interfaces_by_id(self, ids: List[int]) -> List[models.Interface]:
|
|
170
|
+
interfaces = self.netbox.dcim_all_interfaces_by_id(id=ids)
|
|
171
|
+
return self._extend_interfaces(interfaces.results)
|
|
172
|
+
|
|
173
|
+
def _load_neighbours(self, interfaces: List[models.Interface]) -> List[models.NetboxDevice]:
|
|
174
|
+
endpoints = [e for i in interfaces for e in i.connected_endpoints or []]
|
|
175
|
+
remote_interfaces_ids = [e.id for e in endpoints]
|
|
176
|
+
neighbours_ids = [e.device.id for e in endpoints]
|
|
177
|
+
neighbours_ifaces_dics = defaultdict(list)
|
|
178
|
+
# load only the connected interface to speed things up
|
|
179
|
+
for iface in self._load_interfaces_by_id(remote_interfaces_ids):
|
|
180
|
+
neighbours_ifaces_dics[iface.device.id].append(iface)
|
|
181
|
+
neighbours = []
|
|
182
|
+
for neighbour in self.netbox.dcim_all_devices_by_id(id=neighbours_ids).results:
|
|
183
|
+
extended_neighbour = extend_device(
|
|
184
|
+
device=neighbour,
|
|
185
|
+
storage=self,
|
|
186
|
+
interfaces=neighbours_ifaces_dics[neighbour.id],
|
|
187
|
+
neighbours=None, # do not load recursively
|
|
188
|
+
)
|
|
189
|
+
neighbours.append(extended_neighbour)
|
|
190
|
+
return neighbours
|
|
191
|
+
|
|
134
192
|
def get_device(
|
|
135
193
|
self, obj_id, preload_neighbors=False, use_mesh=None,
|
|
136
194
|
**kwargs,
|
|
137
195
|
) -> models.NetboxDevice:
|
|
138
196
|
device = self.netbox.dcim_device(obj_id)
|
|
139
|
-
|
|
140
|
-
|
|
197
|
+
interfaces = self._load_interfaces([device.id])
|
|
198
|
+
neighbours = self._load_neighbours(interfaces)
|
|
199
|
+
|
|
200
|
+
res = extend_device(
|
|
201
|
+
device=device,
|
|
202
|
+
storage=self,
|
|
203
|
+
interfaces=interfaces[device.id],
|
|
204
|
+
neighbours=neighbours,
|
|
205
|
+
)
|
|
141
206
|
return res
|
|
142
207
|
|
|
143
208
|
def flush_perf(self):
|
annet/gen.py
CHANGED
|
@@ -513,9 +513,11 @@ def worker(device_id, args: ShowGenOptions, stdin, loader: "Loader", filterer: F
|
|
|
513
513
|
dumped_data = json.dumps(data, indent=4, sort_keys=True, ensure_ascii=False)
|
|
514
514
|
yield (output_driver.entire_config_dest_path(device, path), dumped_data, False)
|
|
515
515
|
|
|
516
|
-
|
|
517
|
-
|
|
518
|
-
if
|
|
516
|
+
# Consider result of partial run empty and create an empty dest file
|
|
517
|
+
# only if there are some acl rules that has been matched.
|
|
518
|
+
# Otherwise treat it as if no supported generators have been found.
|
|
519
|
+
acl_rules = res.get_acl_rules(args.acl_safe)
|
|
520
|
+
if device.hw.vendor in platform.VENDOR_REVERSES and acl_rules:
|
|
519
521
|
orderer = patching.Orderer.from_hw(device.hw)
|
|
520
522
|
yield (output_driver.cfg_file_names(device)[0],
|
|
521
523
|
format_config_blocks(
|
|
@@ -606,14 +608,14 @@ def _print_perf(gen_type, perf):
|
|
|
606
608
|
(
|
|
607
609
|
(gen if not method else None),
|
|
608
610
|
(method or "." * 30),
|
|
609
|
-
sum(map(itemgetter("time"), stat)),
|
|
610
|
-
(min(map(itemgetter("time"), stat)) if
|
|
611
|
-
(percentile(stat, 0.95, itemgetter("time")) if
|
|
612
|
-
(max(map(itemgetter("time"), stat)) if
|
|
613
|
-
(len(stat) if
|
|
611
|
+
sum(map(itemgetter("time"), stat) if stat else None),
|
|
612
|
+
(min(map(itemgetter("time"), stat)) if stat else None),
|
|
613
|
+
(percentile(stat, 0.95, itemgetter("time")) if stat else None),
|
|
614
|
+
(max(map(itemgetter("time"), stat)) if stat else None),
|
|
615
|
+
(len(stat) if stat else None),
|
|
614
616
|
(len(list(filter(
|
|
615
617
|
lambda item: item in ["call", "disk_write"],
|
|
616
|
-
map(itemgetter("op"), stat)))) if
|
|
618
|
+
map(itemgetter("op"), stat)))) if stat else None),
|
|
617
619
|
)
|
|
618
620
|
|
|
619
621
|
for (gen, gen_perf) in sorted(
|
|
@@ -8,7 +8,7 @@ annet/deploy.py,sha256=B8E0P_VvCrS2URjFvgmUiIkHp95g7pAWfmT34igaDeo,18893
|
|
|
8
8
|
annet/diff.py,sha256=zLcaCnb4lZRUb7frpH1CstQ3kacRcCblZs1uLG8J5lk,3391
|
|
9
9
|
annet/executor.py,sha256=EaeQ_JeRFuUUHUoR2LXDcNvY7IVg0eA2d6zSmQVJt-M,19216
|
|
10
10
|
annet/filtering.py,sha256=F4ZKUCU3Yb1RlL2zKdyHtVUaWPzjWF4vWyMcdygKNYk,852
|
|
11
|
-
annet/gen.py,sha256=
|
|
11
|
+
annet/gen.py,sha256=jlAkT_phlIYrpOIqVc0GrApWp3Y8zr8lyxnZgIdL2F4,33533
|
|
12
12
|
annet/hardware.py,sha256=HYPDfji_GdRn5S0_0fl4rvM7byOY9aHxG6VMAtsLaxE,1090
|
|
13
13
|
annet/implicit.py,sha256=QigK4uoxvrFho2h9yFjOq1d9rLsC5xFlAU4bKkCuMWk,5139
|
|
14
14
|
annet/lib.py,sha256=tQQlxZg1A2Q-tp18PoqBuORQmvP5dAAmAPvP6bBA6a0,3764
|
|
@@ -27,14 +27,14 @@ annet/adapters/netbox/provider.py,sha256=OM7Hq2vnMHNVBfubJvx2qJlMYm3VvKhomdLMNO8
|
|
|
27
27
|
annet/adapters/netbox/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
28
28
|
annet/adapters/netbox/common/client.py,sha256=-lWZmphD-OPuLIHNKhW_h2bnjrVaiyKYAD_MUPasEbo,2483
|
|
29
29
|
annet/adapters/netbox/common/manufacturer.py,sha256=UH_tEKT3GXC8WSm15q0xxXRE7aj0b0icgwmR--PRWBs,1771
|
|
30
|
-
annet/adapters/netbox/common/models.py,sha256=
|
|
30
|
+
annet/adapters/netbox/common/models.py,sha256=rmFQ93NUCnFM-p58aS4sjiOaTuYR0Xz65soiW7IQfDk,2516
|
|
31
31
|
annet/adapters/netbox/common/query.py,sha256=OgUuF-bvshpoBUkrOs0tsMUAhjTsttzx3VV30ryFl0Y,577
|
|
32
32
|
annet/adapters/netbox/common/status_client.py,sha256=W4nTb2yvBlJ2UkWUmUhKQ2PaSQb1shjhHj5ebb4s2s4,591
|
|
33
33
|
annet/adapters/netbox/common/storage_opts.py,sha256=rl_0pr3VzmOy6PDZIUMkKSBfJh90gD9TFL3yBhK_8ME,337
|
|
34
34
|
annet/adapters/netbox/v24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
35
35
|
annet/adapters/netbox/v24/storage.py,sha256=uDcAuabORu8ag3OXDHXKDK469Pd-kNXpUI_Cg-hgW_k,5919
|
|
36
36
|
annet/adapters/netbox/v37/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
37
|
-
annet/adapters/netbox/v37/storage.py,sha256=
|
|
37
|
+
annet/adapters/netbox/v37/storage.py,sha256=9CxLr2tMWvGA1BLtjd5TTp2qEUQ_aYJq0eZSe-S242E,7372
|
|
38
38
|
annet/annlib/__init__.py,sha256=fT1l4xV5fqqg8HPw9HqmZVN2qwS8i6X1aIm2zGDjxKY,252
|
|
39
39
|
annet/annlib/command.py,sha256=uuBddMQphtn8P5MO5kzIa8_QrtMns-k05VeKv1bcAuA,1043
|
|
40
40
|
annet/annlib/diff.py,sha256=UPt3kYFQdQdVVy3ePYzNHPAxMVmHxCrCnZnMCV6ou2Q,4587
|
|
@@ -52,7 +52,7 @@ annet/annlib/netdev/devdb/__init__.py,sha256=aKYjjLbJebdKBjnGDpVLQdSqrV2JL24spGm
|
|
|
52
52
|
annet/annlib/netdev/devdb/data/devdb.json,sha256=NldGS8_whScc7eC_CZPEDB9AoxtfvK_51oJVFIu0Tlo,5072
|
|
53
53
|
annet/annlib/netdev/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
54
54
|
annet/annlib/netdev/views/dump.py,sha256=XJ6UO6sYSO5pIoe5R4eTQmKwx0_JJ71_h8QSYAURtyk,4184
|
|
55
|
-
annet/annlib/netdev/views/hardware.py,sha256=
|
|
55
|
+
annet/annlib/netdev/views/hardware.py,sha256=o-w-k1bOORWwEnSGsDq-9Q_oIeH3yQv9eiCJn_UgG-Y,3324
|
|
56
56
|
annet/annlib/rbparser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
57
57
|
annet/annlib/rbparser/acl.py,sha256=RR8yPt6t96_IiyuKVbeZ-3x32cyhBAT2wC1y99oWBO8,3931
|
|
58
58
|
annet/annlib/rbparser/deploying.py,sha256=ACT8QNhDAhJx3ZKuGh2nYBOrpdka2qEKuLDxvQAGKLk,1649
|
|
@@ -124,10 +124,10 @@ annet/rulebook/texts/routeros.rul,sha256=ipfxjj0mjFef6IsUlupqx4BY_Je_OUb8u_U1019
|
|
|
124
124
|
annet_generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
125
125
|
annet_generators/example/__init__.py,sha256=zVd8_DrXuOASrNzg2Ab94rPyvJff83L-_HppDFxnUjM,228
|
|
126
126
|
annet_generators/example/lldp.py,sha256=68CLrK7vxTQQy9XIBxtywuEdBNlIlfXGYj8_wYWs5UI,1146
|
|
127
|
-
annet-0.13.
|
|
128
|
-
annet-0.13.
|
|
129
|
-
annet-0.13.
|
|
130
|
-
annet-0.13.
|
|
131
|
-
annet-0.13.
|
|
132
|
-
annet-0.13.
|
|
133
|
-
annet-0.13.
|
|
127
|
+
annet-0.13.4.dist-info/AUTHORS,sha256=rh3w5P6gEgqmuC-bw-HB68vBCr-yIBFhVL0PG4hguLs,878
|
|
128
|
+
annet-0.13.4.dist-info/LICENSE,sha256=yPxl7dno02Pw7gAcFPIFONzx_gapwDoPXsIsh6Y7lC0,1079
|
|
129
|
+
annet-0.13.4.dist-info/METADATA,sha256=Ug49vbZb6q3AP41fId0L8o2hCst2KTJ9V4l2MgYF2rA,694
|
|
130
|
+
annet-0.13.4.dist-info/WHEEL,sha256=GJ7t_kWBFywbagK5eo9IoUwLW6oyOeTKmQ-9iHFVNxQ,92
|
|
131
|
+
annet-0.13.4.dist-info/entry_points.txt,sha256=yHimujIzR2bwNIbb--MTs_GpXiAve89Egpu2LlgTEkg,119
|
|
132
|
+
annet-0.13.4.dist-info/top_level.txt,sha256=QsoTZBsUtwp_FEcmRwuN8QITBmLOZFqjssRfKilGbP8,23
|
|
133
|
+
annet-0.13.4.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|