trigger 2.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.
- trigger/__init__.py +7 -0
- trigger/acl/__init__.py +32 -0
- trigger/acl/autoacl.py +70 -0
- trigger/acl/db.py +324 -0
- trigger/acl/dicts.py +357 -0
- trigger/acl/grammar.py +112 -0
- trigger/acl/ios.py +222 -0
- trigger/acl/junos.py +422 -0
- trigger/acl/models.py +118 -0
- trigger/acl/parser.py +168 -0
- trigger/acl/queue.py +296 -0
- trigger/acl/support.py +1431 -0
- trigger/acl/tools.py +746 -0
- trigger/bin/__init__.py +0 -0
- trigger/bin/acl.py +233 -0
- trigger/bin/acl_script.py +574 -0
- trigger/bin/aclconv.py +82 -0
- trigger/bin/check_access.py +93 -0
- trigger/bin/check_syntax.py +66 -0
- trigger/bin/fe.py +197 -0
- trigger/bin/find_access.py +191 -0
- trigger/bin/gnng.py +434 -0
- trigger/bin/gong.py +86 -0
- trigger/bin/load_acl.py +841 -0
- trigger/bin/load_config.py +18 -0
- trigger/bin/netdev.py +317 -0
- trigger/bin/optimizer.py +638 -0
- trigger/bin/run_cmds.py +18 -0
- trigger/changemgmt/__init__.py +352 -0
- trigger/changemgmt/bounce.py +57 -0
- trigger/cmds.py +1217 -0
- trigger/conf/__init__.py +94 -0
- trigger/conf/global_settings.py +674 -0
- trigger/contrib/__init__.py +7 -0
- trigger/exceptions.py +307 -0
- trigger/gorc.py +172 -0
- trigger/netdevices/__init__.py +1288 -0
- trigger/netdevices/loader.py +174 -0
- trigger/netscreen.py +1030 -0
- trigger/packages/__init__.py +6 -0
- trigger/packages/peewee.py +8084 -0
- trigger/rancid.py +463 -0
- trigger/tacacsrc.py +584 -0
- trigger/twister.py +2203 -0
- trigger/twister2.py +745 -0
- trigger/utils/__init__.py +88 -0
- trigger/utils/cli.py +349 -0
- trigger/utils/importlib.py +77 -0
- trigger/utils/network.py +157 -0
- trigger/utils/rcs.py +178 -0
- trigger/utils/templates.py +81 -0
- trigger/utils/url.py +78 -0
- trigger/utils/xmltodict.py +298 -0
- trigger-2.0.0.dist-info/METADATA +146 -0
- trigger-2.0.0.dist-info/RECORD +61 -0
- trigger-2.0.0.dist-info/WHEEL +5 -0
- trigger-2.0.0.dist-info/entry_points.txt +15 -0
- trigger-2.0.0.dist-info/licenses/AUTHORS.md +20 -0
- trigger-2.0.0.dist-info/licenses/LICENSE.md +28 -0
- trigger-2.0.0.dist-info/top_level.txt +2 -0
- twisted/plugins/trigger_xmlrpc.py +124 -0
trigger/__init__.py
ADDED
trigger/acl/__init__.py
ADDED
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Trigger's ACL parser.
|
|
3
|
+
|
|
4
|
+
This library contains various modules that allow for parsing, manipulation,
|
|
5
|
+
and management of network access control lists (ACLs). It will parse a complete
|
|
6
|
+
ACL and return an ACL object that can be easily translated to any supported
|
|
7
|
+
vendor syntax.
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
__author__ = "Jathan McCollum"
|
|
11
|
+
__author__ = "Jathan McCollum, Mike Biancaniello, Mike Harding"
|
|
12
|
+
__maintainer__ = "Jathan McCollum"
|
|
13
|
+
__email__ = "jathanism@aol.com"
|
|
14
|
+
__copyright__ = "Copyright 2010-2012, AOL Inc."
|
|
15
|
+
__version__ = (0, 1)
|
|
16
|
+
|
|
17
|
+
import os
|
|
18
|
+
|
|
19
|
+
from trigger.conf import settings
|
|
20
|
+
|
|
21
|
+
__all__ = ["parser", "acl_exists"]
|
|
22
|
+
|
|
23
|
+
# Parser
|
|
24
|
+
from . import parser
|
|
25
|
+
from .parser import *
|
|
26
|
+
|
|
27
|
+
__all__.extend(parser.__all__)
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Functions
|
|
31
|
+
def acl_exists(name):
|
|
32
|
+
return os.access(settings.FIREWALL_DIR + "/acl." + name, os.R_OK)
|
trigger/acl/autoacl.py
ADDED
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
"""
|
|
2
|
+
This module controls when ACLs get auto-applied to network devices,
|
|
3
|
+
in addition to what is specified in acls.db.
|
|
4
|
+
|
|
5
|
+
This is primarily used by :class:`~trigger.acl.db.AclsDB` to populate the
|
|
6
|
+
**implicit** ACL-to-device mappings.
|
|
7
|
+
|
|
8
|
+
No changes should be made to this module. You must specify the path to the
|
|
9
|
+
autoacl logic inside of ``settings.py`` as ``AUTOACL_FILE``. This will be
|
|
10
|
+
exported as ``autoacl`` so that the module path for the :func:`autoacl()`
|
|
11
|
+
function will still be :func:`trigger.autoacl.autoacl`.
|
|
12
|
+
|
|
13
|
+
This trickery allows us to keep the business-logic for how ACLs are mapped to
|
|
14
|
+
devices out of the Trigger packaging.
|
|
15
|
+
|
|
16
|
+
If you do not specify a location for ``AUTOACL_FILE`` or the module cannot be
|
|
17
|
+
loaded, then a default :func:`autoacl()` function ill be used.
|
|
18
|
+
"""
|
|
19
|
+
|
|
20
|
+
__author__ = "Jathan McCollum, Eileen Tschetter"
|
|
21
|
+
__maintainer__ = "Jathan McCollum"
|
|
22
|
+
__email__ = "jathan.mccollum@teamaol.com"
|
|
23
|
+
__copyright__ = "Copyright 2010-2012, AOL Inc."
|
|
24
|
+
|
|
25
|
+
import warnings
|
|
26
|
+
|
|
27
|
+
from twisted.python import log
|
|
28
|
+
|
|
29
|
+
from trigger.conf import settings
|
|
30
|
+
from trigger.utils.importlib import import_module_from_path
|
|
31
|
+
|
|
32
|
+
__all__ = ("autoacl",)
|
|
33
|
+
|
|
34
|
+
module_path = settings.AUTOACL_FILE
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
# In either case we're exporting a single name: autoacl().
|
|
38
|
+
try:
|
|
39
|
+
# Placeholder for the custom autoacl module that will provide the autoacl()
|
|
40
|
+
# function. Either of these operations will raise an ImportError if they
|
|
41
|
+
# don't work, so it's safe to have them within the same try statement.
|
|
42
|
+
_autoacl_module = import_module_from_path(module_path, "_autoacl_module")
|
|
43
|
+
log.msg(f"Loading autoacl() from {module_path}")
|
|
44
|
+
from _autoacl_module import autoacl
|
|
45
|
+
except ImportError:
|
|
46
|
+
msg = f"Function autoacl() could not be found in {module_path}, using default!"
|
|
47
|
+
warnings.warn(msg, RuntimeWarning)
|
|
48
|
+
|
|
49
|
+
def autoacl(dev, explicit_acls=None):
|
|
50
|
+
"""
|
|
51
|
+
Given a NetDevice object, returns a set of **implicit** (auto) ACLs. We
|
|
52
|
+
require a device object so that we don't have circular dependencies
|
|
53
|
+
between netdevices and autoacl.
|
|
54
|
+
|
|
55
|
+
This function MUST return a ``set()`` of acl names or you will break
|
|
56
|
+
the ACL associations. An empty set is fine, but it must be a set!
|
|
57
|
+
|
|
58
|
+
:param dev: A :class:`~trigger.netdevices.NetDevice` object.
|
|
59
|
+
:param explicit_acls: A set containing names of ACLs. Default: set()
|
|
60
|
+
|
|
61
|
+
>>> dev = nd.find('test1-abc')
|
|
62
|
+
>>> dev.vendor
|
|
63
|
+
<Vendor: Juniper>
|
|
64
|
+
>>> autoacl(dev)
|
|
65
|
+
set(['juniper-router-protect', 'juniper-router.policer'])
|
|
66
|
+
|
|
67
|
+
NOTE: If the default function is returned it does nothing with the
|
|
68
|
+
arguments and always returns an empty set.
|
|
69
|
+
"""
|
|
70
|
+
return set()
|
trigger/acl/db.py
ADDED
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Redis-based replacement of the legacy acls.db file. This is used for
|
|
3
|
+
interfacing with the explicit and automatic ACL-to-device mappings.
|
|
4
|
+
|
|
5
|
+
>>> from trigger.netdevices import NetDevices
|
|
6
|
+
>>> from trigger.acl.db import AclsDB
|
|
7
|
+
>>> nd = NetDevices()
|
|
8
|
+
>>> dev = nd.find('test1-abc')
|
|
9
|
+
>>> a = AclsDB()
|
|
10
|
+
>>> a.get_acl_set(dev)
|
|
11
|
+
set(['juniper-router.policer', 'juniper-router-protect', 'abc123'])
|
|
12
|
+
>>> a.get_acl_set(dev, 'explicit')
|
|
13
|
+
set(['abc123'])
|
|
14
|
+
>>> a.get_acl_set(dev, 'implicit')
|
|
15
|
+
set(['juniper-router.policer', 'juniper-router-protect'])
|
|
16
|
+
>>> a.get_acl_dict(dev)
|
|
17
|
+
{'all': set(['abc123', 'juniper-router-protect', 'juniper-router.policer']),
|
|
18
|
+
'explicit': set(['abc123']),
|
|
19
|
+
'implicit': set(['juniper-router-protect', 'juniper-router.policer'])}
|
|
20
|
+
"""
|
|
21
|
+
|
|
22
|
+
__author__ = "Jathan McCollum"
|
|
23
|
+
__maintainer__ = "Jathan McCollum"
|
|
24
|
+
__email__ = "jathan@gmail.com"
|
|
25
|
+
__copyright__ = "Copyright 2010-2012, AOL Inc.; 2013 Salesforce.com"
|
|
26
|
+
|
|
27
|
+
from collections import defaultdict
|
|
28
|
+
|
|
29
|
+
import redis
|
|
30
|
+
from twisted.python import log
|
|
31
|
+
|
|
32
|
+
from trigger import exceptions
|
|
33
|
+
from trigger.acl.autoacl import autoacl
|
|
34
|
+
from trigger.conf import settings
|
|
35
|
+
|
|
36
|
+
ACLSDB_BACKUP = "./acls.csv"
|
|
37
|
+
DEBUG = False
|
|
38
|
+
|
|
39
|
+
# The redis instance. It doesn't care if it can't reach Redis until you actually
|
|
40
|
+
# try to talk to Redis.
|
|
41
|
+
r = redis.Redis(
|
|
42
|
+
host=settings.REDIS_HOST, port=settings.REDIS_PORT, db=settings.REDIS_DB
|
|
43
|
+
)
|
|
44
|
+
|
|
45
|
+
# Exports
|
|
46
|
+
__all__ = (
|
|
47
|
+
# functions
|
|
48
|
+
"get_matching_acls",
|
|
49
|
+
"get_all_acls",
|
|
50
|
+
"get_bulk_acls",
|
|
51
|
+
"populate_bulk_acls",
|
|
52
|
+
# classes
|
|
53
|
+
"AclsDB",
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
|
|
57
|
+
# Classes
|
|
58
|
+
class AclsDB:
|
|
59
|
+
"""
|
|
60
|
+
Container for ACL operations.
|
|
61
|
+
|
|
62
|
+
add/remove operations are for explicit associations only.
|
|
63
|
+
"""
|
|
64
|
+
|
|
65
|
+
def __init__(self):
|
|
66
|
+
self.redis = r
|
|
67
|
+
log.msg("ACLs database client initialized")
|
|
68
|
+
|
|
69
|
+
def add_acl(self, device, acl):
|
|
70
|
+
"""
|
|
71
|
+
Add explicit acl to device
|
|
72
|
+
|
|
73
|
+
>>> dev = nd.find('test1-mtc')
|
|
74
|
+
>>> a.add_acl(dev, 'acb123')
|
|
75
|
+
'added acl abc123 to test1-mtc.net.aol.com'
|
|
76
|
+
"""
|
|
77
|
+
try:
|
|
78
|
+
rc = self.redis.sadd(f"acls:explicit:{device.nodeName}", acl)
|
|
79
|
+
except redis.exceptions.ResponseError as err:
|
|
80
|
+
return str(err)
|
|
81
|
+
if rc != 1:
|
|
82
|
+
raise exceptions.ACLSetError(f"{device.nodeName} already has acl {acl}")
|
|
83
|
+
self.redis.save()
|
|
84
|
+
|
|
85
|
+
return f"added acl {acl} to {device}"
|
|
86
|
+
|
|
87
|
+
def remove_acl(self, device, acl):
|
|
88
|
+
"""
|
|
89
|
+
Remove explicit acl from device.
|
|
90
|
+
|
|
91
|
+
>>> a.remove_acl(dev, 'acb123')
|
|
92
|
+
'removed acl abc123 from test1-mtc.net.aol.com'
|
|
93
|
+
"""
|
|
94
|
+
try:
|
|
95
|
+
rc = self.redis.srem(f"acls:explicit:{device.nodeName}", acl)
|
|
96
|
+
except redis.exceptions.ResponseError as err:
|
|
97
|
+
return str(err)
|
|
98
|
+
if rc != 1:
|
|
99
|
+
raise exceptions.ACLSetError(f"{device.nodeName} does not have acl {acl}")
|
|
100
|
+
self.redis.save()
|
|
101
|
+
|
|
102
|
+
return f"removed acl {acl} from {device}"
|
|
103
|
+
|
|
104
|
+
def get_acl_dict(self, device):
|
|
105
|
+
"""
|
|
106
|
+
Returns a dict of acl mappings for a @device, which is expected to
|
|
107
|
+
be a NetDevice object.
|
|
108
|
+
|
|
109
|
+
>>> a.get_acl_dict(dev)
|
|
110
|
+
{'all': set(['115j', 'protectRE', 'protectRE.policer', 'test-bluej',
|
|
111
|
+
'testgreenj', 'testops_blockmj']),
|
|
112
|
+
'explicit': set(['test-bluej', 'testgreenj', 'testops_blockmj']),
|
|
113
|
+
'implicit': set(['115j', 'protectRE', 'protectRE.policer'])}
|
|
114
|
+
"""
|
|
115
|
+
acls = {}
|
|
116
|
+
|
|
117
|
+
# Explicit (we want to make sure the key exists before we try to assign
|
|
118
|
+
# a value)
|
|
119
|
+
expl_key = f"acls:explicit:{device.nodeName}"
|
|
120
|
+
if self.redis.exists(expl_key):
|
|
121
|
+
acls["explicit"] = self.redis.smembers(expl_key) or set()
|
|
122
|
+
else:
|
|
123
|
+
acls["explicit"] = set()
|
|
124
|
+
|
|
125
|
+
# Implicit (automatically-assigned). We're passing the explicit_acls to
|
|
126
|
+
# autoacl so that we can use them logically for auto assignments.
|
|
127
|
+
acls["implicit"] = autoacl(device, explicit_acls=acls["explicit"])
|
|
128
|
+
|
|
129
|
+
# All
|
|
130
|
+
acls["all"] = acls["implicit"] | acls["explicit"]
|
|
131
|
+
|
|
132
|
+
return acls
|
|
133
|
+
|
|
134
|
+
def get_acl_set(self, device, acl_set="all"):
|
|
135
|
+
"""
|
|
136
|
+
Return an acl set matching @acl_set for a given device. Match can be
|
|
137
|
+
one of ['all', 'explicit', 'implicit']. Defaults to 'all'.
|
|
138
|
+
|
|
139
|
+
>>> a.get_acl_set(dev)
|
|
140
|
+
set(['testops_blockmj', 'testgreenj', '115j', 'protectRE',
|
|
141
|
+
'protectRE.policer', 'test-bluej'])
|
|
142
|
+
>>> a.get_acl_set(dev, 'explicit')
|
|
143
|
+
set(['testops_blockmj', 'test-bluej', 'testgreenj'])
|
|
144
|
+
>>> a.get_acl_set(dev, 'implicit')
|
|
145
|
+
set(['protectRE', 'protectRE.policer', '115j'])
|
|
146
|
+
"""
|
|
147
|
+
acls_dict = self.get_acl_dict(device)
|
|
148
|
+
# ACL_SETS = ['all', 'explicit', 'implicit', 'bulk']
|
|
149
|
+
ACL_SETS = acls_dict.keys()
|
|
150
|
+
if DEBUG:
|
|
151
|
+
print("fetching"), acl_set, "acls for", device
|
|
152
|
+
if acl_set not in ACL_SETS:
|
|
153
|
+
raise exceptions.InvalidACLSet(f"match statement must be one of {ACL_SETS}")
|
|
154
|
+
|
|
155
|
+
return acls_dict[acl_set]
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
# Functions
|
|
159
|
+
def populate_explicit_acls(aclsdb_file):
|
|
160
|
+
"""
|
|
161
|
+
populate acls:explicit from legacy acls.db file.
|
|
162
|
+
|
|
163
|
+
Format:
|
|
164
|
+
|
|
165
|
+
'{unused},{hostname},{acls}\\n'
|
|
166
|
+
|
|
167
|
+
- @unused is leftover from legacy and is not used
|
|
168
|
+
- @hostname column is the fqdn of the device
|
|
169
|
+
- @acls is a colon-separated list of ACL names
|
|
170
|
+
|
|
171
|
+
Example:
|
|
172
|
+
|
|
173
|
+
xx,test1-abc.net.aol.com,juniper-router.policer:juniper-router-protect:abc123
|
|
174
|
+
xx,test2-abc.net.aol.com,juniper-router.policer:juniper-router-protect:abc123
|
|
175
|
+
"""
|
|
176
|
+
import csv
|
|
177
|
+
|
|
178
|
+
for row in csv.reader(open(aclsdb_file)):
|
|
179
|
+
if not row[0].startswith("!"):
|
|
180
|
+
[r.sadd(f"acls:explicit:{row[1]}", acl) for acl in row[2].split(":")]
|
|
181
|
+
r.save()
|
|
182
|
+
|
|
183
|
+
|
|
184
|
+
def backup_explicit_acls():
|
|
185
|
+
"""dumps acls:explicit:* to csv"""
|
|
186
|
+
import csv
|
|
187
|
+
|
|
188
|
+
out = csv.writer(open(ACLSDB_BACKUP, "w"))
|
|
189
|
+
for key in r.keys("acls:explicit:*"):
|
|
190
|
+
out.writerow([key.split(":")[-1], ":".join(map(str, r.smembers(key)))])
|
|
191
|
+
|
|
192
|
+
|
|
193
|
+
def populate_implicit_acls(nd=None):
|
|
194
|
+
"""populate acls:implicit (autoacls)"""
|
|
195
|
+
nd = nd or get_netdevices()
|
|
196
|
+
for dev in nd.all():
|
|
197
|
+
[r.sadd(f"acls:implicit:{dev.nodeName}", acl) for acl in autoacl(dev)]
|
|
198
|
+
r.save()
|
|
199
|
+
|
|
200
|
+
|
|
201
|
+
def get_netdevices(production_only=True, with_acls=True):
|
|
202
|
+
"""Shortcut to import, instantiate, and return a NetDevices instance."""
|
|
203
|
+
from trigger.netdevices import NetDevices
|
|
204
|
+
|
|
205
|
+
return NetDevices(production_only=production_only, with_acls=with_acls)
|
|
206
|
+
|
|
207
|
+
|
|
208
|
+
def get_all_acls(nd=None):
|
|
209
|
+
"""
|
|
210
|
+
Returns a dict keyed by acl names whose containing a set of NetDevices
|
|
211
|
+
objects to which each acl is applied.
|
|
212
|
+
|
|
213
|
+
@nd can be your own NetDevices object if one is not supplied already
|
|
214
|
+
|
|
215
|
+
>>> all_acls = get_all_acls()
|
|
216
|
+
>>> all_acls['abc123']
|
|
217
|
+
set([<NetDevice: test1-abc.net.aol.com>, <NetDevice: fw1-xyz.net.aol.com>])
|
|
218
|
+
"""
|
|
219
|
+
# nd = nd or settings.get_netdevices()
|
|
220
|
+
nd = nd or get_netdevices()
|
|
221
|
+
all_acls = defaultdict(set)
|
|
222
|
+
for device in nd.all():
|
|
223
|
+
[all_acls[acl].add(device) for acl in device.acls if acl != ""]
|
|
224
|
+
|
|
225
|
+
return all_acls
|
|
226
|
+
|
|
227
|
+
|
|
228
|
+
def get_bulk_acls(nd=None):
|
|
229
|
+
"""
|
|
230
|
+
Returns a set of acls with an applied count over
|
|
231
|
+
settings.AUTOLOAD_BULK_THRESH.
|
|
232
|
+
"""
|
|
233
|
+
# nd = nd or settings.get_netdevices()
|
|
234
|
+
nd = nd or get_netdevices()
|
|
235
|
+
all_acls = get_all_acls()
|
|
236
|
+
bulk_acls = set(
|
|
237
|
+
[
|
|
238
|
+
acl
|
|
239
|
+
for acl, devs in all_acls.items()
|
|
240
|
+
if len(devs) >= settings.AUTOLOAD_BULK_THRESH
|
|
241
|
+
]
|
|
242
|
+
)
|
|
243
|
+
|
|
244
|
+
return bulk_acls
|
|
245
|
+
|
|
246
|
+
|
|
247
|
+
def populate_bulk_acls(nd=None):
|
|
248
|
+
"""
|
|
249
|
+
Given a NetDevices instance, Adds bulk_acls attribute to NetDevice objects.
|
|
250
|
+
"""
|
|
251
|
+
nd = nd or get_netdevices()
|
|
252
|
+
bulk_acls = get_bulk_acls()
|
|
253
|
+
for dev in nd.all():
|
|
254
|
+
dev.bulk_acls = dev.acls.intersection(bulk_acls)
|
|
255
|
+
|
|
256
|
+
|
|
257
|
+
def get_matching_acls(wanted, exact=True, match_acl=True, match_device=False, nd=None):
|
|
258
|
+
"""
|
|
259
|
+
Return a sorted list of the names of devices that have at least one
|
|
260
|
+
of the wanted ACLs, and the ACLs that matched on each. Without 'exact',
|
|
261
|
+
match ACL name by startswith.
|
|
262
|
+
|
|
263
|
+
To get a list of devices, matching the ACLs specified:
|
|
264
|
+
|
|
265
|
+
>>> adb.get_matching_acls(['abc123'])
|
|
266
|
+
[('fw1-xyz.net.aol.com', ['abc123']), ('test1-abc.net.aol.com', ['abc123'])]
|
|
267
|
+
|
|
268
|
+
To get a list of ACLS matching the devices specified using an explicit
|
|
269
|
+
match (default) by setting match_device=True:
|
|
270
|
+
|
|
271
|
+
>>> adb.get_matching_acls(['test1-abc'], match_device=True)
|
|
272
|
+
[]
|
|
273
|
+
>>> adb.get_matching_acls(['test1-abc.net.aol.com'], match_device=True)
|
|
274
|
+
[('test1-abc.net.aol.com', ['abc123', 'juniper-router-protect',
|
|
275
|
+
'juniper-router.policer'])]
|
|
276
|
+
|
|
277
|
+
To get a list of ACLS matching the devices specified using a partial
|
|
278
|
+
match. Not how it returns all devices starting with 'test1-mtc':
|
|
279
|
+
|
|
280
|
+
>>> adb.get_matching_acls(['test1-abc'], match_device=True, exact=False)
|
|
281
|
+
[('test1-abc.net.aol.com', ['abc123', 'juniper-router-protect',
|
|
282
|
+
'juniper-router.policer'])]
|
|
283
|
+
"""
|
|
284
|
+
found = []
|
|
285
|
+
wanted_set = set(wanted)
|
|
286
|
+
|
|
287
|
+
def match_exact(x):
|
|
288
|
+
return x & wanted_set
|
|
289
|
+
|
|
290
|
+
def match_begin(x):
|
|
291
|
+
matched = set()
|
|
292
|
+
for a in wanted_set:
|
|
293
|
+
for b in x:
|
|
294
|
+
if b.startswith(a):
|
|
295
|
+
matched.add(b)
|
|
296
|
+
return matched
|
|
297
|
+
|
|
298
|
+
match = exact and match_exact or match_begin
|
|
299
|
+
|
|
300
|
+
# Return all the ACLs if matched by device, or the matched ACLs
|
|
301
|
+
# if matched by ACL.
|
|
302
|
+
# nd = nd or settings.get_netdevices()
|
|
303
|
+
nd = nd or get_netdevices()
|
|
304
|
+
for name, dev in nd.items():
|
|
305
|
+
hit = None
|
|
306
|
+
if match_device:
|
|
307
|
+
if exact and name in wanted:
|
|
308
|
+
hit = dev.acls
|
|
309
|
+
elif not exact:
|
|
310
|
+
for x in wanted:
|
|
311
|
+
if name.startswith(x):
|
|
312
|
+
hit = dev.acls
|
|
313
|
+
break
|
|
314
|
+
|
|
315
|
+
if hit is None and match_acl:
|
|
316
|
+
hit = match(dev.acls)
|
|
317
|
+
|
|
318
|
+
if hit:
|
|
319
|
+
matched = list(hit)
|
|
320
|
+
matched.sort()
|
|
321
|
+
found.append((name, matched))
|
|
322
|
+
|
|
323
|
+
found.sort()
|
|
324
|
+
return found
|