annet 0.0__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/__init__.py +61 -0
- annet/adapters/__init__.py +0 -0
- annet/adapters/netbox/__init__.py +0 -0
- annet/adapters/netbox/common/__init__.py +0 -0
- annet/adapters/netbox/common/client.py +87 -0
- annet/adapters/netbox/common/manufacturer.py +62 -0
- annet/adapters/netbox/common/models.py +105 -0
- annet/adapters/netbox/common/query.py +23 -0
- annet/adapters/netbox/common/status_client.py +25 -0
- annet/adapters/netbox/common/storage_opts.py +14 -0
- annet/adapters/netbox/provider.py +34 -0
- annet/adapters/netbox/v24/__init__.py +0 -0
- annet/adapters/netbox/v24/api_models.py +73 -0
- annet/adapters/netbox/v24/client.py +59 -0
- annet/adapters/netbox/v24/storage.py +196 -0
- annet/adapters/netbox/v37/__init__.py +0 -0
- annet/adapters/netbox/v37/api_models.py +38 -0
- annet/adapters/netbox/v37/client.py +62 -0
- annet/adapters/netbox/v37/storage.py +149 -0
- annet/annet.py +25 -0
- annet/annlib/__init__.py +7 -0
- annet/annlib/command.py +49 -0
- annet/annlib/diff.py +158 -0
- annet/annlib/errors.py +8 -0
- annet/annlib/filter_acl.py +196 -0
- annet/annlib/jsontools.py +116 -0
- annet/annlib/lib.py +495 -0
- annet/annlib/netdev/__init__.py +0 -0
- annet/annlib/netdev/db.py +62 -0
- annet/annlib/netdev/devdb/__init__.py +28 -0
- annet/annlib/netdev/devdb/data/devdb.json +137 -0
- annet/annlib/netdev/views/__init__.py +0 -0
- annet/annlib/netdev/views/dump.py +121 -0
- annet/annlib/netdev/views/hardware.py +112 -0
- annet/annlib/output.py +246 -0
- annet/annlib/patching.py +533 -0
- annet/annlib/rbparser/__init__.py +0 -0
- annet/annlib/rbparser/acl.py +120 -0
- annet/annlib/rbparser/deploying.py +55 -0
- annet/annlib/rbparser/ordering.py +52 -0
- annet/annlib/rbparser/platform.py +51 -0
- annet/annlib/rbparser/syntax.py +115 -0
- annet/annlib/rulebook/__init__.py +0 -0
- annet/annlib/rulebook/common.py +350 -0
- annet/annlib/tabparser.py +648 -0
- annet/annlib/types.py +35 -0
- annet/api/__init__.py +826 -0
- annet/argparse.py +415 -0
- annet/cli.py +237 -0
- annet/cli_args.py +503 -0
- annet/configs/context.yml +18 -0
- annet/configs/logging.yaml +39 -0
- annet/connectors.py +77 -0
- annet/deploy.py +536 -0
- annet/diff.py +84 -0
- annet/executor.py +551 -0
- annet/filtering.py +40 -0
- annet/gen.py +865 -0
- annet/generators/__init__.py +435 -0
- annet/generators/base.py +136 -0
- annet/generators/common/__init__.py +0 -0
- annet/generators/common/initial.py +33 -0
- annet/generators/entire.py +97 -0
- annet/generators/exceptions.py +10 -0
- annet/generators/jsonfragment.py +125 -0
- annet/generators/partial.py +119 -0
- annet/generators/perf.py +79 -0
- annet/generators/ref.py +15 -0
- annet/generators/result.py +127 -0
- annet/hardware.py +45 -0
- annet/implicit.py +139 -0
- annet/lib.py +128 -0
- annet/output.py +167 -0
- annet/parallel.py +448 -0
- annet/patching.py +25 -0
- annet/reference.py +148 -0
- annet/rulebook/__init__.py +114 -0
- annet/rulebook/arista/__init__.py +0 -0
- annet/rulebook/arista/iface.py +16 -0
- annet/rulebook/aruba/__init__.py +16 -0
- annet/rulebook/aruba/ap_env.py +146 -0
- annet/rulebook/aruba/misc.py +8 -0
- annet/rulebook/cisco/__init__.py +0 -0
- annet/rulebook/cisco/iface.py +68 -0
- annet/rulebook/cisco/misc.py +57 -0
- annet/rulebook/cisco/vlandb.py +90 -0
- annet/rulebook/common.py +19 -0
- annet/rulebook/deploying.py +87 -0
- annet/rulebook/huawei/__init__.py +0 -0
- annet/rulebook/huawei/aaa.py +75 -0
- annet/rulebook/huawei/bgp.py +97 -0
- annet/rulebook/huawei/iface.py +33 -0
- annet/rulebook/huawei/misc.py +337 -0
- annet/rulebook/huawei/vlandb.py +115 -0
- annet/rulebook/juniper/__init__.py +107 -0
- annet/rulebook/nexus/__init__.py +0 -0
- annet/rulebook/nexus/iface.py +92 -0
- annet/rulebook/patching.py +143 -0
- annet/rulebook/ribbon/__init__.py +12 -0
- annet/rulebook/texts/arista.deploy +20 -0
- annet/rulebook/texts/arista.order +125 -0
- annet/rulebook/texts/arista.rul +59 -0
- annet/rulebook/texts/aruba.deploy +20 -0
- annet/rulebook/texts/aruba.order +83 -0
- annet/rulebook/texts/aruba.rul +87 -0
- annet/rulebook/texts/cisco.deploy +27 -0
- annet/rulebook/texts/cisco.order +82 -0
- annet/rulebook/texts/cisco.rul +105 -0
- annet/rulebook/texts/huawei.deploy +188 -0
- annet/rulebook/texts/huawei.order +388 -0
- annet/rulebook/texts/huawei.rul +471 -0
- annet/rulebook/texts/juniper.rul +120 -0
- annet/rulebook/texts/nexus.deploy +24 -0
- annet/rulebook/texts/nexus.order +85 -0
- annet/rulebook/texts/nexus.rul +83 -0
- annet/rulebook/texts/nokia.rul +31 -0
- annet/rulebook/texts/pc.order +5 -0
- annet/rulebook/texts/pc.rul +9 -0
- annet/rulebook/texts/ribbon.deploy +22 -0
- annet/rulebook/texts/ribbon.rul +77 -0
- annet/rulebook/texts/routeros.order +38 -0
- annet/rulebook/texts/routeros.rul +45 -0
- annet/storage.py +125 -0
- annet/tabparser.py +36 -0
- annet/text_term_format.py +95 -0
- annet/tracing.py +170 -0
- annet/types.py +227 -0
- annet-0.0.dist-info/AUTHORS +21 -0
- annet-0.0.dist-info/LICENSE +21 -0
- annet-0.0.dist-info/METADATA +26 -0
- annet-0.0.dist-info/RECORD +137 -0
- annet-0.0.dist-info/WHEEL +5 -0
- annet-0.0.dist-info/entry_points.txt +5 -0
- annet-0.0.dist-info/top_level.txt +2 -0
- annet_generators/__init__.py +0 -0
- annet_generators/example/__init__.py +12 -0
- annet_generators/example/lldp.py +53 -0
|
@@ -0,0 +1,107 @@
|
|
|
1
|
+
import re
|
|
2
|
+
from collections import OrderedDict as odict
|
|
3
|
+
from functools import wraps
|
|
4
|
+
|
|
5
|
+
from annet.annlib.lib import jun_activate, jun_is_inactive, merge_dicts
|
|
6
|
+
from annet.annlib.types import Op
|
|
7
|
+
|
|
8
|
+
from annet.rulebook import common
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
def _inactive_blocks(diff_foo):
|
|
12
|
+
@wraps(diff_foo)
|
|
13
|
+
def wrapper(old, new, diff_pre, *args, **kwargs):
|
|
14
|
+
old_inactives = list(map(jun_activate, filter(jun_is_inactive, old)))
|
|
15
|
+
new_inactives = list(map(jun_activate, filter(jun_is_inactive, new)))
|
|
16
|
+
if len(old_inactives) == 0 and len(new_inactives) == 0:
|
|
17
|
+
return diff_foo(old, new, diff_pre, *args, **kwargs)
|
|
18
|
+
|
|
19
|
+
inactive_pre = odict([(jun_activate(k), v) for k, v in diff_pre.items() if jun_is_inactive(k)])
|
|
20
|
+
merged_pre = merge_dicts(diff_pre, inactive_pre)
|
|
21
|
+
diff = diff_foo(_strip_toplevel_inactives(old),
|
|
22
|
+
_strip_toplevel_inactives(new),
|
|
23
|
+
merged_pre,
|
|
24
|
+
*args, **kwargs)
|
|
25
|
+
|
|
26
|
+
for activated in [k for k in old_inactives if k in new]:
|
|
27
|
+
diff += [(Op.ADDED, _activate_cmd(activated, merged_pre), {}, diff_pre[activated]["match"])]
|
|
28
|
+
|
|
29
|
+
for deactivated in [k for k in new_inactives if k not in old_inactives]:
|
|
30
|
+
# если деактивуруемого блока не существует - ставим один deactivate, глубже не идем
|
|
31
|
+
if deactivated not in diff_pre:
|
|
32
|
+
diff = [(Op.ADDED, _deactivate_cmd(deactivated, merged_pre), {}, inactive_pre[deactivated]["match"])]
|
|
33
|
+
else:
|
|
34
|
+
diff += [(Op.ADDED, _deactivate_cmd(deactivated, merged_pre), {}, diff_pre[deactivated]["match"])]
|
|
35
|
+
return diff
|
|
36
|
+
return wrapper
|
|
37
|
+
|
|
38
|
+
|
|
39
|
+
@_inactive_blocks
|
|
40
|
+
def default_diff(old, new, diff_pre, _pops=(Op.AFFECTED,)):
|
|
41
|
+
diff = common.default_diff(old, new, diff_pre, _pops)
|
|
42
|
+
diff = _ignore_quotes(diff)
|
|
43
|
+
diff = _strip_inactive_removed(diff)
|
|
44
|
+
return diff
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
@_inactive_blocks
|
|
48
|
+
def ordered_diff(old, new, diff_pre, _pops=(Op.AFFECTED,)):
|
|
49
|
+
diff = common.ordered_diff(old, new, diff_pre, _pops)
|
|
50
|
+
diff = _ignore_quotes(diff)
|
|
51
|
+
diff = _strip_inactive_removed(diff)
|
|
52
|
+
return diff
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
# =====
|
|
56
|
+
def _strip_toplevel_inactives(tree):
|
|
57
|
+
for inactive in filter(jun_is_inactive, tree):
|
|
58
|
+
assert jun_activate(inactive) not in tree
|
|
59
|
+
return odict([(k, v) if not jun_is_inactive(k) else (jun_activate(k), v) for k, v in tree.items()])
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def _activate_cmd(active_key, diff_pre):
|
|
63
|
+
return _cmd(active_key, diff_pre, "activate")
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
def _deactivate_cmd(active_key, diff_pre):
|
|
67
|
+
return _cmd(active_key, diff_pre, "deactivate")
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
def _cmd(active_key, diff_pre, cmd):
|
|
71
|
+
assert not jun_is_inactive(active_key)
|
|
72
|
+
if not diff_pre[active_key]["subtree"]:
|
|
73
|
+
# Если конанда не имеет подблоков И имеет агрументы то надо их отбросить
|
|
74
|
+
return " ".join([cmd, active_key.split()[0]])
|
|
75
|
+
return " ".join([cmd, active_key])
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
def _ignore_quotes(diff):
|
|
79
|
+
"""
|
|
80
|
+
Фильтрует из diff строки которые различаются
|
|
81
|
+
только наличием/отсутсвием кавычек
|
|
82
|
+
i.e.
|
|
83
|
+
description "loopbacks";
|
|
84
|
+
description loopbacks;
|
|
85
|
+
эквивалентны
|
|
86
|
+
"""
|
|
87
|
+
equivs = {}
|
|
88
|
+
for elem in diff:
|
|
89
|
+
key = _strip_quotes(elem[1])
|
|
90
|
+
if key not in equivs:
|
|
91
|
+
equivs[key] = 0
|
|
92
|
+
equivs[key] += 1
|
|
93
|
+
filtered_diff = [elem for elem in diff if equivs[_strip_quotes(elem[1])] == 1]
|
|
94
|
+
return filtered_diff
|
|
95
|
+
|
|
96
|
+
|
|
97
|
+
def _strip_quotes(key):
|
|
98
|
+
return re.sub(r"\"(?P<quoted_text>[^\"]+)\"$", r"\g<quoted_text>", key)
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def _strip_inactive_removed(diff):
|
|
102
|
+
for elem in diff:
|
|
103
|
+
if elem[0] == Op.REMOVED and elem[3]["key"]:
|
|
104
|
+
key = elem[3]["key"][0]
|
|
105
|
+
if jun_is_inactive(key):
|
|
106
|
+
elem[3]["key"] = tuple([jun_activate(key)])
|
|
107
|
+
return diff
|
|
File without changes
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
from annet.annlib.lib import uniq
|
|
2
|
+
from annet.annlib.rulebook import common
|
|
3
|
+
from annet.annlib.types import Op
|
|
4
|
+
|
|
5
|
+
from annet.rulebook.cisco.iface import is_in_channel, is_ip_cmd, is_vpn_cmd
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
def diff(old, new, diff_pre, _pops=(Op.AFFECTED,)):
|
|
9
|
+
for iface_row in old:
|
|
10
|
+
_filter_channel_members(old[iface_row])
|
|
11
|
+
for iface_row in new:
|
|
12
|
+
_filter_channel_members(new[iface_row])
|
|
13
|
+
|
|
14
|
+
for iface_row in uniq(old, new):
|
|
15
|
+
iface_old = old.get(iface_row, {})
|
|
16
|
+
iface_new = new.get(iface_row, {})
|
|
17
|
+
iface_pre = diff_pre[iface_row]["subtree"]
|
|
18
|
+
vpn_changed = False
|
|
19
|
+
for (op, cmd, _, _) in common.default_diff(iface_old, iface_new, iface_pre, _pops):
|
|
20
|
+
if op in {Op.ADDED, Op.REMOVED}:
|
|
21
|
+
vpn_changed |= is_vpn_cmd(cmd)
|
|
22
|
+
break
|
|
23
|
+
|
|
24
|
+
if vpn_changed:
|
|
25
|
+
for cmd in list(iface_old.keys()):
|
|
26
|
+
if is_ip_cmd(cmd) and not is_vpn_cmd(cmd):
|
|
27
|
+
del iface_old[cmd]
|
|
28
|
+
|
|
29
|
+
if _is_diff_removed_lag_from_lag_member(iface_old, iface_new):
|
|
30
|
+
for cmd in list(iface_old.keys()):
|
|
31
|
+
if _is_allowed_on_old_lag_memeber(cmd):
|
|
32
|
+
del iface_old[cmd]
|
|
33
|
+
|
|
34
|
+
ret = common.default_diff(old, new, diff_pre, _pops)
|
|
35
|
+
|
|
36
|
+
return ret
|
|
37
|
+
|
|
38
|
+
# ===
|
|
39
|
+
|
|
40
|
+
# Вырезает все команды не разрешенные
|
|
41
|
+
# на членах агрегата. В running-config
|
|
42
|
+
# листинге они наследуются от самого port-channel
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
def _filter_channel_members(tree):
|
|
46
|
+
if any(is_in_channel(x) for x in tree):
|
|
47
|
+
for cmd in list(tree.keys()):
|
|
48
|
+
if not _is_allowed_on_channel(cmd):
|
|
49
|
+
del tree[cmd]
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
def _is_allowed_on_channel(cmd_line):
|
|
53
|
+
return cmd_line.startswith((
|
|
54
|
+
"channel-group",
|
|
55
|
+
"cdp",
|
|
56
|
+
"description",
|
|
57
|
+
"inherit",
|
|
58
|
+
"ip port",
|
|
59
|
+
"ipv6 port",
|
|
60
|
+
"mac port",
|
|
61
|
+
"lacp",
|
|
62
|
+
"switchport host",
|
|
63
|
+
"switchport",
|
|
64
|
+
"shutdown",
|
|
65
|
+
"rate-limit cpu",
|
|
66
|
+
"snmp trap link-status",
|
|
67
|
+
"mtu",
|
|
68
|
+
"macsec", # NOCDEV-9008
|
|
69
|
+
))
|
|
70
|
+
|
|
71
|
+
# ===
|
|
72
|
+
|
|
73
|
+
# При удалении lag, часть команд удаляется сначала с lag, тем самым удаляя с lag member,
|
|
74
|
+
# но рассчитанный diff этот нюанс не учитывает
|
|
75
|
+
|
|
76
|
+
|
|
77
|
+
def _is_diff_removed_lag_from_lag_member(old, new):
|
|
78
|
+
"""
|
|
79
|
+
Проверяем, что в old есть признак lag member, а в new его нет. Следовательно порт выводится из lag.
|
|
80
|
+
"""
|
|
81
|
+
if any(is_in_channel(x) for x in old) and not any(is_in_channel(x) for x in new):
|
|
82
|
+
return True
|
|
83
|
+
return False
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
def _is_allowed_on_old_lag_memeber(cmd_line):
|
|
87
|
+
"""
|
|
88
|
+
Эти команды принудительно добавим на интерфейс после удаления его из lag
|
|
89
|
+
"""
|
|
90
|
+
return cmd_line.startswith((
|
|
91
|
+
"mtu",
|
|
92
|
+
))
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
import functools
|
|
2
|
+
import re
|
|
3
|
+
from collections import OrderedDict as odict
|
|
4
|
+
|
|
5
|
+
from annet.annlib.rbparser import platform, syntax
|
|
6
|
+
from valkit.common import valid_bool, valid_string_list
|
|
7
|
+
from valkit.python import valid_object_path
|
|
8
|
+
|
|
9
|
+
from .common import import_rulebook_function
|
|
10
|
+
|
|
11
|
+
|
|
12
|
+
DEFAULT_PATCH_LOGIC = "common.default"
|
|
13
|
+
ORDERED_PATCH_LOGIC = "common.ordered"
|
|
14
|
+
REWRITE_PATCH_LOGIC = "common.rewrite"
|
|
15
|
+
REWRITE_DIFF_LOGIC = "common.rewrite_diff"
|
|
16
|
+
MULTILINE_DIFF_LOGIC = "common.multiline_diff"
|
|
17
|
+
|
|
18
|
+
|
|
19
|
+
# =====
|
|
20
|
+
@functools.lru_cache()
|
|
21
|
+
def compile_patching_text(text, vendor):
|
|
22
|
+
return _compile_patching(
|
|
23
|
+
tree=syntax.parse_text(text, params_scheme={
|
|
24
|
+
"global": {
|
|
25
|
+
"validator": valid_bool,
|
|
26
|
+
"default": False,
|
|
27
|
+
},
|
|
28
|
+
"logic": {
|
|
29
|
+
"validator": valid_object_path,
|
|
30
|
+
"default": DEFAULT_PATCH_LOGIC,
|
|
31
|
+
},
|
|
32
|
+
"diff_logic": {
|
|
33
|
+
"validator": valid_object_path,
|
|
34
|
+
"default": platform.VENDOR_DIFF[vendor],
|
|
35
|
+
},
|
|
36
|
+
"comment": {
|
|
37
|
+
"validator": valid_string_list,
|
|
38
|
+
"default": [],
|
|
39
|
+
},
|
|
40
|
+
"multiline": {
|
|
41
|
+
"validator": valid_bool,
|
|
42
|
+
"default": False,
|
|
43
|
+
},
|
|
44
|
+
"ordered": {
|
|
45
|
+
"validator": valid_bool,
|
|
46
|
+
"default": False,
|
|
47
|
+
},
|
|
48
|
+
"rewrite": {
|
|
49
|
+
"validator": valid_bool,
|
|
50
|
+
"default": False,
|
|
51
|
+
},
|
|
52
|
+
"parent": {
|
|
53
|
+
"validator": valid_bool,
|
|
54
|
+
"default": False,
|
|
55
|
+
},
|
|
56
|
+
"force_commit": {
|
|
57
|
+
"validator": valid_bool,
|
|
58
|
+
"default": False,
|
|
59
|
+
},
|
|
60
|
+
"ignore_case": {
|
|
61
|
+
"validator": valid_bool,
|
|
62
|
+
"default": False,
|
|
63
|
+
},
|
|
64
|
+
}),
|
|
65
|
+
reverse_prefix=platform.VENDOR_REVERSES[vendor],
|
|
66
|
+
vendor=vendor,
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# =====
|
|
71
|
+
def _compile_patching(tree, reverse_prefix, vendor):
|
|
72
|
+
rules = {"local": odict(), "global": odict()}
|
|
73
|
+
for (raw_rule, attrs) in tree.items():
|
|
74
|
+
regexp = _attrs_to_regexp(attrs)
|
|
75
|
+
attrs = _regexp_to_attrs(regexp, attrs)
|
|
76
|
+
if attrs["type"] == "ignore":
|
|
77
|
+
rule = {
|
|
78
|
+
"type": attrs["type"],
|
|
79
|
+
"attrs": {
|
|
80
|
+
"regexp": regexp,
|
|
81
|
+
"diff_logic": import_rulebook_function(attrs["params"]["diff_logic"]),
|
|
82
|
+
"parent": bool(attrs["children"]),
|
|
83
|
+
"context": attrs["context"],
|
|
84
|
+
},
|
|
85
|
+
"children": {"global": {}, "local": {}}
|
|
86
|
+
}
|
|
87
|
+
else:
|
|
88
|
+
if attrs["params"]["ordered"]:
|
|
89
|
+
attrs["params"]["diff_logic"] = platform.VENDOR_DIFF_ORDERED[vendor]
|
|
90
|
+
attrs["params"]["logic"] = ORDERED_PATCH_LOGIC
|
|
91
|
+
elif attrs["params"]["rewrite"]:
|
|
92
|
+
attrs["params"]["diff_logic"] = REWRITE_DIFF_LOGIC
|
|
93
|
+
attrs["params"]["logic"] = REWRITE_PATCH_LOGIC
|
|
94
|
+
elif attrs["params"]["multiline"]:
|
|
95
|
+
attrs["params"]["diff_logic"] = MULTILINE_DIFF_LOGIC
|
|
96
|
+
rule = {
|
|
97
|
+
"type": attrs["type"],
|
|
98
|
+
"attrs": {
|
|
99
|
+
"logic": import_rulebook_function(attrs["params"]["logic"]),
|
|
100
|
+
"diff_logic": import_rulebook_function(attrs["params"]["diff_logic"]),
|
|
101
|
+
"regexp": regexp,
|
|
102
|
+
"reverse": _make_reverse(attrs["row"], reverse_prefix, flags=regexp.flags),
|
|
103
|
+
"comment": attrs["params"]["comment"],
|
|
104
|
+
"multiline": attrs["params"]["multiline"],
|
|
105
|
+
"parent": attrs["params"]["parent"] or bool(attrs["children"]),
|
|
106
|
+
"force_commit": attrs["params"]["force_commit"],
|
|
107
|
+
"ignore_case": attrs["params"]["ignore_case"],
|
|
108
|
+
"context": attrs["context"],
|
|
109
|
+
},
|
|
110
|
+
"children": None,
|
|
111
|
+
}
|
|
112
|
+
if not attrs["params"]["global"]:
|
|
113
|
+
rule["children"] = _compile_patching(attrs["children"], reverse_prefix, vendor)
|
|
114
|
+
rules["global" if attrs["params"]["global"] else "local"][raw_rule] = rule
|
|
115
|
+
return rules
|
|
116
|
+
|
|
117
|
+
|
|
118
|
+
@functools.lru_cache()
|
|
119
|
+
def _make_reverse(row, reverse_prefix, flags=0):
|
|
120
|
+
if row.startswith(reverse_prefix + " "):
|
|
121
|
+
row = row[len(reverse_prefix + " "):]
|
|
122
|
+
else:
|
|
123
|
+
row = "%s %s" % (reverse_prefix, row)
|
|
124
|
+
|
|
125
|
+
if row[-1] == "~":
|
|
126
|
+
row = row[:-1] + "{}"
|
|
127
|
+
|
|
128
|
+
row = re.sub(r"\*(/\S+/)?", "{}", row, flags=flags)
|
|
129
|
+
row = re.sub(r"\s*~(/\S+/)?", "", row, flags=flags)
|
|
130
|
+
return row
|
|
131
|
+
|
|
132
|
+
|
|
133
|
+
def _attrs_to_regexp(attrs):
|
|
134
|
+
flags = 0
|
|
135
|
+
ignore_case = attrs["params"]["ignore_case"]
|
|
136
|
+
if ignore_case:
|
|
137
|
+
flags |= re.IGNORECASE
|
|
138
|
+
return syntax.compile_row_regexp(attrs["row"], flags=flags)
|
|
139
|
+
|
|
140
|
+
|
|
141
|
+
def _regexp_to_attrs(regexp, attrs):
|
|
142
|
+
attrs["params"]["ignore_case"] = bool(regexp.flags & re.IGNORECASE)
|
|
143
|
+
return attrs
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
from annet.annlib.rulebook import common
|
|
2
|
+
from annet.annlib.types import Op
|
|
3
|
+
|
|
4
|
+
|
|
5
|
+
def default_diff(old, new, diff_pre, _pops=(Op.AFFECTED,)):
|
|
6
|
+
diff = common.default_diff(old, new, diff_pre, _pops)
|
|
7
|
+
return diff
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
def ordered_diff(old, new, diff_pre, _pops=(Op.AFFECTED,)):
|
|
11
|
+
diff = common.ordered_diff(old, new, diff_pre, _pops)
|
|
12
|
+
return diff
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Рулбук деплоя на устройства
|
|
2
|
+
#
|
|
3
|
+
# Операторы:
|
|
4
|
+
# * Один аргумент
|
|
5
|
+
# ~ Несколько аргументов (минимум один)
|
|
6
|
+
#
|
|
7
|
+
# Параметры:
|
|
8
|
+
# %timeout=... Таймаут выполнения команды (в секундах, по умолчанию 30)
|
|
9
|
+
#
|
|
10
|
+
# Ответы на вопросы
|
|
11
|
+
#
|
|
12
|
+
# <команда>
|
|
13
|
+
# dialog: <вопрос> ::: <ответ> <параметры>
|
|
14
|
+
#
|
|
15
|
+
# Если <вопрос> заключён в слеши (//), то воспринимается как регулярка, иначе - точное совпадение.
|
|
16
|
+
# Параметы:
|
|
17
|
+
# %send_nl=... Посылать ли перевод строки после ответа (bool, по умолчанию true)
|
|
18
|
+
# -----
|
|
19
|
+
|
|
20
|
+
~ %global
|
|
@@ -0,0 +1,125 @@
|
|
|
1
|
+
# В этом файле определяется порядок команд, в котором их следует подавать на устройство.
|
|
2
|
+
# - Если порядок команды не важен - ее можно не писать сюда совсем.
|
|
3
|
+
# - Если команда начинается с undo и прописан параметр %order_reverse - команда считается
|
|
4
|
+
# обратной, но занимает место между прямыми там, где указано (т.е. undo vlan batch
|
|
5
|
+
# будет стоять после блоков interface).
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
alias tmate-arista bash tmate-arista
|
|
9
|
+
service
|
|
10
|
+
switch
|
|
11
|
+
hardware
|
|
12
|
+
transceiver
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
logging trap
|
|
16
|
+
logging monitor
|
|
17
|
+
logging
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
platform
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
hostname
|
|
24
|
+
ip name-server
|
|
25
|
+
ip domain-name
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
ntp
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
qos profile *
|
|
32
|
+
~ %global
|
|
33
|
+
|
|
34
|
+
|
|
35
|
+
snmp-server
|
|
36
|
+
|
|
37
|
+
|
|
38
|
+
spanning-tree
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
service
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
username *
|
|
45
|
+
username * ssh-key
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
tacacs-server
|
|
49
|
+
|
|
50
|
+
|
|
51
|
+
aaa group
|
|
52
|
+
~ %global
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
aaa
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
username
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
role
|
|
62
|
+
~ %global
|
|
63
|
+
|
|
64
|
+
|
|
65
|
+
vlan
|
|
66
|
+
|
|
67
|
+
|
|
68
|
+
vrf instance
|
|
69
|
+
|
|
70
|
+
mpls label range dynamic *
|
|
71
|
+
mpls label range isis-sr *
|
|
72
|
+
mpls ip
|
|
73
|
+
mpls ldp
|
|
74
|
+
|
|
75
|
+
router isis
|
|
76
|
+
~ %global
|
|
77
|
+
|
|
78
|
+
interface
|
|
79
|
+
~ %global
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
(?:ip|ipv6) access-list
|
|
83
|
+
~ %global
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
(?:ip|ipv6) route
|
|
87
|
+
|
|
88
|
+
|
|
89
|
+
(?:ip|ipv6) routing
|
|
90
|
+
|
|
91
|
+
|
|
92
|
+
ip community-list
|
|
93
|
+
|
|
94
|
+
|
|
95
|
+
ip ftp
|
|
96
|
+
|
|
97
|
+
|
|
98
|
+
qos rewrite
|
|
99
|
+
qos map
|
|
100
|
+
|
|
101
|
+
|
|
102
|
+
route-map * (?:permit|deny) *
|
|
103
|
+
~ %global
|
|
104
|
+
|
|
105
|
+
|
|
106
|
+
router bfd
|
|
107
|
+
~ %global
|
|
108
|
+
|
|
109
|
+
|
|
110
|
+
router bgp
|
|
111
|
+
~ %global
|
|
112
|
+
|
|
113
|
+
|
|
114
|
+
router multicast
|
|
115
|
+
|
|
116
|
+
|
|
117
|
+
ip tacacs
|
|
118
|
+
|
|
119
|
+
|
|
120
|
+
management
|
|
121
|
+
~ %global
|
|
122
|
+
|
|
123
|
+
|
|
124
|
+
# vim: set syntax=annrulebook:
|
|
125
|
+
~ %global
|
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
description %global
|
|
2
|
+
|
|
3
|
+
|
|
4
|
+
qos profile *
|
|
5
|
+
~ %global
|
|
6
|
+
|
|
7
|
+
username * ssh-key
|
|
8
|
+
username *
|
|
9
|
+
|
|
10
|
+
aaa group ~
|
|
11
|
+
~ %global
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
role *
|
|
15
|
+
~ %global
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
vrf instance *
|
|
19
|
+
~ %global
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
interface * %logic=arista.iface.permanent
|
|
23
|
+
no switchport
|
|
24
|
+
description *
|
|
25
|
+
channel-group *
|
|
26
|
+
lacp rate *
|
|
27
|
+
service-profile *
|
|
28
|
+
~ %global
|
|
29
|
+
|
|
30
|
+
|
|
31
|
+
ip access-list standard *
|
|
32
|
+
* %logic=huawei.misc.undo_redo
|
|
33
|
+
|
|
34
|
+
ipv6 access-list standard *
|
|
35
|
+
* %logic=huawei.misc.undo_redo
|
|
36
|
+
|
|
37
|
+
ipv6 access-list *
|
|
38
|
+
* %logic=huawei.misc.undo_redo
|
|
39
|
+
|
|
40
|
+
route-map * * *
|
|
41
|
+
~ %global
|
|
42
|
+
|
|
43
|
+
router bfd
|
|
44
|
+
~ %global
|
|
45
|
+
|
|
46
|
+
|
|
47
|
+
router bgp *
|
|
48
|
+
no bgp default *
|
|
49
|
+
neighbor * maximum-routes
|
|
50
|
+
~ %global
|
|
51
|
+
|
|
52
|
+
ip load-sharing trident fields * %logic=common.default_instead_undo
|
|
53
|
+
|
|
54
|
+
management *
|
|
55
|
+
~ %global
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
no ~ %global
|
|
59
|
+
~ %global
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
# Рулбук деплоя на устройства
|
|
2
|
+
#
|
|
3
|
+
# Операторы:
|
|
4
|
+
# * Один аргумент
|
|
5
|
+
# ~ Несколько аргументов (минимум один)
|
|
6
|
+
#
|
|
7
|
+
# Параметры:
|
|
8
|
+
# %timeout=... Таймаут выполнения команды (в секундах, по умолчанию 30)
|
|
9
|
+
#
|
|
10
|
+
# Ответы на вопросы
|
|
11
|
+
#
|
|
12
|
+
# <команда>
|
|
13
|
+
# dialog: <вопрос> ::: <ответ> <параметры>
|
|
14
|
+
#
|
|
15
|
+
# Если <вопрос> заключён в слеши (//), то воспринимается как регулярка, иначе - точное совпадение.
|
|
16
|
+
# Параметы:
|
|
17
|
+
# %send_nl=... Посылать ли перевод строки после ответа (bool, по умолчанию true)
|
|
18
|
+
# -----
|
|
19
|
+
|
|
20
|
+
~ %ifcontext=block:ap-env %apply_logic=aruba.ap_env.apply
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
# В этом файле определяется порядок команд, в котором их следует подавать на устройство.
|
|
2
|
+
# - Если порядок команды не важен - ее можно не писать сюда совсем.
|
|
3
|
+
# - Если команда начинается с undo и прописан параметр %order_reverse - команда считается
|
|
4
|
+
# обратной, но занимает место между прямыми там, где указано.
|
|
5
|
+
|
|
6
|
+
|
|
7
|
+
hostname
|
|
8
|
+
ip-address
|
|
9
|
+
iap-master
|
|
10
|
+
iap-conductor
|
|
11
|
+
zone
|
|
12
|
+
dot11a-radio-disable
|
|
13
|
+
dot11g-radio-disable
|
|
14
|
+
ap-installation
|
|
15
|
+
a-channel
|
|
16
|
+
g-channel
|
|
17
|
+
a-external-antenna
|
|
18
|
+
g-external-antenna
|
|
19
|
+
a-ant-pol
|
|
20
|
+
g-ant-pol
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
virtual-controller-country *
|
|
24
|
+
virtual-controller-key *
|
|
25
|
+
name *
|
|
26
|
+
virtual-controller-ip *
|
|
27
|
+
ip-mode *
|
|
28
|
+
syslog-server *
|
|
29
|
+
terminal-access
|
|
30
|
+
telnet-server
|
|
31
|
+
loginsession timeout *
|
|
32
|
+
ntp-server *
|
|
33
|
+
clock timezone ~
|
|
34
|
+
rf-band *
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
allow-new-aps
|
|
38
|
+
allowed-ap *
|
|
39
|
+
|
|
40
|
+
|
|
41
|
+
snmp-server
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
arm
|
|
45
|
+
~
|
|
46
|
+
|
|
47
|
+
|
|
48
|
+
rf
|
|
49
|
+
~
|
|
50
|
+
|
|
51
|
+
|
|
52
|
+
syslog-level
|
|
53
|
+
|
|
54
|
+
|
|
55
|
+
iot ~
|
|
56
|
+
|
|
57
|
+
|
|
58
|
+
wlan ~
|
|
59
|
+
~
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
wired-port-profile *
|
|
63
|
+
~
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
uplink
|
|
67
|
+
~
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
airgroup
|
|
71
|
+
~
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
airgroupservice *
|
|
75
|
+
~
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
ipm
|
|
79
|
+
~
|
|
80
|
+
|
|
81
|
+
|
|
82
|
+
cluster-security
|
|
83
|
+
~
|