annet 0.16.7__py3-none-any.whl → 0.16.9__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.

Files changed (37) hide show
  1. annet/adapters/fetchers/__init__.py +0 -0
  2. annet/adapters/fetchers/stub/__init__.py +0 -0
  3. annet/adapters/fetchers/stub/fetcher.py +19 -0
  4. annet/adapters/file/__init__.py +0 -0
  5. annet/adapters/file/provider.py +226 -0
  6. annet/adapters/netbox/common/models.py +108 -3
  7. annet/adapters/netbox/v37/storage.py +31 -3
  8. annet/annlib/netdev/views/hardware.py +31 -0
  9. annet/bgp_models.py +266 -0
  10. annet/configs/context.yml +2 -3
  11. annet/configs/logging.yaml +1 -0
  12. annet/generators/__init__.py +18 -4
  13. annet/implicit.py +5 -0
  14. annet/mesh/__init__.py +16 -0
  15. annet/mesh/basemodel.py +180 -0
  16. annet/mesh/device_models.py +62 -0
  17. annet/mesh/executor.py +248 -0
  18. annet/mesh/match_args.py +165 -0
  19. annet/mesh/models_converter.py +84 -0
  20. annet/mesh/peer_models.py +98 -0
  21. annet/mesh/registry.py +212 -0
  22. annet/rulebook/routeros/__init__.py +0 -0
  23. annet/rulebook/routeros/file.py +5 -0
  24. annet/rulebook/texts/cisco.order +5 -2
  25. annet/rulebook/texts/cisco.rul +6 -0
  26. annet/storage.py +41 -2
  27. {annet-0.16.7.dist-info → annet-0.16.9.dist-info}/METADATA +3 -1
  28. {annet-0.16.7.dist-info → annet-0.16.9.dist-info}/RECORD +37 -18
  29. annet_generators/example/__init__.py +1 -3
  30. annet_generators/mesh_example/__init__.py +9 -0
  31. annet_generators/mesh_example/bgp.py +43 -0
  32. annet_generators/mesh_example/mesh_logic.py +28 -0
  33. {annet-0.16.7.dist-info → annet-0.16.9.dist-info}/AUTHORS +0 -0
  34. {annet-0.16.7.dist-info → annet-0.16.9.dist-info}/LICENSE +0 -0
  35. {annet-0.16.7.dist-info → annet-0.16.9.dist-info}/WHEEL +0 -0
  36. {annet-0.16.7.dist-info → annet-0.16.9.dist-info}/entry_points.txt +0 -0
  37. {annet-0.16.7.dist-info → annet-0.16.9.dist-info}/top_level.txt +0 -0
