def try_cli(command): """Try CLI command and exit if invalid""" try: return clicmd(command, True) except: print 'Script Error: Check Command Syntax' exit()
def version_check(): pimage = True sh_switch = clicmd('show switch', True) ver = '' if 'Image Selected: secondary' in sh_switch: pimage = False sh_switch = sh_switch.splitlines() for line in sh_switch: if (pimage and ('Primary ver:' in line)) or (not pimage and ('Secondary ver:' in line)): ver = line.split(':') ver = ver[1].strip() if ver == '': print FMT_ERROR.format('Problem detecting software version') exit() elif ver.startswith('15.6') or ver.startswith('15.7'): return True else: return False
def __call__(self): self.get_params() # just display the version and exit if self.args.version is True: print self.proc_name, "Version:", _version_ return # run these commands in sequence cmd_list = [ ('show ports {} config port-number no-refresh'.format(self.args.ports), False), ('show ports {} utilization port-number packets'.format(self.args.ports), False), ('show port {} utilization port-number bytes'.format(self.args.ports), False), ('show port {} utilization port-number bandwidth'.format(self.args.ports), False), ('run script portsum.py {}'.format(self.args.ports), True), # the script produces its own output ('show ports {} information detail'.format(self.args.ports), False), ('show ports {} wred no-refresh'.format(self.args.ports), False), ('show ports {} flow-control no-refresh'.format(self.args.ports), False), ('show ports {} qosmonitor no-refresh'.format(self.args.ports), False), ] for cmd, no_display in cmd_list: print '*' * 80 print cmd if no_display: exsh.clicmd(cmd) else: print exsh.clicmd(cmd, capture=True)
def main(): parser = ArgParser(prog='dhcp43.py', description="This script will generate the hex needed to configure EXOS's built-in DHCP server with option 43 for ZTP. " "It will also either provide the command to use, or configure the option on the specified VLAN.") parser.add_argument('-s', '--server_address', help='IP Address of TFTP server for sub-option 100. May be omitted if a URL is used for sub-option 101.', type=str, default="") parser.add_argument('-v', '--vlan_name', help='VLAN to configure option 43 on. If this is included, the option 43 config will be added to the DHCP ' 'server configuration on this switch for this VLAN. If not, the config command will simply be printed.', type=str, default="") parser.add_argument('files', help='Files to be downloaded. If the \'-s\' option is used, this may be simply be a file name. ' 'If the \'-s\' option is not used, this should be a full URL. (IE, tftp://192.168.1.10/config.xsf)', type=str, nargs='+') args = parser.parse_args() vlan = args.vlan_name server = args.server_address files = args.files # Convert the IP address to hex, if it exists hex = [] if len(server): ip = server.split('.') hex.append(binascii.hexlify(chr(100))) #sub-option 100 hex.append(binascii.hexlify(chr(4))) #length = 4 bytes for i in ip: #convert each byte of the IP to hex hex.append(binascii.hexlify(chr(int(i)))) # Convert the filenames/URLs to hex for i in files: hex.append(binascii.hexlify(chr(101))) #sub-option 101 hex.append(binascii.hexlify(chr(len(i)))) #length of filename/URL in bytes hex.append(binascii.hexlify(i)) #filename converted to hex #Generate the command needed to configure this: hex = ''.join(hex) #join all the hex into one string hex = ':'.join(hex[i:i+2] for i in range(0, len(hex), 2)) #delimit the bytes with ':', like EXOS expects if len(vlan): #if a vlan was give do the configuration cmd = 'configure vlan {0} dhcp-options code 43 hex {1}'.format(vlan, hex) clicmd(cmd) else: #otherwise print the command vlan = '<vlan_name>' cmd = 'configure vlan {0} dhcp-options code 43 hex {1}'.format(vlan, hex) print cmd
def main(): var1=exsh.clicmd("show ports stack-ports rxerrors no-refresh | i 1", capture=True) var1=str(var1) var1=var1.split() var1=int(var1[2]) if var1>0: var5=exsh.clicmd("create log message \"RX errors are present on stack-port 1\"") var5=exsh.clicmd("clear counters port stack-ports") else:
def port_check(port): try: ports_result = [] cmd = 'debug cfgmgr show next vlan.show_ports_info portList={0} port=None'.format(port) result = json.loads(exsh.clicmd(cmd, capture=True)) for status in result['data']: ports_result.append(status['status']) if 'ERROR' in ports_result: return False else: return True except RuntimeError as cmdMsg: print 'Error:', cmdMsg, ':', cmd exsh.clicmd('create log message "flow_mod.py: Error: cmd={0} : msg={1}"'.format(cmd, cmdMsg), capture=False) return False
def port_is_valid(port): port = port.replace(' ', '') port_check = json.loads(exsh.clicmd('debug cfgmgr show next maximum-rows 1 vlan.show_ports_info portList={0}'.format(port), capture=True, xml=False)) if port_check['data'][0]['status'] == 'SUCCESS': return True else: return False
def cfg_areas(): """ Returns a list of config modules with non-default config Does not support user-created VRs. """ cfg_modules = [] config = exsh.clicmd('show config', capture=True) config = config.splitlines(True) moduleName = '' moduleStr = '' configExist = False for line in config: if '#' not in line and line != '\n': moduleStr += line configExist = True elif configExist is True and '#' in line: cfg_modules.append(moduleName) moduleStr = line moduleName = '' configExist = False elif '#' in line: moduleStr += line configExist = False if '# Module ' in line: moduleName = line.replace('# Module ', '') moduleName = moduleName.replace(' configuration.\n', '') moduleName = moduleName.lower() elif configExist is True and line == '\n': moduleStr += line else: moduleStr = '' return cfg_modules
def cmd2Dict(clicmd): """ some EXOS commands return not all info if you use cmd2data, e.g. show switch, this function helps in this case """ aDict = {} tag = None value = "" data = exsh.clicmd(clicmd, capture=True) for line in data.split("\n"): if not line: # ignore empty lines continue if line[0] != " ": # this a tag line s = line.rstrip().split(":", 1) # cleanup the entries s = [t.strip() for t in s] if len(s) == 2: if tag: # we need to save the old stuff aDict[tag] = value tag = s[0] value = s[1] else: # should not happen, but if than we add it to the previous tag value += "\n" + s[0] else: # belongs to the previous tag value += "\n" + line.strip() if tag: # save the last tag too aDict[tag] = value return aDict
def __call__(self): DIAG_LOCK = '/usr/local/cfg/diag.lock' if isfile(DIAG_LOCK): # returning from a diagnostics reboot remove(DIAG_LOCK) return # create an EXOS process that starts diagnostics print >> stderr, "\nStarting Diagnostics\n" with open(DIAG_LOCK, 'w'): pass # create the EXOS expy backend process exsh.clicmd('create process {0} python-module {0} start on-demand'.format(PROCESS_NAME)) slot_clause = '' exsh.clicmd('start process {0} {1}'.format(PROCESS_NAME, slot_clause))
def port_active(port): port_status = json.loads(clicmd('debug cfgmgr show one vlan.show_ports_info formatted portList={0}'.format(port), capture=True)) port_status = port_status['data'][0]['linkState'] if port_status == '1': return True else: return False
def cliCmd(cmd, arg=None, fmt=None): # Send a command, with optional args; fmt = None|raw|xml if fmt == 'xml': captFlag = False xmlFlag = True elif fmt == 'raw': captFlag = True xmlFlag = False else: captFlag = False xmlFlag = False try: output = exsh.clicmd(cmd, args=arg, capture=captFlag, xml=xmlFlag) debug("cliCmd -> {}".format(cmd)) except RuntimeError as detail: print "RuntimeError:", detail print "Unable to execute CLI command '{}'".format(cmd) if arg: print " with arguments '{}'".foramt(arg) sys.exit(1) if fmt == 'xml': # because exsh.clicmd returns malformed XML output = '<xmldata>' + output + '</xmldata>' return output
def get_port_vlan_list(port): vlanRslt = json.loads( clicmd( 'debug cfgmgr show next vlan.show_ports_info_detail_vlans port={0} vlanIfInstance=None' .format(port), True)) port_data = [] for vlanRow in vlanRslt['data']: port_data.append(str(vlanRow['vlanName'])) return port_data
def get_vlan_ports(vlan): vlanportsRslt = json.loads( clicmd('debug cfgmgr show one vlan.vlanPort vlanName={0}'.format(vlan), True)) return ({ 'untagged': str(vlanportsRslt['data'][0]['untaggedPorts']), 'tagged': str(vlanportsRslt['data'][0]['taggedPorts']) })
def get_active_ports(): active_list = [] vlan_ports_info = json.loads(exsh.clicmd('debug cfgmgr show next vlan.show_ports_info port=None ' 'portList=*', capture=True, xml=False)) for item in vlan_ports_info['data']: if item['linkState'] == '1': active_list.append(item['port']) return active_list
def halDebugCongestion(): """ Returns CPU and fabric congestion for all switches in a stack. If the switch is a standalone it will report as slot 1. """ stackRslt = json.loads(exsh.clicmd('debug cfgmgr show next hal.halDebugCongestion formatted', True)) slot_data = [] for slot in stackRslt['data']: slot_data.append({'Slot' : str(slot['slot']), 'cpu_cng' : str(slot['cpu_cng']), 'fabric_cng' : str(slot['fabric_cng'])}) return slot_data
def get_switch_start_dates(): """ Returns an array of strings containing the initial start date of each switch in the stack """ raw_out = exsh.clicmd("sho odometers", capture=True, xml=False) #odo_info = re.findall('[a-zA-z]{3}-\d+-\d+', raw_out) odo_info = re.findall('Switch.*', raw_out) odo_info = [re.findall('[a-zA-z]{3}-\d+-\d+', line)[0] \ for line in odo_info] return odo_info
def get_vlans(): """ Returns a list of all VLANs created on the switch """ output = json.loads(exsh.clicmd('debug cfgmgr show next vlan.vlan', capture=True)) output = output['data'] vlans = [] for item in output: vlans.append(item['name']) return set(vlans)
def json_clicmd(self, cmd): # issue debug cfgmgr CLI command to EXOS and return the JSON data self.log.debug(cmd) json_result = exsh.clicmd(cmd, capture=True) try: json_dict = json.loads(json_result) except: self.log.debug('JSON format error') return None, None # extract and return the data list return (json_dict.get("class"), json_dict.get("data"))
def get_exos_json_data(self, cmd): # run the command that returns JSON results result = exsh.clicmd(cmd, True) # convert the results to JSON try: json_result = json.loads(result) except: return [] # return the list of dictionaries return json_result.get('data', [])
def __call__(self): # cleanup from previous run try: exsh.clicmd('delete process {}'.format(self.process_name)) except Exception: pass if isfile(self.diag_lock): # returning from a diagnostics reboot remove(self.diag_lock) self.fix_mgmt_port() return # create an EXOS process that starts diagnostics print >> stderr, "\nStarting Diagnostics\n" with open(self.diag_lock, 'w'): pass # create the EXOS expy backend process exsh.clicmd( 'create process {0} python-module {0} start on-demand'.format( self.process_name)) slot_clause = '' exsh.clicmd('start process {0} {1}'.format(self.process_name, slot_clause))
def get_port_vlans(port): vlanRslt = json.loads( exsh.clicmd( 'debug cfgmgr show next vlan.show_ports_info_detail_vlans formatted port={0} vlanIfInstance=None' .format(port), True)) port_data = [] for vlanRow in vlanRslt['data']: port_data.append({ 'VlanName': str(vlanRow['vlanName']), 'VlanId': str(vlanRow['vlanId']), 'tag': str(vlanRow['tagStatus']) }) return port_data
def get_all_ports(): """Create and return a EXOS CLI friendly port list string containing all device ports Some show commands do not provide a "port all" option but allow for specifiying a port list. This method creates an "all" port list to be used with these CLI commands In the future this may be used to return the all port string as well as an active port list :return: str. -- EXOS CLI friendly port list containing all ports on device """ vlan_ports_info = json.loads(exsh.clicmd('debug cfgmgr show next maximum-rows 1 vlan.show_ports_info port=None portList=*', capture=True, xml=False)) all_ports = vlan_ports_info['data'][0]['portList'] return all_ports
def operational_slots(): """Check slot status and return list of operational slots :return: list -- operational slots """ if get_platform() == 'Summit': return ['1'] op_slots = [] dm_card_info = json.loads(exsh.clicmd('debug cfgmgr show next dm.card_info', capture=True, xml=False)) dm_card_info = dm_card_info['data'] for item in dm_card_info: if item['card_state_str'] == 'Operational' and item['slot'] not in op_slots: op_slots.append(item['slot']) return op_slots
def json_clicmd(self, cmd): # issue debug cfgmgr CLI command to EXOS and return the JSON data self.log.debug(cmd) if i_am_script is True: json_result = exsh.clicmd(cmd, capture=True) else: json_result = exec_cli([cmd], ignore_errors=True) try: json_dict = json.loads(json_result) except Exception as e: self.log.warn('JSON format error {}\n{}'.format(e, json_result)) return None # extract and return the data list return json_dict.get('data')
def get_mlag_peers(): mlagpeerRslt = json.loads(clicmd('debug cfgmgr show next vsm.mLagPeer', True)) mlag_peer = [] dup = False for peerRow in mlagpeerRslt['data']: for peer in mlag_peer: if peer['peerName'] == peerRow['peerName'] or peerRow['peerName'] == None: dup = True if dup is True: pass else: mlag_peer.append({'peerName': str(peerRow['peerName']), 'peerIpAddr': str(peerRow['peerIpAddr']), 'localIpAddr': str(peerRow['localIpAddr']), 'vlan': str(peerRow['vlan'])}) return mlag_peer
def get_mlag_peers(): mlagpeerRslt = json.loads(clicmd('debug cfgmgr show next vsm.mLagPeer', True)) mlag_peer = [] dup = False for peerRow in mlagpeerRslt['data']: for peer in mlag_peer: if peer['peerName'] == peerRow['peerName']: dup = True if dup is True: pass else: mlag_peer.append({'peerName': str(peerRow['peerName']), 'peerIpAddr': str(peerRow['peerIpAddr']), 'localIpAddr': str(peerRow['localIpAddr']), 'vlan': str(peerRow['vlan'])}) return mlag_peer
def get_mlag_ports(): mlagportRslt = json.loads(clicmd('debug cfgmgr show next vsm.mLagPort', True)) mlag_ports = [] dup = False for mportRow in mlagportRslt['data']: for peer in mlag_ports: if peer['peerName'] == mportRow['peerName'] and peer['idx'] == mportRow['idx']: dup = True if dup is True: pass else: mlag_ports.append({'peerName': str(mportRow['peerName']), 'idx': str(mportRow['idx']), 'port': str(mportRow['port']), 'localportstate': str(mportRow['lclLinkState']), 'remoteportstate': str(mportRow['rmtLinkState'])}) return mlag_ports
def cmd2data(clicmd): """ Runs an EXOS command and returns the output in json format """ re_reply = re.compile(r'<reply>.+?</reply>', re.DOTALL) xmlout = exsh.clicmd(clicmd, capture=False, xml=True) data = [] for reply in re.finditer(re_reply, xmlout): if reply: reply_xml = reply.group() root = ElementTree.fromstring(reply_xml) for message in root.iter('message'): for element in message: mdata = {} edata = {} for e in element: text = int(e.text) if e.text is not None and e.text.isdigit() else e.text edata[e.tag] = text mdata[element.tag] = edata data.append(mdata) return data
def build_report(self): hdg = [ [ '', 'In', 'Out', 'In', 'Out', 'In', 'Out', 'In', 'Out', 'In', 'Out', 'In', 'Out', 'In' ], [ 'Port', 'Octets', 'Octets', 'Ucasts', 'Ucasts', 'Mcasts', 'Mcasts', 'Bcasts', 'Bcasts', 'Discards', 'Discards', 'Errors', 'Errors', 'Unknowns' ] ] try: exsh.clicmd('show time') print exsh.clicmd('show time', True), except RuntimeError: pass rows = [] for port, port_stat in self.port_stats.items(): port_rxerr = self.port_rxerr.get(port) port_txerr = self.port_txerr.get(port) port_congestion = self.port_congestion.get(port) port_qos = self.port_qos.get(port) cols = [] # Port cols.append(port) # In Octets cols.append(port_stat.get('rxByteCnt')) # Out Octets cols.append(port_stat.get('txByteCnt')) # In Ucasts cols.append(port_stat.get('rxPktCnt')) # Out Ucasts cols.append(port_stat.get('txPktCnt')) # In Mcasts cols.append(port_stat.get('rxMcast')) # Out Mcasts cols.append(port_stat.get('txMcast')) # In Bcasts cols.append(port_stat.get('rxBcast')) # Out Bcasts cols.append(port_stat.get('txBcast')) # In Discards cnt = 0 for fld in [ "q0congPkts", "q1congPkts", "q2congPkts", "q3congPkts", "q4congPkts", "q5congPkts", "q6congPkts", "q7congPkts"]: cnt += int(port_qos.get(fld), 0) cols.append(cnt) # OutDiscards cols.append(port_congestion.get('dropPkts')) # In Errors cnt = 0 for fld in [ "rxAlign", "rxCrc", "rxFrag", "rxJabber", "rxLost", "rxOver", "rxUnder"]: cnt += int(port_rxerr.get(fld), 0) cols.append(cnt) # Out Errors cnt = 0 for fld in [ "txCollisions", "txDeferred", "txErrors", "txLateCollisions", "txLost", "txParity"]: cnt += int(port_txerr.get(fld), 0) cols.append(cnt) # In Unknowns # TODO cols.append(0) rows.append(cols) # determine the max width of data fields max_width = 0 for row in hdg: for entry in row: if len(str(entry)) > max_width: max_width = len(str(entry)) for row_entry in rows: for entry in row_entry: if len(str(entry)) > max_width: max_width = len(str(entry)) # leave room for a space max_width += 1 # print headings row = hdg[0] print_line = '' for idx in range(len(row)): if idx: print_line += '{:^{}}'.format(row[idx], max_width) else: print_line += '{:<{}}'.format(row[idx], max_width) print print_line row = hdg[1] print_line = '' for idx in range(len(row)): if idx: print_line += '{:>{}}'.format(row[idx], max_width) else: print_line += '{:<{}}'.format(row[idx], max_width) print print_line # print heading separator print_line = '' for idx in range(len(hdg[0])): if idx: print_line += ' {}'.format('-' * (max_width - 1)) else: print_line += '{} '.format('-' * (max_width - 1)) print print_line # print ports stats for row in rows: cnt = 0 print_line = '' for idx in range(len(row)): if idx: print_line += '{:>{}}'.format(row[idx], max_width) else: print_line += '{:<{}}'.format(row[idx], max_width) print print_line
def signal_handler(signal, frame): if cli_refresh and not legacy_version: # renable cli refresh, if we disabled it previously clicmd('enable cli refresh') sys.stdout.flush() sys.exit(0)
def main(): parser = ArgParser(prog='watch.py', description = "This script displays the output of a " "specified CLI command every n seconds " "Example \"run script watch.py \"show port " "packet no-ref\"\"") parser.add_argument("command", help="Command to iterate. Should be enclosed in quotes " "(i.e. \"show l2stats vlan Mgmt\")") parser.add_argument('-c', '--count', help='Number of times to issue the command (default 3)', type=int, default=3) parser.add_argument('-i', '--interval', help='Wait time between command iterations (default 5 sec)', type=int, default=5) parser.add_argument('-d', '--diff', help='If numerical values have changed in an ouput print difference between ' 'previous and current command iteration', action="store_true") args = parser.parse_args() cmd = args.command count = args.count interval = args.interval stat_diff = args.diff cli_refresh = True legacy_version = version_check() # Create and register a hanlder for SIGINT so we handle ^C cleanly def signal_handler(signal, frame): if cli_refresh and not legacy_version: # renable cli refresh, if we disabled it previously clicmd('enable cli refresh') sys.stdout.flush() sys.exit(0) signal.signal(signal.SIGINT, signal_handler) # Handle Auto-refreshing Commands if legacy_version: print 'WARNING: Switch is running pre 16.1 code. Please be sure to not use auto-refreshing commands\n' else: # Check to see if cli refresh is disabled cli_out = clicmd('show management | include "CLI refresh"', True) if 'Disabled' in cli_out: cli_refresh = False if cli_refresh: # Temporarily disable refreshing CLI commands to prevent script from hanging clicmd('disable cli refresh') if stat_diff: prev_output = try_cli(cmd) print prev_output count -=1 prev_output = prev_output.split('\n') while count != 0: sleep(interval) curr_output = try_cli(cmd).split('\n') for index in range(len(prev_output)): # Split current and prev command outputs into list divided based on numerical and non-numerical strings prev = re.split(r'(\d+)', prev_output[index]) curr = re.split(r'(\d+)', curr_output[index]) for i in range(len(prev)): if prev[i].isdigit() and curr[i] > prev[i]: diff = int(curr[i]) - int(prev[i]) diff = '+' + str(diff) FMT = '{0:>' + str(len(curr[i])) + '}' sys.stdout.write(FMT.format(diff)) else: sys.stdout.write(prev[i]) sys.stdout.flush() print count -= 1 prev_output = curr_output else: for i in range(count): print try_cli(cmd) sleep(interval) if cli_refresh and not legacy_version: # Restore CLI refresh clicmd('enable cli refresh')
def main(): parser = ArgParser(prog='conf_diff.py', description='Compare the saved configuration with the currently running one.') parser.add_argument('-d', '--debug', help='Enables verbose logging and leaves temp files for debugging', action='store_true') parser.add_argument('-c', '--clean', help='Remove previous debug files. Executes "rm temp_*; rm *.temp"', action='store_true') args = parser.parse_args() debug = args.debug clean = args.clean if clean: print "DEBUG: Cleaning up previous debug files" clicmd("rm temp_*") clicmd("rm *.temp") print "Comparing configurations, please wait..." #create unique names for temp files t_stamp = str(time()) if debug: print "DEBUG: Creating temp files" saved_name = '/usr/local/cfg/saved_{0}.temp'.format(t_stamp[:-3]) running_name = '/usr/local/cfg/running_{0}.temp'.format(t_stamp[:-3]) temp_config = 'temp_{0}'.format(t_stamp[:-3]) saved_file = open(saved_name, 'w') running_file = open(running_name, 'w') # find the selected config file if debug: print "DEBUG: Finding selected config" output = clicmd('show switch | include "Config Selected"', True).split() selected_config = output[2] selected_config = selected_config[:-4] # save the running config to a temp file, # then convert both config files from XML to human-readable format if debug: print "DEBUG: Generating temp version of running config" clicmd("save config {0}".format(temp_config)) if debug: print "DEBUG: Generating temp cfgmgr version of selected config" saved_file.write(clicmd("debug cfgmgr show configuration file {0}".format(selected_config), True)) if debug: print "DEBUG: Generating temp cfgmgr version of running config" running_file.write(clicmd("debug cfgmgr show configuration file {0}".format(temp_config), True)) # set the selected config back, since the save config changed it clicmd("use config {0}".format(selected_config), False) # close the files, and reopen them for reading saved_file.close() running_file.close() saved_file = open(saved_name, 'r') running_file = open(running_name, 'r') # diff the two configs if debug: print "DEBUG: Diffing configs" d = Differ() diff = list(d.compare(saved_file.readlines(), running_file.readlines())) # print the results of the diff print " " print "If line starts with \'+\', the command has been added since last save." print "If line starts with \'-\', the command was present in the last save, and has been deleted." print " " print "Config changes:" for line in diff: if line.startswith('+ ') or line.startswith('- '): print line[:-1] print "Note that this script has cleared the CLI dirty bit. The configuration has not been saved." # clean up saved_file.close() running_file.close() # remove files that were opened if not debug: clicmd("rm {0}".format(saved_name)) clicmd("rm {0}".format(running_name)) clicmd("rm {0}.cfg".format(temp_config))
import sys import exsh do_list = [ 'create vlan 10-20', 'config vlan 10-20 add ports all tagged', ] show_list = [ 'show vid', 'show ports', 'show ports vid', 'show ports info', 'show ports config no', 'show ports statistics no', ] # just print any command line args to show they showed up print sys.argv # stuff to do for cmd in do_list: print '\n',cmd exsh.clicmd(cmd) # stuff to show for cmd in show_list: print '\n',cmd print exsh.clicmd(cmd,capture=True)
def main(): print FMT_H1.format("Checking MLAG Configuration and Status") # Check to see if MLAG is configured vsm_config = len(clicmd('show configuration vsm', True).splitlines()) if vsm_config <= 3: print FMT_ERROR.format('MLAG Not Configured') exit() # Check software version, 15.6 must run legacy MLAG check script pimage = True sh_switch = clicmd('show switch', True) ver = '' if 'Image Selected: secondary' in sh_switch: pimage = False sh_switch = sh_switch.splitlines() for line in sh_switch: if (pimage and ('Primary ver:' in line)) or (not pimage and ('Secondary ver:' in line)): ver = line.split(':') ver = ver[1].strip() if ver == '': print FMT_ERROR.format('Problem detecting software version') exit() elif ver.startswith('15.6'): print('Switch running EXOS 15.6, executing legacy script, multi-peer not supported.') legacy_mlag_check() else: peer_info = get_mlag_peers() mports = get_mlag_ports() sharing = json.loads(clicmd('debug cfgmgr show next vlan.ls_ports_show', capture=True)) sharing = sharing['data'] lag_ports = [] for port in sharing: lag_ports.append(port['port']) for index, peer in enumerate(peer_info): perror = False # Get Peer Name pname = peer['peerName'] print FMT_H1.format('Checking MLAG Peer "{0}"'.format(pname)) # Get ISC VLAN isc_vlan = peer['vlan'] isc_port = '' # Check to see if MLAG peer is not configured if isc_vlan == 'None': print FMT_H2.format(FMT_CFG.format('Peer "{0}" is not properly configured, ISC VLAN configuration not found'.format(pname))) perror = True continue # Check the number of ports added to the ISC vlan, and get the port number of the ISC link port_check = get_vlan_ports(isc_vlan) plist = ['-', ','] # Catch 1 tagged and 1 untagged port added to ISC if port_check['untagged'] != 'None' and port_check['tagged'] != 'None': print FMT_H2.format(FMT_CFG.format('ISC vlan "{0}" for peer {1} has more than one port added, please resolve'.format(isc_vlan, pname))) perror = True continue # Check if NO ports are added to ISC elif port_check['untagged'] == 'None' and port_check['tagged'] == 'None': print FMT_H2.format(FMT_CFG.format('No port added to ISC vlan "{0}" for peer {1}, please resolve'.format(isc_vlan, pname))) perror = True continue # Check if untagged or tagged fields contain port list, meaning multiple ports are added elif any(s in port_check['untagged'] for s in plist) or any(s in port_check['tagged'] for s in plist): print FMT_H2.format(FMT_CFG.format('ISC vlan "{0}" for peer {1} has more than one port added, please resolve'.format(isc_vlan, pname))) perror = True continue elif port_check['untagged'] == 'None': isc_port = port_check['tagged'] elif port_check['tagged'] == 'None': isc_port = port_check['untagged'] if isc_port == '': FMT_ERROR.format('Problem detecting ISC port for peer {0}'.format(pname)) perror = True continue # Create a list of the vlans that exist on the ISC port isc_vlans = get_port_vlan_list(isc_port) # Now we can iterate through MLAG ports, and check if the vlans on them are # on the ISC port. If not, an error will be written to the CLI. missing_vlans = [] mlag_ports = [] mport_vids = [] # Create a list 'mlag_ports' that contains all MLAG ports for the peer for port in mports: if port['peerName'] == pname: mlag_ports.append(port['port']) # Create a list of all VLANs on all MLAG ports for the peer for port in mlag_ports: vlan_list = get_port_vlan_list(port) for vid in vlan_list: if vid not in mport_vids: mport_vids.append(vid) # Check ISC and MLAG Port status # Check ISC if isc_port in lag_ports: for port in sharing: if port['loadShareMaster'] == isc_port: if port['linkState'] == '0': print FMT_CFG.format( 'Port {0}, a LAG member of the ISC for peer {1}, is down. Please resolve.'.format( port['port'], pname)) perror = True elif port['agg_membership'] == '0' and port['linkState'] == '1': print FMT_CFG.format( 'Port {0}, a LAG member of the ISC for peer {1} is not added to the aggregator. Please resolve.'.format( port['port'], pname)) perror = True else: print FMT_CFG.format( 'ISC for {0} is not a LAG. It is recommended that all ISC connections use link aggregation'.format( pname)) perror = True if not port_active(isc_port): print FMT_CFG.format( 'ISC port {0} for Peer {1} not active. Please resolve.'.format(isc_port, pname)) perror = True # Check MLAG Ports for port in mlag_ports: if port in lag_ports: for lag_port in sharing: if lag_port['loadShareMaster'] == port: if lag_port['linkState'] == '0': print FMT_CFG.format( 'MLAG port {0} for peer {1} is down. Please resolve.'.format( lag_port['port'], pname)) perror = True elif lag_port['agg_membership'] == '0' and lag_port['linkState'] == '1': print FMT_CFG.format( 'MLAG port {0} for peer {1} is not added to the aggregator. Please resolve.'.format( lag_port['port'], pname)) perror = True else: if not port_active(port): print FMT_CFG.format( 'MLAG Port {0} for Peer {1} is not active. Please resolve.'.format(port, pname)) perror = True # Check to see if MLAG port VLANs are missing from ISC and add the missing vlans to a list for vid in mport_vids: if vid not in isc_vlans: missing_vlans.append(vid) print FMT_H2.format(FMT_CFG.format('VLAN {0} is found on an MLAG port but not added to ISC port {1}'.format (vid, isc_port))) perror = True # If vlans are missing, ask the user if they woud like to resolve if missing_vlans != [] and yes_no_input(">> Would you like to add the missing vlans to the ISC? (y/n)"): for vlan in missing_vlans: print('Adding missing VLANS..') clicmd('configure vlan {0} add port {1} tagged'.format(vlan, isc_port)) ## Check local and remote checksums to determine if FDB and VLANs match for count in range(0, 3): checksums = clicmd('debug fdb show globals | include LclCkhsum:', True) checksums = checksums.split() if index == 0: local = checksums[2] remote = checksums[4] elif index == 1: local = checksums[7] remote = checksums[9] else: print FMT_ERROR.format('Checksum check failed.') exit() # print local # print remote if local == remote: # print FMT_H2.format('Local and remote FDB checksums match.') break if local != remote: print FMT_CFG.format('Local and remote FDB checksums do not match. Please check config on the other MLAG peer.') print clicmd('debug fdb show globals', True) perror = True if not perror: print FMT_H2.format('No problems found on peer "{0}"'.format(pname)) print '\n>> MLAG config check completed.\n'
ports_result.append(status['status']) if 'ERROR' in ports_result: return False else: return True except RuntimeError as cmdMsg: print 'Error:', cmdMsg, ':', cmd exsh.clicmd('create log message "flow_mod.py: Error: cmd={0} : msg={1}"'.format(cmd, cmdMsg), capture=False) return False if port_check(ports) == True: FORMAT = '{prt:<8.8} {vlanType}:{tagged}' print FORMAT.format(prt='Port', vlanType='untagged', tagged='tagged') cmd2 = 'debug cfgmgr show next vlan.show_ports_info portList={0} port=None'.format(ports) portRslt = exsh.clicmd(cmd2, capture=True) portDict = json.loads(portRslt) index = -1 for row in portDict['data']: index = (index + 1) port = row['port'] vlanRslt = json.loads(exsh.clicmd( 'debug cfgmgr show next vlan.show_ports_info_detail_vlans formatted port={0} vlanIfInstance=None'.format(port), True)) taggedVlan = [] untaggedVlan = [] for vlanRow in vlanRslt['data']: vid = vlanRow.get('vlanId', None) if vid: if vlanRow['tagStatus'] == '1': taggedVlan.append(vid) else:
def main(): print "Comparing configurations, please wait..." #create unique names for temp files t_stamp = str(time()) saved_name = '/usr/local/cfg/saved_{0}.temp'.format(t_stamp[:-3]) running_name = '/usr/local/cfg/running_{0}.temp'.format(t_stamp[:-3]) temp_config = 'temp_{0}'.format(t_stamp[:-3]) saved_file = open(saved_name, 'w') running_file = open(running_name, 'w') # find the selected config file output = clicmd('show switch | include "Config Selected"', True).split() selected_config = output[2] selected_config = selected_config[:-4] # save the running config to a temp file, # then convert both config files from XML to human-readable format clicmd("save config {0}".format(temp_config)) saved_file.write(clicmd("debug cfgmgr show configuration file {0}".format(selected_config), True)) running_file.write(clicmd("debug cfgmgr show configuration file {0}".format(temp_config), True)) # set the selected config back, since the save config changed it clicmd("use config {0}".format(selected_config), False) # close the files, and reopen them for reading saved_file.close() running_file.close() saved_file = open(saved_name, 'r') running_file = open(running_name, 'r') # diff the two configs d = Differ() diff = list(d.compare(saved_file.readlines(), running_file.readlines())) # print the results of the diff print " " print "If line starts with \'+\', the command has been added since last save." print "If line starts with \'-\', the command was present in the last save, and has been deleted." print " " print "Config changes:" for line in diff: if line.startswith('+ ') or line.startswith('- '): print line[:-1] print "Note that this script has cleared the CLI dirty bit. The configuration has not been saved." # clean up saved_file.close() running_file.close() # remove files that were opened clicmd("rm {0}".format(saved_name)) clicmd("rm {0}".format(running_name)) clicmd("rm {0}.cfg".format(temp_config))
def legacy_mlag_check(): # Find which vlan is the ISC vlan cli_output = clicmd('debug vsm show peer | inc "vrId :"', True).split() isc_vlan = cli_output[5] peer_name = clicmd('debug vsm show peer | include "Name : "', True).split() #Checkes to see if MLAG peer is not configured if cli_output[5] == 'Unknown': print ("Tool does not support this configuration") exit() else: print print ("****mlag_config_check.py running on MLAG Peer {0}****").format(peer_name[6]) print # Check the number of ports added to the ISC vlan, and get the port number of the ISC link cli_output = clicmd('show vlan ' + isc_vlan, True).split() index = cli_output.index('Ports:') index = index + 1 # +1, since we found the item before the number of ports num_ports = cli_output[index] # Remove the trailing period from that output if num_ports.endswith('.'): num_ports = int(num_ports[:-1]) #Check the number of ports added to the ISC vlan if num_ports > 1: print 'Multiple ports are added to the ISC vlan (' + isc_vlan + '). Please correct.' return elif num_ports == 0: print 'No ports are added to the ISC vlan (' + isc_vlan + '). Please correct.' return # At this point, we can assume that there is one port added to the ISC vlan, # and continue checking the MLAG configuration. # Determine what the port number of the ISC is if 'Tag:' in cli_output: index = cli_output.index('Tag:') index = index + 1 isc_port = cli_output[index] elif 'Untag:' in cli_output: index = cli_output.index('Untag:') index = index + 1 isc_port = cli_output[index] else: print FMT_ERROR.format('An error occurred. Unable to determine ISC port') return # Remove the flags around the port number if isc_port.endswith('g'): isc_port = isc_port[:-1] elif isc_port.endswith('G'): print ('The ISC port is also configured as an MLAG port. Please correct.') return if isc_port.startswith('*'): isc_port = isc_port[1:] elif isc_port.startswith('!'): isc_port = isc_port[1:] print 'The ISC port (' + isc_port + ') is disabled. Please correct.' # Create a list of the vlans that exist on the ISC port cli_output = clicmd('show port ' + isc_port + ' info detail', True).split() vlan_on_next_iteration = False isc_port_vlans = list() for i in cli_output: if vlan_on_next_iteration: #remove a trailing comma, if present if i.endswith(','): vlan = i[:-1] else: vlan = i isc_port_vlans.append(vlan) if i == 'Name:': vlan_on_next_iteration = True else : vlan_on_next_iteration = False # Now, isc_port_vlans contains all the vlans on the ISC port. # Now we can iterate through MLAG ports, and check if the vlans on them are # on the ISC port. If not, an error will be written to the CLI. cli_output = clicmd('show config vsm', True) lines = cli_output.split('\n') #remove an empty string that breaks the for loop below lines = lines[:-1] #create an empty list to be used in the loop mlag_ports = list() for l in lines: line = l.split() if line[0] == 'enable': mlag_ports.append(line[3]) for p in mlag_ports: cli_output = clicmd('show port ' + p + ' info detail', True).split() vlan_on_next_iteration = False port_vlans = list() for i in cli_output: if vlan_on_next_iteration: #remove a trailing comma, if present if i.endswith(','): vlan = i[:-1] else: vlan = i if vlan not in isc_port_vlans: print 'Vlan ' + vlan + ' is not added to the ISC port (' + isc_port + '), and is found on MLAG port ' + p + '. Please correct.' if i == 'Name:': vlan_on_next_iteration = True else : vlan_on_next_iteration = False ## Check local and remote checksums to determine if FDB and VLANs match for count in range(0,3): checksums = clicmd('debug fdb show globals | include LclCkhsum:', True) checksums = checksums.split() local = checksums[2] remote = checksums[4] #print local #print remote if local == remote: print ('Local and remote FDB checksums match.') break if local != remote: print 'Local and remote FDB checksums do not match. Please check config on the other MLAG peer.' print clicmd('debug fdb show globals', True)
def get_vlan_ports(vlan): vlanportsRslt = json.loads(clicmd('debug cfgmgr show one vlan.vlanPort vlanName={0}'.format(vlan), True)) return ({'untagged' : str(vlanportsRslt['data'][0]['untaggedPorts']), 'tagged' : str(vlanportsRslt['data'][0]['taggedPorts'])})
def main(): print FMT_H1.format("Checking MLAG Configuration and Status") # Check to see if MLAG is configured vsm_config = len(clicmd('show configuration vsm', True).splitlines()) if vsm_config <= 3: print FMT_ERROR.format('MLAG Not Configured') exit() # Check software version, 15.6 must run legacy MLAG check script pimage = True sh_switch = clicmd('show switch', True) ver = '' if 'Image Selected: secondary' in sh_switch: pimage = False sh_switch = sh_switch.splitlines() for line in sh_switch: if (pimage and ('Primary ver:' in line)) or (not pimage and ('Secondary ver:' in line)): ver = line.split(':') ver = ver[1].strip() if ver == '': print FMT_ERROR.format('Problem detecting software version') exit() elif ver.startswith('15.6'): print('Switch running EXOS 15.6, executing legacy script, multi-peer not supported.') legacy_mlag_check() else: peer_info = get_mlag_peers() mports = get_mlag_ports() sharing = json.loads(clicmd('debug cfgmgr show next vlan.ls_ports_show', capture=True)) sharing = sharing['data'] lag_ports = [] for port in sharing: lag_ports.append(port['port']) for index, peer in enumerate(peer_info): perror = False # Get Peer Name pname = peer['peerName'] print FMT_H1.format('Checking MLAG Peer "{0}"'.format(pname)) # Get ISC VLAN isc_vlan = peer['vlan'] isc_port = '' # Check to see if MLAG peer is not configured if isc_vlan == 'None': print FMT_H2.format(FMT_CFG.format('Peer "{0}" is not properly configured, ISC VLAN configuration not found'.format(pname))) perror = True continue # Check the number of ports added to the ISC vlan, and get the port number of the ISC link port_check = get_vlan_ports(isc_vlan) plist = ['-', ','] # Catch 1 tagged and 1 untagged port added to ISC if port_check['untagged'] != 'None' and port_check['tagged'] != 'None': print FMT_H2.format(FMT_CFG.format('ISC vlan "{0}" for peer {1} has more than one port added, please resolve'.format(isc_vlan, pname))) perror = True continue # Check if NO ports are added to ISC elif port_check['untagged'] == 'None' and port_check['tagged'] == 'None': print FMT_H2.format(FMT_CFG.format('No port added to ISC vlan "{0}" for peer {1}, please resolve'.format(isc_vlan, pname))) perror = True continue # Check if untagged or tagged fields contain port list, meaning multiple ports are added elif any(s in port_check['untagged'] for s in plist) or any(s in port_check['tagged'] for s in plist): print FMT_H2.format(FMT_CFG.format('ISC vlan "{0}" for peer {1} has more than one port added, please resolve'.format(isc_vlan, pname))) perror = True continue elif port_check['untagged'] == 'None': isc_port = port_check['tagged'] elif port_check['tagged'] == 'None': isc_port = port_check['untagged'] if isc_port == '': FMT_ERROR.format('Problem detecting ISC port for peer {0}'.format(pname)) perror = True continue # Create a list of the vlans that exist on the ISC port isc_vlans = get_port_vlan_list(isc_port) # Now we can iterate through MLAG ports, and check if the vlans on them are # on the ISC port. If not, an error will be written to the CLI. missing_vlans = [] mlag_ports = [] mport_vids = [] # Create a list 'mlag_ports' that contains all MLAG ports for the peer for port in mports: if port['peerName'] == pname: mlag_ports.append(port['port']) # Create a list of all VLANs on all MLAG ports for the peer for port in mlag_ports: vlan_list = get_port_vlan_list(port) if vlan_list == ['None']: print FMT_CFG_WRN.format('No VLANs added to MLAG Port {0}'.format(port)) continue for vid in vlan_list: if vid not in mport_vids: mport_vids.append(vid) # Check ISC and MLAG Port status # Check ISC if isc_port in lag_ports: for port in sharing: if port['loadShareMaster'] == isc_port: if port['linkState'] == '0': print FMT_CFG.format( 'Port {0}, a LAG member of the ISC for peer {1}, is down. Please resolve.'.format( port['port'], pname)) perror = True elif port['agg_membership'] == '0' and port['linkState'] == '1': print FMT_CFG.format( 'Port {0}, a LAG member of the ISC for peer {1} is not added to the aggregator. Please resolve.'.format( port['port'], pname)) perror = True else: print FMT_CFG.format( 'ISC for {0} is not a LAG. It is recommended that all ISC connections use link aggregation'.format( pname)) perror = True if not port_active(isc_port): print FMT_CFG.format( 'ISC port {0} for Peer {1} not active. Please resolve.'.format(isc_port, pname)) perror = True # Check MLAG Ports for port in mlag_ports: if port in lag_ports: for lag_port in sharing: if lag_port['loadShareMaster'] == port: if lag_port['linkState'] == '0': print FMT_CFG.format( 'MLAG port {0} for peer {1} is down. Please resolve.'.format( lag_port['port'], pname)) perror = True elif lag_port['agg_membership'] == '0' and lag_port['linkState'] == '1': print FMT_CFG.format( 'MLAG port {0} for peer {1} is not added to the aggregator. Please resolve.'.format( lag_port['port'], pname)) perror = True else: if not port_active(port): print FMT_CFG.format( 'MLAG Port {0} for Peer {1} is not active. Please resolve.'.format(port, pname)) perror = True # Check to see if MLAG port VLANs are missing from ISC and add the missing vlans to a list for vid in mport_vids: if vid not in isc_vlans: missing_vlans.append(vid) print FMT_H2.format(FMT_CFG.format('VLAN {0} is found on an MLAG port but not added to ISC port {1}'.format (vid, isc_port))) perror = True # If vlans are missing, ask the user if they woud like to resolve if missing_vlans != [] and yes_no_input(">> Would you like to add the missing vlans to the ISC? (y/n)"): for vlan in missing_vlans: print('Adding missing VLANS..') clicmd('configure vlan {0} add port {1} tagged'.format(vlan, isc_port)) ## Check local and remote checksums to determine if FDB and VLANs match for count in range(0, 3): checksums = clicmd('debug fdb show globals | include LclC[kh][kh]sum:', True) checksums = checksums.split() if index == 0: local = checksums[2] remote = checksums[4] elif index == 1: local = checksums[7] remote = checksums[9] else: print FMT_ERROR.format('Checksum check failed.') exit() # print local # print remote if local == remote: # print FMT_H2.format('Local and remote FDB checksums match.') break if local != remote: print FMT_CFG.format('Local and remote FDB checksums do not match. Please check config on the other MLAG peer.') print clicmd('debug fdb show globals', True) perror = True if not perror: print FMT_H2.format('No problems found on peer "{0}"'.format(pname)) print '\n>> MLAG config check completed.\n'
def main(): parser = ArgParser( prog='dhcp43.py', description= "This script will generate the hex needed to configure EXOS's built-in DHCP server with option 43 for ZTP. " "It will also either provide the command to use, or configure the option on the specified VLAN.", usage="%(prog)s [-h] [-s SERVER_ADDRESS] [-v VLAN_NAME] files") parser.add_argument( '-s', '--server-address', help= 'IP Address of TFTP server for sub-option 100. May be omitted if a URL is used for sub-option 101.', type=str, default="") parser.add_argument( '-v', '--vlan-name', help= 'VLAN to configure option 43 on. If this is included, the option 43 config will be added to the DHCP ' 'server configuration on this switch for this VLAN. If not, the config command will simply be printed.', type=str, default="<vlan_name>") parser.add_argument( 'files', help= 'File(s) to be downloaded. If the \'-s\' option is used, this may be simply be a file name. ' 'If multiple files are given, they should be separated by spaces. ' 'If the \'-s\' option is not used, this should be a full URL. (IE, tftp://192.168.1.10/config.xsf)', type=str, nargs='+') args = parser.parse_args() vlan = args.vlan_name server = args.server_address files = args.files # Convert the IP address to hex, if it exists hex = [] if len(server): ip = server.split('.') hex.append(binascii.hexlify(chr(100))) #sub-option 100 hex.append(binascii.hexlify(chr(4))) #length = 4 bytes for i in ip: #convert each byte of the IP to hex hex.append(binascii.hexlify(chr(int(i)))) # Convert the filenames/URLs to hex for i in files: hex.append(binascii.hexlify(chr(101))) #sub-option 101 hex.append(binascii.hexlify(chr( len(i)))) #length of filename/URL in bytes hex.append(binascii.hexlify(i)) #filename converted to hex #Generate the command needed to configure this: hex = ''.join(hex) #join all the hex into one string hex = ':'.join(hex[i:i + 2] for i in range(0, len( hex), 2)) #delimit the bytes with ':', like EXOS expects #Create the command cmd = 'configure vlan {0} dhcp-options code 43 hex {1}'.format(vlan, hex) #execute it if running on EXOS and a VLAN name was given, otherwise print it if env_is_exos and vlan is not "<vlan_name>": clicmd(cmd) else: print cmd
def try_cli(command): """Try CLI command and exit if invalid""" try: return clicmd(command, True) except: exit()
def get_port_vlan_list(port): vlanRslt = json.loads(clicmd('debug cfgmgr show next vlan.show_ports_info_detail_vlans port={0} vlanIfInstance=None'.format(port), True)) port_data = [] for vlanRow in vlanRslt['data']: port_data.append(str(vlanRow['vlanName'])) return port_data
def legacy_mlag_check(): # Find which vlan is the ISC vlan cli_output = clicmd('debug vsm show peer | inc "vrId :"', True).split() isc_vlan = cli_output[5] peer_name = clicmd('debug vsm show peer | include "Name : "', True).split() #Checkes to see if MLAG peer is not configured if cli_output[5] == 'Unknown': print ("Tool does not support this configuration") exit() else: print print ("****mlag_config_check.py running on MLAG Peer {0}****").format(peer_name[6]) print # Check the number of ports added to the ISC vlan, and get the port number of the ISC link cli_output = clicmd('show vlan ' + isc_vlan, True).split() index = cli_output.index('Ports:') index = index + 1 # +1, since we found the item before the number of ports num_ports = cli_output[index] # Remove the trailing period from that output if num_ports.endswith('.'): num_ports = int(num_ports[:-1]) #Check the number of ports added to the ISC vlan if num_ports > 1: print 'Multiple ports are added to the ISC vlan (' + isc_vlan + '). Please correct.' return elif num_ports == 0: print 'No ports are added to the ISC vlan (' + isc_vlan + '). Please correct.' return # At this point, we can assume that there is one port added to the ISC vlan, # and continue checking the MLAG configuration. # Determine what the port number of the ISC is if 'Tag:' in cli_output: index = cli_output.index('Tag:') index = index + 1 isc_port = cli_output[index] elif 'Untag:' in cli_output: index = cli_output.index('Untag:') index = index + 1 isc_port = cli_output[index] else: print FMT_ERROR.format('An error occurred. Unable to determine ISC port') return # if there is a no display string, disp_string_index will be -1. Otherwise, strip everyting after the first paren around the display string if disp_string_index != -1: isc_port = isc_port[:disp_string_index] # Remove the flags around the port number if isc_port.endswith('g'): isc_port = isc_port[:-1] elif isc_port.endswith('G'): print ('The ISC port is also configured as an MLAG port. Please correct.') return if isc_port.startswith('*'): isc_port = isc_port[1:] elif isc_port.startswith('!'): isc_port = isc_port[1:] print 'The ISC port (' + isc_port + ') is disabled. Please correct.' # Create a list of the vlans that exist on the ISC port cli_output = clicmd('show port ' + isc_port + ' info detail', True).split() vlan_on_next_iteration = False isc_port_vlans = list() for i in cli_output: if vlan_on_next_iteration: #remove a trailing comma, if present if i.endswith(','): vlan = i[:-1] else: vlan = i isc_port_vlans.append(vlan) if i == 'Name:': vlan_on_next_iteration = True else : vlan_on_next_iteration = False # Now, isc_port_vlans contains all the vlans on the ISC port. # Now we can iterate through MLAG ports, and check if the vlans on them are # on the ISC port. If not, an error will be written to the CLI. cli_output = clicmd('show config vsm', True) lines = cli_output.split('\n') #remove an empty string that breaks the for loop below lines = lines[:-1] #create an empty list to be used in the loop mlag_ports = list() for l in lines: line = l.split() if line[0] == 'enable': mlag_ports.append(line[3]) for p in mlag_ports: cli_output = clicmd('show port ' + p + ' info detail', True).split() vlan_on_next_iteration = False port_vlans = list() for i in cli_output: if vlan_on_next_iteration: #remove a trailing comma, if present if i.endswith(','): vlan = i[:-1] else: vlan = i if vlan not in isc_port_vlans: print 'Vlan ' + vlan + ' is not added to the ISC port (' + isc_port + '), and is found on MLAG port ' + p + '. Please correct.' if i == 'Name:': vlan_on_next_iteration = True else : vlan_on_next_iteration = False ## Check local and remote checksums to determine if FDB and VLANs match for count in range(0,3): checksums = clicmd('debug fdb show globals | include LclC[kh][kh]sum:', True) checksums = checksums.split() local = checksums[2] remote = checksums[4] #print local #print remote if local == remote: print ('Local and remote FDB checksums match.') break if local != remote: print 'Local and remote FDB checksums do not match. Please check config on the other MLAG peer.' print clicmd('debug fdb show globals', True)
# watch.py # This script displays the output of a specified CLI command every n seconds # # Usage: run script watch.py <seconds> <cli_cmd> # seconds: delay between commands in seconds # cli_cmd: CLI command to be watched # # Note: CLI commands will need to be enclosed in quotes # # Last updated: August 25, 2015 from exsh import clicmd from time import sleep import sys if(len(sys.argv) == 3): command = sys.argv[2] time = int(sys.argv[1]) while(True): print clicmd(command, True) sleep(time) else: print "Error: Incorrect number of arguments" print "Usage: run script watch.py <seconds> <cli_cmd>" print " seconds: time between commands in seconds" print " cli_cmd: CLI command to be watched" print "Note: CLI commands will need to be enclosed in quotes"