-
Notifications
You must be signed in to change notification settings - Fork 0
/
maps_config.py
254 lines (213 loc) · 10.7 KB
/
maps_config.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
#!/usr/bin/python
# -*- coding: utf-8 -*-
"""
Copyright 2023, 2024 Consoli Solutions, LLC. All rights reserved.
**License**
Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with
the License. You may also obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an
"AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific
language governing permissions and limitations under the License.
The license is free for single customer use (internal applications). Use of this module in the production,
redistribution, or service delivery for commerce requires an additional license. Contact [email protected] for
details.
**Description**
Creates MAPS SFP rules from a workbook
**Version Control**
+-----------+---------------+-----------------------------------------------------------------------------------+
| Version | Last Edit | Description |
+===========+===============+===================================================================================+
| 4.0.0 | 06 Mar 2024 | Initial Launch |
+-----------+---------------+-----------------------------------------------------------------------------------+
| 4.0.1 | 03 Apr 2024 | Added version numbers of imported libraries. |
+-----------+---------------+-----------------------------------------------------------------------------------+
"""
__author__ = 'Jack Consoli'
__copyright__ = 'Copyright 2023, 2024 Consoli Solutions, LLC'
__date__ = '03 Apr 2024'
__license__ = 'Apache License, Version 2.0'
__email__ = '[email protected]'
__maintainer__ = 'Jack Consoli'
__status__ = 'Released'
__version__ = '4.0.1'
import sys
import os
import datetime
import brcdapi.log as brcdapi_log
import brcdapi.gen_util as gen_util
import brcdapi.brcdapi_rest as brcdapi_rest
import brcdapi.fos_auth as fos_auth
import brcdapi.util as brcdapi_util
import brcdapi.file as brcdapi_file
import brcddb.brcddb_common as brcddb_common
import brcddb.brcddb_project as brcddb_project
import brcddb.api.interface as api_int
import brcddb.report.maps as maps_report
import brcddb.util.maps as brcddb_maps
_version_d = dict(
brcdapi_log=brcdapi_log.__version__,
gen_util=gen_util.__version__,
brcdapi_rest=brcdapi_rest.__version__,
fos_auth=fos_auth.__version__,
brcdapi_util=brcdapi_util.__version__,
brcdapi_file=brcdapi_file.__version__,
brcddb_common=brcddb_common.__version__,
brcddb_project=brcddb_project.__version__,
api_int=api_int.__version__,
maps_report=maps_report.__version__,
brcddb_maps=brcddb_maps.__version__,
)
_DOC_STRING = False # Should always be False. Prohibits any actual I/O. Only useful for building documentation
# _STAND_ALONE: True: Executes as a standalone module taking input from the command line. False: Does not automatically
# execute. This is useful when importing this module into another module that calls psuedo_main().
_STAND_ALONE = True # See note above
# debug input (for copy and paste into Run->Edit Configurations->script parameters):
# -ip 10.144.72.15 -id admin -pw AdminPassw0rd! -s self -i test/maps_test -log _logs
# Input parameter definitions
_input_d = gen_util.parseargs_login_d.copy()
_input_d.update(
i=dict(h='Required. Name of input file. Typically an edited version of the Excel workbook generated by '
'maps_report.py. Extension ".xlsx" is automatically added if no extension present.'),
fm=dict(r=False,
h='(Optional) FID map. This is useful when creating a MAPS policy intended to be applied to multiple '
'logical switches. The FID map is built such that all FIDs are mapped 1:1. This parameter allows you to'
'modify the map. The parameter is a semi-colon separated list of workbook FID,chassis FID. For example: '
'To map FID 1 in the workbook to FIDs 1, 2, and 3 in the parameter would be "-fm 1,1;1,2;1,3". A '
'range is also supported so a shorter way to write this would be "-fm 1,1-3". Only FIDs present in '
'the chassis are acted on. If the intent is to apply the MAPS updates to all FIDs except FID 128, this '
'could be written as "-fm 1,1-127". Note that any FID not modified with this option is mapped 1:1.'),
)
_input_d.update(gen_util.parseargs_log_d.copy())
_input_d.update(gen_util.parseargs_debug_d.copy())
_MAX_CHANGES = 32 # Maximum number of MAPS changes to make in a single request
_maps_kpi_l = (
# 'running/brocade-fabric/fabric-switch', Done automatically in brcddb.api.interface._get_chassis()
'running/brocade-fibrechannel-switch/fibrechannel-switch',
'running/brocade-maps/maps-config',
'running/brocade-maps/rule',
'running/brocade-maps/maps-policy',
'running/brocade-maps/group',
# 'running/brocade-maps/system-resources', # Not used. Not yet anyway.
)
class FOSError(Exception):
pass
def pseudo_main(user_id, pw, ip, sec, maps_file, fid_map_l):
"""Basically the main().
:param user_id: User ID
:type user_id: str
:param pw: Password
:type pw: str
:param ip: IP address
:type ip: str
:param sec: Security. 'none' for HTTP, 'self' for self-signed certificate
:type sec: str
:param maps_file: Name of file in the format output from maps_report.py
:type maps_file: str
:param fid_map_l: FID map
:type fid_map_l: list
:return: Exit code
:rtype: int
"""
ec, el, switch_obj, session = brcddb_common.EXIT_STATUS_OK, list(), None, None
# Create project for data collection
proj_obj = brcddb_project.new('zone_config_x', datetime.datetime.now().strftime('%d %b %Y %H:%M:%S'))
proj_obj.s_python_version(sys.version)
proj_obj.s_description('zone_config_x')
# Create project for new MAPS policies & rules
new_proj_obj = brcddb_project.new('zone_config_x', datetime.datetime.now().strftime('%d %b %Y %H:%M:%S'))
new_proj_obj.s_python_version(sys.version)
new_proj_obj.s_description('zone_config_x')
try:
el.extend(maps_report.read_maps(new_proj_obj, maps_file, echo=True))
if len(el) > 0:
raise FOSError
# Login
session = api_int.login(user_id, pw, ip, sec, proj_obj)
if fos_auth.is_error(session):
el.append('Login failed.') # api_int.login() posts the detail so no need to do it here.
session = None
raise FOSError
# Capture chassis, switch, and MAPS data. Speed is not an issue so get data for all FIDs
if not api_int.get_batch(session, proj_obj, _maps_kpi_l):
raise FOSError
# Send changes
chassis_obj = proj_obj.r_chassis_objects()[0]
for switch_obj in new_proj_obj.r_switch_objects():
error_l, changes = brcddb_maps.update_maps(session, chassis_obj, switch_obj, fid_map_l, echo=True)
el.extend(error_l)
except FOSError:
pass # All error messages should have been reported by the time we get here.
except brcdapi_util.VirtualFabricIdError:
el.append('Software error. Search the log for "Invalid FID" for details.')
ec = brcddb_common.EXIT_STATUS_API_ERROR
except BaseException as e:
el.extend(['Software error.', str(type(e)) + ': ' + str(e)])
ec = brcddb_common.EXIT_STATUS_ERROR
# Log out
if session is not None:
brcdapi_log.log('Logging out', echo=True)
obj = brcdapi_rest.logout(session)
if fos_auth.is_error(obj):
el.extend(['Logout failed', fos_auth.formatted_error_msg(obj)])
# Print any wrap up messages
if len(el) > 0:
el.append(str(len(el)) + ' Errors')
brcdapi_log.log(el, echo=True)
return ec
def _get_input():
"""Retrieves the command line input, reads the input Workbook, and validates the input
:return ec: Error code. See brcddb_common.EXIT_* for details
:rtype ec: int
"""
global __version__, _input_d, _version_d
ec, el, = brcddb_common.EXIT_STATUS_OK, list()
# Get command line input
buf = 'Configures MAPS rules, groups, and policies. Typically from the modified output of maps_report.py'
args_d = gen_util.get_input(buf, _input_d)
# Set up logging
if args_d['d']:
brcdapi_rest.verbose_debug(True)
brcdapi_log.open_log(folder=args_d['log'], supress=args_d['sup'], no_log=args_d['nl'], version_d=_version_d)
# Is the FID map valid?
args_fid_help = ''
fid_map_l = [f for f in range(0, 129)]
if isinstance(args_d['fm'], str):
try:
for map_l in args_d['fm'].split(';'):
temp_l = map_l.split(',')
if len(temp_l) != 2:
ec = brcddb_common.EXIT_STATUS_INPUT_ERROR
args_fid_help = ' Invalid format'
break
for fid in [int(f) for f in gen_util.range_to_list(temp_l[1])]:
fid_map_l[fid] = int(temp_l[0])
if fid_map_l[0] != 0:
raise IndexError
except(TypeError, IndexError):
ec = brcddb_common.EXIT_STATUS_INPUT_ERROR
args_fid_help = 'FIDs must be integers in the range of 1-128'
# Command line feedback
ml = [
os.path.basename(__file__) + ', ' + __version__,
'IP address, -ip: ' + brcdapi_util.mask_ip_addr(args_d['ip']),
'ID, -id: ' + str(args_d['id']),
'HTTPS, -s: ' + str(args_d['s']),
'Input file, -i: ' + str(args_d['i']),
'FID map, -fm: ' + str(args_d['fm']) + args_fid_help
]
brcdapi_log.log(ml + el, echo=True)
return ec if ec != brcddb_common.EXIT_STATUS_OK else \
pseudo_main(args_d['id'], args_d['pw'], args_d['ip'], args_d['s'],
brcdapi_file.full_file_name(args_d['i'], '.xlsx'), fid_map_l)
##################################################################
#
# Main Entry Point
#
###################################################################
if _DOC_STRING:
print('_DOC_STRING is True. No processing')
exit(brcddb_common.EXIT_STATUS_OK)
if _STAND_ALONE:
_ec = _get_input()
brcdapi_log.close_log(['', 'Processing Complete. Exit code: ' + str(_ec)], echo=True)
exit(_ec)