annet/mesh/registry.py ADDED
@@ -0,0 +1,212 @@
1
+ from dataclasses import dataclass
2
+ from typing import Callable, Any
3
+
4
+ from .match_args import MatchExpr, PairMatcher, SingleMatcher
5
+ from .match_args import MatchedArgs
6
+ from .device_models import GlobalOptionsDTO
7
+ from .peer_models import PeerDTO, MeshSession
8
+
9
+
10
+ class DirectPeer(PeerDTO):
11
+ match: MatchedArgs
12
+ device: Any
13
+ ports: list[str]
14
+
15
+ def __init__(self, match: MatchedArgs, device: Any, ports: list[str]) -> None:
16
+ super().__init__()
17
+ self.match = match
18
+ self.device = device
19
+ self.ports = ports
20
+
21
+
22
+ class IndirectPeer(PeerDTO):
23
+ match: MatchedArgs
24
+ device: Any
25
+
26
+ def __init__(self, match: MatchedArgs, device: Any) -> None:
27
+ super().__init__()
28
+ self.match = match
29
+ self.device = device
30
+
31
+
32
+ class GlobalOptions(GlobalOptionsDTO):
33
+ match: MatchedArgs
34
+ device: Any
35
+
36
+ def __init__(self, match: MatchedArgs, device: Any) -> None:
37
+ super().__init__()
38
+ self.match = match
39
+ self.device = device
40
+
41
+
42
+ GlobalHandler = Callable[[GlobalOptions], None]
43
+
44
+
45
+ @dataclass
46
+ class GlobalRule:
47
+ matcher: SingleMatcher
48
+ handler: GlobalHandler
49
+
50
+
51
+ DirectHandler = Callable[[DirectPeer, DirectPeer, MeshSession], None]
52
+ IndirectHandler = Callable[[IndirectPeer, IndirectPeer, MeshSession], None]
53
+
54
+
55
+ @dataclass
56
+ class DirectRule:
57
+ __slots__ = ("matcher", "handler")
58
+ matcher: PairMatcher
59
+ handler: DirectHandler
60
+
61
+
62
+ @dataclass
63
+ class IndirectRule:
64
+ __slots__ = ("matcher", "handler")
65
+ matcher: PairMatcher
66
+ handler: IndirectHandler
67
+
68
+
69
+ @dataclass
70
+ class MatchedGlobal:
71
+ __slots__ = ("match", "handler")
72
+ match: MatchedArgs
73
+ handler: GlobalHandler
74
+
75
+
76
+ @dataclass
77
+ class MatchedDirectPair:
78
+ __slots__ = ("handler", "direct_order", "name_left", "name_right", "match_left", "match_right")
79
+ handler: DirectHandler
80
+ direct_order: bool
81
+ name_left: str
82
+ name_right: str
83
+ match_left: MatchedArgs
84
+ match_right: MatchedArgs
85
+
86
+
87
+ @dataclass
88
+ class MatchedIndirectPair:
89
+ __slots__ = ("handler", "direct_order", "name_left", "name_right", "match_left", "match_right")
90
+ handler: IndirectHandler
91
+ direct_order: bool
92
+ name_left: str
93
+ name_right: str
94
+ match_left: MatchedArgs
95
+ match_right: MatchedArgs
96
+
97
+
98
+ class MeshRulesRegistry:
99
+ def __init__(self, match_short_name: bool = False):
100
+ self.direct_rules: list[DirectRule] = []
101
+ self.indirect_rules: list[IndirectRule] = []
102
+ self.global_rules: list[GlobalRule] = []
103
+ self.nested: list[MeshRulesRegistry] = []
104
+ self.match_short_name = match_short_name
105
+
106
+ def _normalize_host(self, host: str) -> str:
107
+ if self.match_short_name:
108
+ return host.split(".", maxsplit=1)[0]
109
+ return host
110
+
111
+ def include(self, nested_registry: "MeshRulesRegistry") -> None:
112
+ self.nested.append(nested_registry)
113
+
114
+ def device(self, peer_mask: str, *match: MatchExpr) -> Callable[[GlobalHandler], GlobalHandler]:
115
+ matcher = SingleMatcher(peer_mask, match)
116
+
117
+ def register(handler: GlobalHandler) -> GlobalHandler:
118
+ self.global_rules.append(GlobalRule(matcher, handler))
119
+ return handler
120
+
121
+ return register
122
+
123
+ def direct(
124
+ self, left_mask: str, right_mask: str, *match: MatchExpr,
125
+ ) -> Callable[[DirectHandler], DirectHandler]:
126
+ matcher = PairMatcher(left_mask, right_mask, match)
127
+
128
+ def register(handler: DirectHandler) -> DirectHandler:
129
+ self.direct_rules.append(DirectRule(matcher, handler))
130
+ return handler
131
+
132
+ return register
133
+
134
+ def indirect(
135
+ self, left_mask: str, right_mask: str, *match: MatchExpr,
136
+ ) -> Callable[[IndirectHandler], IndirectHandler]:
137
+ matcher = PairMatcher(left_mask, right_mask, match)
138
+
139
+ def register(handler: IndirectHandler) -> IndirectHandler:
140
+ self.indirect_rules.append(IndirectRule(matcher, handler))
141
+ return handler
142
+
143
+ return register
144
+
145
+ def lookup_direct(self, device: str, neighbors: list[str]) -> list[MatchedDirectPair]:
146
+ found = []
147
+ device = self._normalize_host(device)
148
+ for neighbor in neighbors:
149
+ neighbor = self._normalize_host(neighbor)
150
+ for rule in self.direct_rules:
151
+ if args := rule.matcher.match_pair(device, neighbor):
152
+ found.append(MatchedDirectPair(
153
+ handler=rule.handler,
154
+ direct_order=True,
155
+ name_left=device,
156
+ name_right=neighbor,
157
+ match_left=args[0],
158
+ match_right=args[1],
159
+ ))
160
+ if args := rule.matcher.match_pair(neighbor, device):
161
+ found.append(MatchedDirectPair(
162
+ handler=rule.handler,
163
+ direct_order=False,
164
+ name_left=neighbor,
165
+ name_right=device,
166
+ match_left=args[0],
167
+ match_right=args[1],
168
+ ))
169
+ for registry in self.nested:
170
+ found.extend(registry.lookup_direct(device, neighbors))
171
+ return found
172
+
173
+ def lookup_indirect(self, device: str, devices: list[str]) -> list[MatchedIndirectPair]:
174
+ found = []
175
+ device = self._normalize_host(device)
176
+ for other_device in devices:
177
+ other_device = self._normalize_host(other_device)
178
+ for rule in self.indirect_rules:
179
+ if args := rule.matcher.match_pair(device, other_device):
180
+ found.append(MatchedIndirectPair(
181
+ handler=rule.handler,
182
+ direct_order=True,
183
+ name_left=device,
184
+ name_right=other_device,
185
+ match_left=args[0],
186
+ match_right=args[1],
187
+ ))
188
+ if args := rule.matcher.match_pair(other_device, device):
189
+ found.append(MatchedIndirectPair(
190
+ handler=rule.handler,
191
+ direct_order=False,
192
+ name_left=other_device,
193
+ name_right=device,
194
+ match_left=args[0],
195
+ match_right=args[1],
196
+ ))
197
+ for registry in self.nested:
198
+ found.extend(registry.lookup_indirect(device, devices))
199
+ return found
200
+
201
+ def lookup_global(self, device: str) -> list[MatchedGlobal]:
202
+ found = []
203
+ device = self._normalize_host(device)
204
+ for rule in self.global_rules:
205
+ if args := rule.matcher.match_one(device):
206
+ found.append(MatchedGlobal(
207
+ handler=rule.handler,
208
+ match=args,
209
+ ))
210
+ for registry in self.nested:
211
+ found.extend(registry.lookup_global(device))
212
+ return found
File without changes
@@ -0,0 +1,5 @@
1
+ from annet.annlib.types import Op
2
+
3
+
4
+ def change(key, diff, **kwargs):
5
+ yield from [(True, add["row"], None) for add in diff[Op.ADDED]]
@@ -52,8 +52,6 @@ spanning-tree
52
52
  no system jumbomtu %order_reverse
53
53
  system jumbomtu
54
54
 
55
- route-map
56
-
57
55
  service dhcp
58
56
  ip dhcp relay
59
57
  ipv6 dhcp relay
@@ -74,9 +72,14 @@ interface *
74
72
 
75
73
  interface */\S+\.\d+/
76
74
 
75
+ route-map
76
+
77
77
  # удалять eth-trunk можно только после того, как вычистим member interfaces
78
78
  undo interface */port-channel\d+/ %order_reverse
79
79
 
80
+ # remote as of neighbors should be assigned before peer-group, the rule is applied to neighbors, not peer-groups
80
81
  router bgp
82
+ neighbor */[\da-f\.\:]+/ remote-as
83
+ neighbor */[\da-f\.\:]+/ peer-group
81
84
 
82
85
  line
@@ -42,12 +42,17 @@ no snmp-server sysobjectid type stack-oid
42
42
 
43
43
  !interface */(mgmt|ipmi|Vlan1$)/
44
44
 
45
+ interface Loopback
46
+ ipv6 address *
47
+ ip address ~
48
+
45
49
  # SVI/Subifs/Lagg
46
50
  interface */(Vlan|Ethernet.*\.|port-channel.*\.?)\d+$/ %diff_logic=cisco.iface.diff
47
51
  vrf member
48
52
  ipv6 link-local
49
53
  ipv6 address *
50
54
  ipv6 nd ~ %logic=cisco.misc.no_ipv6_nd_suppress_ra
55
+ ip address ~
51
56
  mtu
52
57
 
53
58
  # Physical
@@ -59,6 +64,7 @@ interface */\w*Ethernet[0-9\/]+$/ %logic=common.permanent %diff_logic=cisco.
59
64
  vrf member
60
65
  ipv6 link-local
61
66
  ipv6 address *
67
+ ip address ~
62
68
  channel-group
63
69
  mtu
64
70
  storm-control * level
annet/storage.py CHANGED
@@ -1,4 +1,5 @@
1
1
  import abc
2
+ from collections.abc import Sequence
2
3
  from typing import Any, Iterable, Optional, Type, Union, Protocol, Dict
3
4
  from annet.connectors import Connector, get_connector_from_config
4
5
  from annet.annlib.netdev.views.hardware import HardwareView
@@ -48,13 +49,21 @@ class Storage(abc.ABC):
48
49
  def resolve_fdnds_by_query(self, query: Any):
49
50
  pass
50
51
 
52
+ @abc.abstractmethod
53
+ def resolve_all_fdnds(self) -> list[str]:
54
+ pass
55
+
56
+ @abc.abstractmethod
57
+ def search_connections(self, device: "Device", neighbor: "Device") -> list[tuple["Interface", "Interface"]]:
58
+ pass
59
+
51
60
  @abc.abstractmethod
52
61
  def make_devices(
53
62
  self,
54
63
  query: Any,
55
64
  preload_neighbors: bool = False,
56
- use_mesh: bool = None,
57
- preload_extra_fields=False,
65
+ use_mesh: Optional[bool] = None,
66
+ preload_extra_fields: bool = False,
58
67
  **kwargs,
59
68
  ):
60
69
  pass
@@ -85,6 +94,17 @@ class Query(abc.ABC):
85
94
  return False
86
95
 
87
96
 
97
+ class Interface(Protocol):
98
+ @property
99
+ @abc.abstractmethod
100
+ def name(self) -> str:
101
+ raise NotImplementedError
102
+
103
+ @abc.abstractmethod
104
+ def add_addr(self, address_mask: str, vrf: Optional[str]) -> None:
105
+ raise NotImplementedError
106
+
107
+
88
108
  class Device(Protocol):
89
109
  @property
90
110
  @abc.abstractmethod
@@ -124,11 +144,30 @@ class Device(Protocol):
124
144
  def neighbours_ids(self):
125
145
  pass
126
146
 
147
+ @property
148
+ @abc.abstractmethod
149
+ def neighbours_fqdns(self):
150
+ pass
151
+
127
152
  @property
128
153
  @abc.abstractmethod
129
154
  def breed(self) -> str:
130
155
  pass
131
156
 
157
+ @abc.abstractmethod
158
+ def make_lag(self, lag: int, ports: Sequence[str], lag_min_links: Optional[int]) -> Interface:
159
+ raise NotImplementedError
160
+
161
+ @abc.abstractmethod
162
+ def add_svi(self, svi: int) -> Interface:
163
+ """Add SVI interface or return existing one"""
164
+ raise NotImplementedError
165
+
166
+ @abc.abstractmethod
167
+ def add_subif(self, interface: str, subif: int) -> Interface:
168
+ """Add sub interface or return existing one"""
169
+ raise NotImplementedError
170
+
132
171
 
133
172
  def get_storage() -> tuple[StorageProvider, Dict[str, Any]]:
134
173
  connectors = storage_connector.get_all()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: annet
3
- Version: 0.16.7
3
+ Version: 0.16.9
4
4
  Summary: annet
5
5
  Home-page: https://github.com/annetutil/annet
6
6
  License: MIT
@@ -23,4 +23,6 @@ Requires-Dist: aiohttp >=3.8.4
23
23
  Requires-Dist: yarl >=1.8.2
24
24
  Requires-Dist: adaptix ==3.0.0b7
25
25
  Requires-Dist: dataclass-rest ==0.4
26
+ Requires-Dist: requests >=2.32.3
27
+ Requires-Dist: annetbox >=0.1.8 ; python_version > "3.9"
26
28
 
@@ -1,6 +1,7 @@
1
1
  annet/__init__.py,sha256=k2dq8aOYjkjZszKoOlxEmR49uYoKh-8_HC2K8FeqLwA,2139
2
2
  annet/annet.py,sha256=TMdEuM7GJQ4TjRVmuK3bCTZN-21lxjQ9sXqEdILUuBk,725
3
3
  annet/argparse.py,sha256=v1MfhjR0B8qahza0WinmXClpR8UiDFhmwDDWtNroJPA,12855
4
+ annet/bgp_models.py,sha256=lV9TW7oPiaiWxD9c5pMIpAnghVIUFK_cTpxNbUUfIaM,8082
4
5
  annet/cli.py,sha256=hDpjIr3w47lgQ_CvCQS1SXFDK-SJrf5slbT__5u6GIA,12342
5
6
  annet/cli_args.py,sha256=KQlihxSl-Phhq1-9oJDdNSbIllEX55LlPfH6viEKOuw,13483
6
7
  annet/connectors.py,sha256=-Lghz3PtWCBU8Ohrp0KKQcmm1AUZtN0EnOaZ6IQgCQI,5105
@@ -10,31 +11,36 @@ annet/executor.py,sha256=Jny-hm0otZA1naPpFWR-R16SbaZioSQ8pkx-Yd2PYlM,19004
10
11
  annet/filtering.py,sha256=ZtqxPsKdV9reZoRxtQyBg22BqyMqd-2SotYcxZ-68AQ,903
11
12
  annet/gen.py,sha256=rOAveprvBaEXbLyaQUhQ0QtOvcDfndlIOpchNhu8M1U,33499
12
13
  annet/hardware.py,sha256=_iR28dWiPtt6ZYdk-qg1sxazkSRJE3ukqKB-fFFfQak,1141
13
- annet/implicit.py,sha256=_3eY9NKqpLUm25vlJIP2cHN4gdTgzO6rG6mwCKJYMnQ,5439
14
+ annet/implicit.py,sha256=pX1FCZobkx-b5Y9otJDcr2eJQ1BUk_pG-ElKIMUSXWE,5553
14
15
  annet/lib.py,sha256=lOdz3UJFYkO0wnuzIRRq3FpULQliqBtfmGmKOGVFO4Q,4238
15
16
  annet/output.py,sha256=BNPzjuhMa7gSJ8ze_1O-Ey0tTxSyhAiwfztZMQwhMzk,7176
16
17
  annet/parallel.py,sha256=hLkzEht0KhzmzUWDdO4QFYQHzhxs3wPlTA8DxbB2ziw,17160
17
18
  annet/patching.py,sha256=nILbY5oJajN0b1j3f0HEJm05H3HVThnWvB7vDVh7UQw,559
18
19
  annet/reference.py,sha256=B8mH8VUMcecPnzULiTVb_kTQ7jQrCL7zp4pfIZQa5fk,4035
19
- annet/storage.py,sha256=s5kiSonsQZnT-ioAyoLtezLe1QbbJwK5-Wr1QfMxupU,2811
20
+ annet/storage.py,sha256=eAHEvPbRuKDUJdnkzSrHmW_lBJS3Y0g93Y2VJ4qzifQ,3941
20
21
  annet/tabparser.py,sha256=N0O7G9DTdmgcBDxz0PH7B_r-Z8FsUkZqm9hTBy3PZFA,969
21
22
  annet/text_term_format.py,sha256=CHb6viv45vmYl-SK1A1vyPHGhaEni6jVybBusaQnct8,2813
22
23
  annet/tracing.py,sha256=ndpM-au1c88uBBpOuH_z52qWZL773edYozNyys_wA68,4044
23
24
  annet/types.py,sha256=f2HwqoKa6AucwFwDMszoouB6m1B8n6VmdjHMktO30Kc,7175
24
25
  annet/adapters/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
+ annet/adapters/fetchers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
27
+ annet/adapters/fetchers/stub/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
+ annet/adapters/fetchers/stub/fetcher.py,sha256=bJGNJcvjrxSa4d8gly6NkaRcxoK57zbZhzkW5vq278I,656
29
+ annet/adapters/file/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
30
+ annet/adapters/file/provider.py,sha256=Wn3sG2TOI6ZWuRHhPSyg8S0Dnrz5LN3VyuqE6S7r5GM,5930
25
31
  annet/adapters/netbox/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
26
32
  annet/adapters/netbox/provider.py,sha256=IIs37QFHuJHxq4A0WfBS4JENk--v3BxqgNPal1Or4Xc,1470
27
33
  annet/adapters/netbox/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
28
34
  annet/adapters/netbox/common/client.py,sha256=-lWZmphD-OPuLIHNKhW_h2bnjrVaiyKYAD_MUPasEbo,2483
29
35
  annet/adapters/netbox/common/manufacturer.py,sha256=WZsBfHq6kohbbkszxPARjMdXB5rWGBO4Gz1rA-IlqL8,1555
30
- annet/adapters/netbox/common/models.py,sha256=zWxsChKZiJ_VQ5_K-l_o-iyDQgxNLvYpk4EvVSoga5o,3316
36
+ annet/adapters/netbox/common/models.py,sha256=h7kP2TQrYj09BOANHoKIw9xFBT2RHm31Qlmal2dM8pc,6864
31
37
  annet/adapters/netbox/common/query.py,sha256=ziUFM7cUEbEIf3k1szTll4aO-OCUa-2Ogxbebi7Tegs,646
32
38
  annet/adapters/netbox/common/status_client.py,sha256=W4nTb2yvBlJ2UkWUmUhKQ2PaSQb1shjhHj5ebb4s2s4,591
33
39
  annet/adapters/netbox/common/storage_opts.py,sha256=iadgWGMb-rfSp3SnFAw8SH5bMKjwvcAsJ74v_z0CCXQ,507
34
40
  annet/adapters/netbox/v24/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
35
41
  annet/adapters/netbox/v24/storage.py,sha256=THI592VLx3ehixsPZQ1Ko3mYIAZQbnDY-toIziqBbL8,6005
36
42
  annet/adapters/netbox/v37/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
37
- annet/adapters/netbox/v37/storage.py,sha256=TonXJuR6ng6xiczHsxsm0Zlo5Wokl3N_Uqg4r7HHj6c,8421
43
+ annet/adapters/netbox/v37/storage.py,sha256=Fq72sIHZRXx-lMS_3mzD-thaNNJ_zogaA-aCyXaEn2U,9716
38
44
  annet/annlib/__init__.py,sha256=fT1l4xV5fqqg8HPw9HqmZVN2qwS8i6X1aIm2zGDjxKY,252
39
45
  annet/annlib/command.py,sha256=uuBddMQphtn8P5MO5kzIa8_QrtMns-k05VeKv1bcAuA,1043
40
46
  annet/annlib/diff.py,sha256=MZ6eQAU3cadQp8KaSE6uAYFtcfMDCIe_eNuVROnYkCk,4496
@@ -52,7 +58,7 @@ annet/annlib/netdev/devdb/__init__.py,sha256=aKYjjLbJebdKBjnGDpVLQdSqrV2JL24spGm
52
58
  annet/annlib/netdev/devdb/data/devdb.json,sha256=Qph7WxZBEbgBqbCFeYu6ZM0qkEBn80WmJEjfJkcaZ-0,5940
53
59
  annet/annlib/netdev/views/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
54
60
  annet/annlib/netdev/views/dump.py,sha256=rIlyvnA3uM8bB_7oq1nS2KDxTp6dQh2hz-FbNhYIpOU,4630
55
- annet/annlib/netdev/views/hardware.py,sha256=1JdTkrumOTYd5GKz4_LKg8G-B6ccrzl5VdNT-JhX40A,3495
61
+ annet/annlib/netdev/views/hardware.py,sha256=3JCZLH7deIHhCguwPJTUX-WDvWjG_xt6BdSEZSO6zkQ,4226
56
62
  annet/annlib/rbparser/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
57
63
  annet/annlib/rbparser/acl.py,sha256=RR8yPt6t96_IiyuKVbeZ-3x32cyhBAT2wC1y99oWBO8,3931
58
64
  annet/annlib/rbparser/deploying.py,sha256=ACT8QNhDAhJx3ZKuGh2nYBOrpdka2qEKuLDxvQAGKLk,1649
@@ -62,9 +68,9 @@ annet/annlib/rbparser/syntax.py,sha256=iZ7Y-4QQBw4L3UtjEh54qisiRDhobl7HZxFNdP8mi
62
68
  annet/annlib/rulebook/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
63
69
  annet/annlib/rulebook/common.py,sha256=Kd9Xout0xC6ZZDnyaORx0W-1kSM-gTgjQbp1iIXWxic,16489
64
70
  annet/api/__init__.py,sha256=7EB3d89kGXKf4Huw7cqyOULTGC9ydL4sHiVw8K0Aeqg,33722
65
- annet/configs/context.yml,sha256=rXbeCmeYGaCEVVncwdouZIx5O7-PzABe4q-tfke0sSA,389
66
- annet/configs/logging.yaml,sha256=Hu42lRK248dssp9TgkbHCaZNl0E6f4IChGb0XaQnTVo,970
67
- annet/generators/__init__.py,sha256=rQAA_ghWRY2PcPYU6HArtt6sPEJXuBEEAvyUT9uDDms,15913
71
+ annet/configs/context.yml,sha256=nZ2Rr4VIn3kvzBNVOhIPJb3tBmd6Ikmkw5ODlQakPUo,389
72
+ annet/configs/logging.yaml,sha256=EUagfir99QqA73Scc3k7sfQccbU3E1SvEQdyhLFtCl4,997
73
+ annet/generators/__init__.py,sha256=rVHHDTPKHPZsml1eNEAj3o-8RweFTN8J7LX3tKMXdIY,16402
68
74
  annet/generators/base.py,sha256=rgQLcQBPZm4ecbKmRhVOpBR-GFJAiVfdb_y5f2-LUR8,3670
69
75
  annet/generators/entire.py,sha256=7WySkVaXNT3ZAiHcQ0JUKdlhGJAN8cNUxF6c7ilYnO8,2928
70
76
  annet/generators/exceptions.py,sha256=GPXTBgn2xZ3Ev_bdOPlfCLGRC1kQHe_dEq88S-uyi5s,151
@@ -75,6 +81,14 @@ annet/generators/ref.py,sha256=QVdeL8po1D0kBsVLOpCjFR81D8yNTk-kaQj5WUM4hng,438
75
81
  annet/generators/result.py,sha256=zMAvGOYQU803bGy6datZduHLgrEqK2Zba_Jcf9Qn9p0,4976
76
82
  annet/generators/common/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
77
83
  annet/generators/common/initial.py,sha256=qYBxXFhyOPy34cxc6hsIXseod-lYCmmbuNHpM0uteY0,1244
84
+ annet/mesh/__init__.py,sha256=_Ho7ZwPuEZ7wsOu_oG0avvPzQVn8g-A0w2fqZ42Gf30,369
85
+ annet/mesh/basemodel.py,sha256=bBBx1wu3ftENgf_4PGCV-SkEcxH3tFekvoointT3894,4739
86
+ annet/mesh/device_models.py,sha256=m3S2IUW7dH0drAop3imwuTk27X93c8lLC2ot8S6rA5Y,2068
87
+ annet/mesh/executor.py,sha256=KoFrDd-6XsN2IO-AnLKYiKYebMmN6KpbUVq8AWXUYVE,10926
88
+ annet/mesh/match_args.py,sha256=CR3kdIV9NGtyk9E2JbcOQ3TRuYEryTWP3m2yCo2VCWg,5751
89
+ annet/mesh/models_converter.py,sha256=EdAQIkE-AfdCqMuzVQEdsG5lQdsaAwmqNqq9b8GRnGQ,2888
90
+ annet/mesh/peer_models.py,sha256=sHny5nvLTWY2gqrq-SzZJ-lzEa90E_RCuBoiLb-Rub8,2129
91
+ annet/mesh/registry.py,sha256=N2QyfyH0Qt73l16CO8VRKIBKHscBntEfS-j9B4xs-ys,6906
78
92
  annet/rulebook/__init__.py,sha256=14IpOfTbeJtre7JKrfXVYiH0qAXsUSOL7AatUFmSQs0,3847
79
93
  annet/rulebook/common.py,sha256=zK1s2c5lc5HQbIlMUQ4HARQudXSgOYiZ_Sxc2I_tHqg,721
80
94
  annet/rulebook/deploying.py,sha256=XV0XQvc3YvwM8SOgOQlc-fCW4bnjQg_1CTZkTwMp14A,2972
@@ -100,6 +114,8 @@ annet/rulebook/juniper/__init__.py,sha256=WByFrqKCdr-ORCme2AURQGnYbN66t3omB3-9dW
100
114
  annet/rulebook/nexus/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
101
115
  annet/rulebook/nexus/iface.py,sha256=aeog9iSGT2zZ78tsGlrRcfgfOv7yW3jLwryXqdeplRw,2923
102
116
  annet/rulebook/ribbon/__init__.py,sha256=TRbkQVvk0-HxkUQW9-LmiG6XIfTZ-8t3SiaDemNCzK4,347
117
+ annet/rulebook/routeros/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
118
+ annet/rulebook/routeros/file.py,sha256=zK7RwBk1YaVoDSFSg1u7Pt8u0Fk3nhhu27aJRngemwc,137
103
119
  annet/rulebook/texts/arista.deploy,sha256=OS9eFyJpEPztcOHkBwajw_RTJfTT7ivaMHfx4_HXaUg,792
104
120
  annet/rulebook/texts/arista.order,sha256=TKy3S56tIypwfVaw0akK1sXGatCpLVwpB4Jvq-dIu90,1457
105
121
  annet/rulebook/texts/arista.rul,sha256=HUYiN55s8Y6Wrd5q1Awe7-o5BYBh7gIxthUC5NvrfJI,786
@@ -110,8 +126,8 @@ annet/rulebook/texts/b4com.deploy,sha256=SVX8-yLHM90tJC4M-ekpGuGM1aQZW3euSGyg67l
110
126
  annet/rulebook/texts/b4com.order,sha256=G3aToAIHHzKzDCM3q7_lyr9wJvuVOXVbVvF3wm5PiTE,707
111
127
  annet/rulebook/texts/b4com.rul,sha256=5mqyUg_oLRSny2iH6QdhfDWVu6kzgDURtlSATD7DFno,1056
112
128
  annet/rulebook/texts/cisco.deploy,sha256=XvXWeOMahE8Uc9RF0xkJj8jGknD4vit8H_f24ubPX7w,1226
113
- annet/rulebook/texts/cisco.order,sha256=eE9ddPQr8ZumjffQsMvl-BBymOwV6juETZU3r7kpRvk,1709
114
- annet/rulebook/texts/cisco.rul,sha256=HGg62zXCn8UVXu9x_Ja5QivPcY5Yo5BYi1CaOXCaDHA,2869
129
+ annet/rulebook/texts/cisco.order,sha256=OvNHMNqkCc-DN2dEjLCTKv_7ZhiaHt4q2X4Y4Z8dvR4,1901
130
+ annet/rulebook/texts/cisco.rul,sha256=7st2vuEMuq18rt0aDbZav24F8Sqj4h8IRoHOlNr7kuM,2959
115
131
  annet/rulebook/texts/huawei.deploy,sha256=azEC6_jQRzwnTSrNgag0hHh6L7hezS_eMk6ZDZfWyXI,10444
116
132
  annet/rulebook/texts/huawei.order,sha256=ENllPX4kO6xNw2mUQcx11yhxo3tKStZ5mUyc0C6s3d0,10657
117
133
  annet/rulebook/texts/huawei.rul,sha256=02Fi1RG4YYea2clHCluBuJDKNbT0hS9jtsk6_h6GK8k,12958
@@ -131,12 +147,15 @@ annet/rulebook/texts/ribbon.rul,sha256=609LyLTDCtXPVQNAzqS-VEyCpW3byHP8TCMJLFMn5
131
147
  annet/rulebook/texts/routeros.order,sha256=M71uy_hf0KAjLNS3zZY3uih4m2xLUcu26FEoVVjC6k0,905
132
148
  annet/rulebook/texts/routeros.rul,sha256=ipfxjj0mjFef6IsUlupqx4BY_Je_OUb8u_U1019O1DE,1203
133
149
  annet_generators/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
134
- annet_generators/example/__init__.py,sha256=zVd8_DrXuOASrNzg2Ab94rPyvJff83L-_HppDFxnUjM,228
150
+ annet_generators/example/__init__.py,sha256=1z030I00c9KeqW0ntkT1IRLYKD5LZAHYjiNHrOLen1Q,221
135
151
  annet_generators/example/lldp.py,sha256=24bGvShxbio-JxUdaehyPRu31LhH9YwSwFDrWVRn6yo,2100
136
- annet-0.16.7.dist-info/AUTHORS,sha256=rh3w5P6gEgqmuC-bw-HB68vBCr-yIBFhVL0PG4hguLs,878
137
- annet-0.16.7.dist-info/LICENSE,sha256=yPxl7dno02Pw7gAcFPIFONzx_gapwDoPXsIsh6Y7lC0,1079
138
- annet-0.16.7.dist-info/METADATA,sha256=eN7Rx0Uey7FJ-BxUBXbWEcsw7Sdt6CfYaejGBjNdkhY,694
139
- annet-0.16.7.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
140
- annet-0.16.7.dist-info/entry_points.txt,sha256=5lIaDGlGi3l6QQ2ry2jZaqViP5Lvt8AmsegdD0Uznck,192
141
- annet-0.16.7.dist-info/top_level.txt,sha256=QsoTZBsUtwp_FEcmRwuN8QITBmLOZFqjssRfKilGbP8,23
142
- annet-0.16.7.dist-info/RECORD,,
152
+ annet_generators/mesh_example/__init__.py,sha256=NfNWgXn1TNiWI6A5tmU6Y-4QV2i33td0Qs3re0MNNMo,218
153
+ annet_generators/mesh_example/bgp.py,sha256=ck--yU_lUdAX9DWaaVQ-C29eQN-EGf1gEpOTBxmMnWA,1317
154
+ annet_generators/mesh_example/mesh_logic.py,sha256=5Wt17LPt-EWe126IFAdaQQGWIOR3mxTJjAMUY8K0c0w,971
155
+ annet-0.16.9.dist-info/AUTHORS,sha256=rh3w5P6gEgqmuC-bw-HB68vBCr-yIBFhVL0PG4hguLs,878
156
+ annet-0.16.9.dist-info/LICENSE,sha256=yPxl7dno02Pw7gAcFPIFONzx_gapwDoPXsIsh6Y7lC0,1079
157
+ annet-0.16.9.dist-info/METADATA,sha256=XJktwf9SQc7QbBVmhoWXRelloT7i_fBf3EIdAMQc5J0,784
158
+ annet-0.16.9.dist-info/WHEEL,sha256=P9jw-gEje8ByB7_hXoICnHtVCrEwMQh-630tKvQWehc,91
159
+ annet-0.16.9.dist-info/entry_points.txt,sha256=5lIaDGlGi3l6QQ2ry2jZaqViP5Lvt8AmsegdD0Uznck,192
160
+ annet-0.16.9.dist-info/top_level.txt,sha256=QsoTZBsUtwp_FEcmRwuN8QITBmLOZFqjssRfKilGbP8,23
161
+ annet-0.16.9.dist-info/RECORD,,
@@ -7,6 +7,4 @@ from . import lldp
7
7
 
8
8
 
9
9
  def get_generators(store: Storage) -> List[BaseGenerator]:
10
- return [
11
- lldp.Lldp(store),
12
- ]
10
+ return lldp.get_generators(store)
@@ -0,0 +1,9 @@
1
+ from typing import List
2
+
3
+ from annet.generators import BaseGenerator
4
+ from annet.storage import Storage
5
+ from . import bgp
6
+
7
+
8
+ def get_generators(store: Storage) -> List[BaseGenerator]:
9
+ return bgp.get_generators(store)
@@ -0,0 +1,43 @@
1
+ from typing import List
2
+
3
+ from annet.adapters.netbox.common.models import NetboxDevice
4
+ from annet.generators import PartialGenerator, BaseGenerator
5
+ from annet.mesh import MeshExecutor
6
+ from annet.storage import Storage
7
+ from .mesh_logic import registry
8
+
9
+
10
+ class Bgp(PartialGenerator):
11
+ TAGS = ["mgmt", "bgp"]
12
+
13
+ def acl_huawei(self, device):
14
+ return """
15
+ bgp
16
+ peer
17
+ """
18
+
19
+ def run_huawei(self, device: NetboxDevice):
20
+ executor = MeshExecutor(registry, device.storage)
21
+ res = executor.execute_for(device)
22
+ yield f"bgp {res.global_options.local_as}"
23
+ for peer in res.peers:
24
+ if peer.group_name:
25
+ yield f" peer {peer.addr} {peer.group_name}"
26
+ if peer.remote_as is not None:
27
+ yield f" peer {peer.addr} remote-as {peer.remote_as}"
28
+
29
+ for group in res.global_options.groups:
30
+ yield f" peer {group.name} remote-as {group.remote_as}"
31
+ for interface in device.interfaces:
32
+ print(
33
+ interface.name,
34
+ interface.lag_min_links,
35
+ interface.lag.name if interface.lag else None,
36
+ interface.ip_addresses,
37
+ )
38
+
39
+
40
+ def get_generators(store: Storage) -> List[BaseGenerator]:
41
+ return [
42
+ Bgp(store),
43
+ ]
@@ -0,0 +1,28 @@
1
+ from annet.mesh import Right, MeshRulesRegistry, GlobalOptions, MeshSession, DirectPeer
2
+
3
+ registry = MeshRulesRegistry()
4
+
5
+
6
+ @registry.device("{name:.*}")
7
+ def device_handler(global_opts: GlobalOptions):
8
+ global_opts.local_as = 12345
9
+ global_opts.groups["GROP_NAME"].remote_as = 11111
10
+
11
+
12
+ @registry.direct("{name:.*}", "m9-sgw{x}.{domain:.*}")
13
+ def direct_handler(device: DirectPeer, neighbor: DirectPeer, session: MeshSession):
14
+ session.asnum = 12345
15
+ device.addr = "192.168.1.254"
16
+ neighbor.addr = f"192.168.1.{neighbor.match.x}"
17
+
18
+
19
+ @registry.direct("{name:.*}", "m9-sgw{x}.{domain:.*}", Right.x.in_([0, 1]))
20
+ def direct_handler2(device: DirectPeer, neighbor: DirectPeer, session: MeshSession):
21
+ session.asnum = 12345
22
+ device.addr = "192.168.1.254/24"
23
+ device.lag = 1
24
+ device.lag_links_min = neighbor.match.x
25
+ device.subif = 100
26
+ neighbor.families = {"ipv4_unicast"}
27
+ neighbor.group_name = "GROUP_NAME"
28
+ neighbor.addr = "192.168.1.200/24"
File without changes