def main(): args = setup_steps() ip = args.host interface = args.interface cost = args.cost state = add_cost_workflow(ip, interface, cost, "CLI") print_error("finished add cost workflow")
def verify_arguments(arguments): """ Author - Jonathan Steward Function - asks user for verification before carrying out any external calls Inputs - argparse object returns - bool - determines the state of if the arguments """ confirm_statement = """ Please confirm the following settings: Adding to lag?: {addremove} Device: {ip} Interface: {int} Agg port: {ae} If you are adding an interface to a group, please ensure the group port exists """ print confirm_statement.format(addremove=arguments.activate, ip=arguments.ip, int=arguments.interface, ae=arguments.ae_int) confirmed = "" while confirmed != "y": confirmed = raw_input("y/n:") confirmed = confirmed.lower() if confirmed == "n": print_error("quitting due to user inputs") return False elif confirmed == "y": user = getpass.getuser() print "user {} confirmed".format(user) else: print_error("please a single y or n") return True
def interface_down_check(message, ip): """ Author - Jonathan Steward Function - workflow function for calling the relevent checks and then automation Inputs - message - string - syslog message ip - string - ip address of sending device returns - bool - state of if it matched the regex string - the issue with the message, if matched this will detail the ip address of device and the ip of the device with the interface down. """ state, int_down = message_check(message) if not state: #print_error("The following message didn't match the regex needed so no interface went physically down\n {}".format(message)) return (False, "", False) print_error(message) issue = "{} interface on {} is down".format(int_down, ip) state, device = device_config_info_lookup(ip) if not state: # no data/too much data. return (True, issue, False) return_message, acted = process_down(int_down, device) issue = "{} {}".format(issue, return_message) return True, issue, acted
def identify_device_RID_from_int_ip(ip): """ Author - Jonathan Steward Function - finds the device_id based on interface ip Inputs - String - Ip address of interface returns - int - ID of related device """ command = """ SELECT device_id from `FYP Data`.interfaces WHERE ip_address = '{}';""".format(ip) result = get_data(command) print "device_id for {} ip is {}".format(ip, result) if not result: print_error("something wrong getting device information") return (False, "") if len(result) > 1: print_error("more than one device record, can't carry out automation") # email admin return (False, "") result = result[0][0] print "device id is {}".format(result) command = """ SELECT ip from `FYP Data`.device_table WHERE device_id = '{}';""".format(result) result = get_data(command) print "device RID is {}".format(result[0][0]) return result[0][0]
def main(): arguments = setup_steps() if not arguments: print_error("Invalid arguments") return state, device = device_config_info_lookup(arguments.ip) # device vendor,community,username,loginpassword,enpassword if not state: return if device.vendor == "cisco": arguments.ae_int = "{}{}".format("Port-channel", arguments.ae_int) elif device.vendor == "juniper": arguments.ae_int = "{}{}".format("ae", arguments.ae_int) else: print_error("The vendor '{}' isn't valid please re-try".format( arguments.vendor)) return state = verify_arguments(arguments) if state: process_lag_change(arguments.activate, arguments.ip, device.username, device.password, device.vendor, arguments.interface, arguments.ae_int, device.community, device.enablePassword)
def find_ae_int_ref(ip, ae_int, interface, community, activate): """ Author - Jonathan Steward Function - identify the lag and interface ifindex and all interfaces Inputs - ip - string ae_int - string interface - string community - string returns - bool - state of if interface and lag found int - ae_index int - interface_index list - device_interfaces """ interface_unit = interface + ".0" device_interfaces = Grab_device_interfaces_snmp(ip, community) ae_index = "" interface_index_unit = "" interface_index = "" print "checking for ae {}".format(ae_int) for inter in device_interfaces: if ae_int: if str(inter.value) == str(ae_int): ae_index = inter.oid_index print "found matching AE index from list of interfaces" print ae_index continue if str(inter.value) == str(interface_unit): interface_index_unit = inter.oid_index print "found interface_unit index" print interface_index_unit continue if str(inter.value) == str(interface): interface_index = inter.oid_index print "found interface index" print interface_index continue if not interface_index: print_error( "requested interface {} not found at all, please re-check".format( interface)) return False, "", "", "" if interface_index_unit: interface_index = interface_index_unit if not ae_index: print_error("{} not found on device".format(ae_int)) if activate: return False, "bad", "", "" return True, ae_index, interface_index, device_interfaces
def parse(message): """ Author - Jonathan Steward Function - Function called from the monitor calls all other functions. Inputs - message - string """ print "recieved message:\n {}".format(message) device_RID, issue, acted = parse_message(message) print_error("{}, {}\n Was it acted on: {}".format(device_RID, issue, acted)) record_actions(device_RID, message, issue, acted)
def change_int_lag_state_cisco(addornot, interface, device_details, ae_int): """ Author - Jonathan Steward Function - Configure cisco device to either add or remove interface from group Inputs - addornot - bool interface - string device_details - object ae_int - int returns - bool - state of if the config was applied or not. """ if not ae_int: pass else: ae_int_number = ae_int.split("Port-channel")[1] connection = ssh_connection(device_details) if not connection: return False command = ("\nen\n{}\nconfig t\n\n\n\n\n".format( device_details.enablePassword)) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "#" not in output: print_error( "password was wrong!, see below for the issue:\n{}".format(output)) return False print output if addornot: lagcommand = "\ninterface {}\n channel-group {} mode active\n".format( interface, ae_int_number) else: lagcommand = "\ninterface {}\nno channel-group\n".format(interface) connection.send(lagcommand) time.sleep(1) output = connection.recv(8000) if "% Invalid arguments detected" in output: print_error("something went wrong, see below:{}".format(output)) print "applied config as seen below:\n{}".format(output) command = "\nend\ncopy run start\n" connection.send(command) time.sleep(1) return True
def Juniper_config(configuration, device_object, config_format='xml'): """ Author - Jonathan Steward Function - use device connection object and connect to load configuration Inputs - configuration - string of what configuration you want to apply device_object - device object containing all the device config_format - the format of the configuration, default is xml but can also be set commands returns - bool - state of if the config operation worked or not. """ device_con = Juniper_connect(device_object) if not device_con: return False try: with Config(device_con, mode='private') as connection: print "{}: connected, loading".format( time.strftime('%Y-%m-%d %H:%M:%S')) try: connection.load(configuration, format=config_format, overwrite=True) except ConfigLoadError as error: print_error( "there was an issue loading configuration:\n{}".format( error)) return False except XMLSyntaxError as error: print_error("there was a syntax error:\n{}".format(error)) return False except: print_error("Something went wrong".format(error)) return False print "{}: loaded, commiting the following change:".format( time.strftime('%Y-%m-%d %H:%M:%S')) diff = connection.pdiff() print diff try: connection.commit( comment='Adding description via api with xml file') except CommitError as error: print_error( "There was an issue with the commit!{}".format(error)) return False print "{}: commit complete".format( time.strftime('%Y-%m-%d %H:%M:%S')) device_con.close() except: print_error("Something went wrong applying config") return True
def check_success(activate, int_state, interface, ae_int): """ Author - Jonathan Steward Function - Simple function to check if an interface was added into lag and output to user/logs Inputs - activate - bool int_state - bool interface - string ae_int - int """ if activate: if int_state: # trying to add and also in lag # success print_error("{} was added to {}".format(interface, ae_int)) else: # trying to add but not in lag # fail print_error( "{} was not added to {} for some reason, might be down other end" .format(interface, ae_int)) else: if int_state: # Trying to remove and in lag # fail print_error("{} was not removed from {} for some reason".format( interface, ae_int)) else: print_error("{} was removed from lag {}".format(interface, ae_int))
def poll_traffic(device_interfaces, device_ip, community): """ Author - Jonathan Steward Function - Polls Device for interface counter and then calls traffic automation for loops Inputs - device_interfaces - list - list of interface objects from snmp gets with database info device_ip - string - ip address of host with high utilization community - string - community string needed for SNMP returns - n/a """ interfaces_traffic = snmppoll("WALK", ".1.3.6.1.2.1.31.1.1.1.10", device_ip, community) time_now = datetime.now() print "polled interface traffic on {}".format(device_ip) if not interfaces_traffic: print_error("no interface traffic stats reutrned!") return for int_traffic in interfaces_traffic: for i in range(len(device_interfaces)): if int(int_traffic.oid_index) != int(device_interfaces[i]["oid_index"]): # Not a matched interface continue if device_interfaces[i]["speed"] == 0: # Will always alarm no need for this break device_interfaces[i]["current_counter"] = int(int_traffic.value) state, device_interfaces[i] = calculate_interface_util(device_interfaces[i], time_now) if not state: break if device_interfaces[i]["util_percentage"] > 1: print_polling_traffic_stats(device_interfaces[i]) print "threashold is {}% current usage is {}% on {} for {} device".format( percentage_threashold, device_interfaces[i]["util_percentage"], device_interfaces[i]["name"], device_ip) update_interface_and_history(device_interfaces[i]) if device_interfaces[i]["util_percentage"] > percentage_threashold: print "interface {} on {} is at {}% which is above threashold".format( device_interfaces[i]["name"], device_ip, device_interfaces[i]["util_percentage"]) traffic_automation(device_interfaces[i], device_ip, community)
def setup_steps(): """ Author - Jonathan Steward Function - carry out arg parse setup taking in arguments and validating that some of them are valid returns - argparse object - stores all arguments input """ parser = argparse.ArgumentParser() host_help = "Host you wish to target" interface_help = "interface you wish to target" cost_help = "cost you wish to apply, should be a whole number" # in a perfect world this would look up passwords username and vendor detail parser.add_argument("-d", "--host", help=host_help, dest="host", required=True) parser.add_argument("-i", "--interface", help=interface_help, dest="interface", required=True) parser.add_argument("-c", "--cost", help=cost_help, dest="cost", required=True) # Note other community data would be needed if a more secure implementation was used. arguments = parser.parse_args() try: int(arguments.cost) except ValueError: print_error("cost provided isn't a whole number") sys.exit() # used to match the corect regex and grab the interface that is down match_interface_name = "(Ethernet|FastEthernet|GigabitEthernet|TenGigE|fe-|ge-|xe-|et-)" # Juniper doesn't have a standard ethernet but does have fast,gig,ten and 100 gig code prefix match_interface_number = "((\d+\/)+)*\d+" interface_regex = match_interface_name + match_interface_number interface_check = re.match(interface_regex, arguments.interface) if not interface_check: print_error("interface isn't valid") sys.exit() ip_state = check_ip(arguments.host) if not ip_state: sys.exit() return arguments
def int_in_ae(ip, ae_int, interface, community, activate, stage): """ Author - Jonathan Steward Function - identifies if the interface is in the lag and if so what lag. Inputs - ip - string ae_int - string interface - string community - string returns - bool - state of if the interface is in lag int - ae_int the interface is in. """ state, ae_index, interface_index, device_interfaces = find_ae_int_ref( ip, ae_int, interface, community, activate) # print interface_index # print ae_index if ae_index == "bad": return False, "bad" if not state: # Error messages in find_ae_int return False, "" if not activate and stage == 1: if ae_int: return True, ae_int else: return True, "" result = SnmpPoll( 'GET', '.1.2.840.10006.300.43.1.2.1.1.13.{}'.format(interface_index), ip, community) print result if not ae_index: if not result.oid_index: print_error("no AE interface found assigned to interface") if activate: return False, "" for inter in device_interfaces: if inter.oid_index == result.value: ae_int = inter.value print_error("Found AE port {}".format(ae_int)) return True, ae_int elif result.value == ae_index: return True, ae_int return False, ae_int
def Juniper_connect(device_object): """ Author - Jonathan Steward Function - Create a connnection to a juniper device Inputs - device_object - Device object returns - device connection object """ print "{}: connecting".format(time.strftime('%Y-%m-%d %H:%M:%S')) try: device_con = Device(host=device_object.ip, user=device_object.username, passwd=device_object.password).open() except ConnectError as error: print_error("{}: there was an issue connecting: {}".format( time.strftime('%Y-%m-%d %H:%M:%S'), error)) return return device_con
def identify_ip(message): """ Author - Jonathan Steward Function - From a messagem parse for the ip address Inputs - message - string returns - ip - string - if failed returns a blank string """ ip_regex = "(?P<host>\d+\.\d+\.\d+\.\d+).*" ip = re.match(ip_regex, message) if not ip: print_error("Syslog message not valid!: \n{}".format(message)) return "" ip = ip.group("host") ip_state = check_ip(ip) if not ip_state: return "" return ip
def add_cost_workflow(ip, interface, cost, called_from): """ Author - Jonathan Steward Function - Workflow function calling relevant functions needed for configuration Inputs - ip - string - ip address of host on which cost needs to be applied interface - string - the interface name of the interface to apply cost to cost - int - Cost to apply to the interface called_from - string - what is callling this fuction for logging returns - bool - state of the workflow """ arg_string = "host : {}, interface: {}, cost: {}, called from : {}".format( ip, interface, cost, called_from) tool = ToolLog("deprefer tool", arg_string) state, device = device_config_info_lookup(ip) if not state: print "didn't get device_config info" tool.set_tool_log(False) return False config_state = False print "starting add_cost_workflow" if device.vendor == "cisco": lock_state = get_config_lock(device.ip, "deprefer tool") if lock_state: config_state = add_cost_interface_cisco_ospf(device, interface, cost) print_error("attempted to configured cisco device") elif device.vendor == "juniper": lock_state = get_config_lock(device.ip, "deprefer tool") if lock_state: config_state = add_cost_interface_juniper_ospf(device, interface, cost) print_error("attempted to configured juniper device") else: print "unsupported vendor {}".format(device.vendor) tool.set_tool_log(False) return False set_config_lock(device.ip, False, "deprefer tool") print"config lock released" tool.set_tool_log(config_state) return True
def add_cost_interface_cisco_ospf(device, interface, cost): """ Author - Jonathan Steward Function - Sends the relevant commmands to a cisco device to apply ospf cost to interface Inputs - device - device object - stores relevant details of device for configuration interface - string - interface that we are adding cost to cost - int - cost to be applied to interface returns - bool - state of the success of configuration """ connection = ssh_connection(device) if not connection: return False # Attempt to log into config command = ("\nen\n{}\nconfig t\n".format(device.enablePassword)) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "#" not in output: print_error("password was wrong!, see below for the issue:\n{}".format(output)) return False print output # Attempt to get to interface prompt command = "\ninterface {interface}\n".format(interface=interface) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "(config-if)" not in output: print_error("interface {} was wrong, see below for output:\n{}".format(interface, output)) return False print output # Attempt to apply to cost command = "\nip ospf cost {cost}\n".format(cost=cost) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "% Invalid" in output: print_error("something went wrong, might not be a L3 interface:{}".format(output)) return False print output command = "\nend\ncopy run start\n" connection.send(command) time.sleep(1) print_error("configured cost correctly") return True
def ssh_connection(device): """ Author - Jonathan Steward Function - create an SSH connection Inputs - device - device object - stores device details for connecting returns - remote_con - paramiko shell object """ remote_con_pre = paramiko.SSHClient() remote_con_pre.set_missing_host_key_policy(paramiko.AutoAddPolicy()) try: remote_con_pre.connect(device.ip, username=device.username, password=device.password, look_for_keys=False, allow_agent=False) except IOError as error: print_error( "Can't connect to SSH for following reason:\n{}".format(error)) return except paramiko.PasswordRequiredException as error: print_error("Username/Password incorrect") return except paramiko.AuthenticationException as error: print_error("Password/Username incorrect") return remote_con = remote_con_pre.invoke_shell() remote_con.settimeout(10) return remote_con
def find_device_ip(device_id): """ Author - Jonathan Steward Function - find the RID of the device required along with some other details Inputs - int - device_id - device_id of the request device returns - string - RID of device string - Vendor of device int - ASN of device """ command = """ SELECT ip, vendor, asn from `FYP Data`.device_table WHERE device_id = {} """.format(device_id) data = get_data(command) if len(data) > 1: print_error("There multipul devices listed under device_id {} somehow".format(device_id)) return "", "", "" if len(data) == 0: print_error("No Data was found for device_id {}".format(device_id)) return "", "", "" print data[0] return data[0][0], data[0][1], data[0][2]
def record_actions(host, message, issue, acted): """ Author - Jonathan Steward Function - sends details to db about event and what happened Inputs - host - string message - string issue - string acted - bool """ device_id = get_device_id(host) command = """ INSERT INTO `FYP Data`.`syslog_events` (`syslog detail`, `device_id`, `acted_on`, `message`) VALUES ("{}", "{}", "{}", "{}"); """.format(issue, device_id, acted, message) if "License" in message: pass elif "bgp" in message: pass else: print_error( "sending following command to log event\n{}".format(command)) set_data_mysql(command)
def process_down(int_down, device): """ Author - Jonathan Steward Function - Call function and evaluate when trying to remove interface from lag Inputs - int_down - string - interface name that went down device - device object storing all details returns - string - the return message to state what happened bool - State of the automation working or not """ print "taking {} out of lag on {}".format(int_down, device.ip) state = process_lag_change(False, device.ip, device.username, device.password, device.vendor, int_down, "", device.community, device.enablePassword) if not state: print_error("Didn't remove interface from lag see above for logs") # email admin return "Didn't remove interface from lag because of issue raised within automation script", False print "message was indicating that interface was down, automation triggered" return ("int {} down removed from lag".format(int_down)), True
def check_for_event(device_int, device_ip): """ Author - Jonathan Steward Function - checks for an existing event and if one exists if its an old event or not Inputs - Global - timeout_minuets - defined at the top to identify how many minuets old an event needs to be before closing it. device_int - object - combined database and snmp gathered information device_ip - string - ip address of the host for this event returns - """ command = """ SELECT * FROM `FYP Data`.interface_events where `interface_id` = '{}' and `state` = 'active' and `issue` = 'out utilization'""".format(device_int["db_id"]) events = get_data(command) if events: time_now = datetime.now() time_diff = (time_now - events[0][4]).seconds timeout_minuets = 5 if time_diff / 60 > timeout_minuets: print_error("closing old event older than {} minuets".format(timeout_minuets)) command = """ UPDATE `FYP Data`.`interface_events` SET `state` = 'resolved' WHERE event_id = {} ;""".format(events[0][0]) set_data_mysql(command) else: print "event for {} on {} already exists will not act".format(device_int["name"], device_ip) return False command = """ INSERT INTO `FYP Data`.`interface_events` (`interface_id`, `state`, `issue`) VALUES ('{}', 'active', 'out utilization');""".format(device_int["db_id"]) set_data_mysql(command) return True
def setup_steps(): """ Author - Jonathan Steward Function - carry out arg parse setup taking in arguments and validating that some of them are valid returns - argparse object - Stores all arguments given to the code """ parser = argparse.ArgumentParser() activate_help = "use this to activate the lag, default is to deactivate" host_help = "use this to enter the host details" # NOTE a company would possibly have their own password/auth system with creds for automation # this isn't being emulated as its just proof of concept interface_help = "enter the full interface name as shown under show interface CASE SENSITIVE" aggport_help = "enter the number of the AE or Port-channel group, scrip will complete based on vendor" # in a perfect world this would look up passwords username and vendor detail parser.add_argument("-a", "--activate", help=activate_help, dest='activate', default=False, action='store_true') parser.add_argument("-d", "--host", help=host_help, dest="ip", required=True) parser.add_argument("-i", "--interface", help=interface_help, dest="interface", required=True) parser.add_argument("-g", "--aggport", help=aggport_help, dest="ae_int", default="") arguments = parser.parse_args() activate = arguments.activate if not arguments.ae_int: if activate: print_error( "Trying to add interface but no AE port provided this isn't possible" ) return print_error("No AE given will attmept to find the AE to remove") else: try: arguments.ae_int = int(arguments.ae_int) except ValueError: print_error( "Please input agg port as a number not full AE or Port-channel \nUsing -g --aggport you inputted {}" .format(arguments.ae_int)) return ip_state = check_ip(arguments.ip) if not ip_state: return match_interface_name = "(Ethernet|FastEthernet|GigabitEthernet|TenGigE|fe-|ge-|xe-|et-)" int_state = re.match(match_interface_name, arguments.interface) if not int_state: print_error( "Interface {} is not valid, please enter the full name. Cisco is case SENSITIVE" .format(arguments.interface)) return return arguments
def process_lag_change( activate, ip, username, password, vendor, interface, ae_int, community, enpassword="******", ): """ Author - Jonathan Steward Function - main workflow of the process to remove interface from lag on device Inputs - activate - bool - identifies if the interface should be added or removed ip - string - ip address of the host username - string - username needed to log into the device password - string - password needed to log into the device vendor - string - the vendor of the device interface - string - interface you want to add or remove ae_int - int - lag you want to remove interface from community - string - snmp community used for polling information from device enpassword - string - default to "cisco", needed to configure cisco devices returns - bool - determines if the automation worked correctly """ variables = [ "activate = {}".format(activate), "ip = {}".format(ip), "username = {}".format(username), "password = {}".format(password), "vendor = {}".format(vendor), "interface = {}".format(interface), "ae_int = {}".format(ae_int), "community = {}".format(community), "enpassword = {}".format(enpassword) ] print variables tool_log = ToolLog("lagchanger", variables) state = get_config_lock(ip, "lagchanger") if not state: tool_log.set_tool_log() return False device_details = Device_object(ip, username, password, enpassword, vendor.lower()) int_state, original_ae_int = int_in_ae(device_details.ip, ae_int, interface, community, activate, 1) if not int_state and original_ae_int == "bad": print_error("intended ae not found") set_config_lock(ip, False, "lagchanger") tool_log.set_tool_log(True) return False if activate: if int_state: # trying to add and also in lag # pointless print_error("interface is already in a lag, can't configure") set_config_lock(ip, False, "lagchanger") tool_log.set_tool_log(True) return False else: # trying to add but not in lag print "trying to add as not in lag" if device_details.vendor == "cisco": state = change_int_lag_state_cisco(True, interface, device_details, ae_int) elif device_details.vendor == "juniper": state = change_int_lag_state_juniper(True, interface, device_details, ae_int) else: if int_state: # Trying to remove and in lag print "trying to remove as in lag" if device_details.vendor == "cisco": state = change_int_lag_state_cisco(False, interface, device_details, ae_int) elif device_details.vendor == "juniper": state = change_int_lag_state_juniper(False, interface, device_details, ae_int) else: # Trying to remove and not in lag # pointless if device_details.vendor == "cisco": print_error( "interface not showing as in lag but cisco devices do this when they are phy down" ) state = change_int_lag_state_cisco(False, interface, device_details, ae_int) else: print_error( "interface is already out of lag, no need to remove further" ) set_config_lock(ip, False, "lagchanger") tool_log.set_tool_log(True) return False if not state: print_error("something failed while configuring, quitting") set_config_lock(ip, False, "lagchanger") tool_log.set_tool_log() return False print_error( "config should have been applied, waiting some time to ensure connection is stable" ) time.sleep(30) int_state, ae_int = int_in_ae(device_details.ip, ae_int, interface, community, activate, 2) check_success(activate, int_state, interface, ae_int) set_config_lock(ip, False, "lagchanger") tool_log.set_tool_log(True) return True
def check_for_peers(): """ Author - Jonathan Steward Function - Gets data from the database about the different peers checks the state of the peers and calls the relevant functions Inputs - n/a returns - int - configures - Number of peers configured used for logging int - checks - Number of peers checked used for logging int - fails - Number of peer actions that failed used for logging """ command = "SELECT * FROM `FYP Data`.BGP_peers" data = get_data(command) # data = peerId/device_id/remote_asn/loopback_source/remote_ip/source_interface/approved/approver/configured non_approved = [] configures = [] checks = [] fails = [] for peer in data: if peer[6] == 0: # Need to approve print_error("peer id {} for device {} and remote ip {} needs to be approved".format( peer[0], peer[1], peer[4])) non_approved.append(peer[0]) elif peer[8] == 0: # Need to configure set_peer_status(peer[0], 1) configures.append(peer[0]) state, peer_object, device = configure_peer_workflow(peer) if state: set_peer_status(peer[0], 2) state = check_peer_status( peer_object["device_ip"], peer_object["remote_ip"], device) if state: print_error("Peer is established") set_peer_status(peer[0], 3) else: fails.append(peer[0]) elif peer[8] == 1: # Started to configured but didn't work print_error("Peer id {} was attempted to be configured previously but there was a problem".format(peer[0])) # EMAIL NETWORK ENGINEER OR SOMETHING SIMILAR elif peer[8] == 2: # Configured but wasn't in established state checks.append(peer[0]) print_error("Checking peer: {}".format(peer)) state = check_peer_workflow(peer) if state: print_error("Peer is established") set_peer_status(peer[0], 3) else: print_error("Peer still not established") fails.append(peer[0]) else: # Peer fully configured pass # Setting peer status to in progress return configures, checks, fails, non_approved
def check_peer_status(device_ip, remote_ip, device): """ Author - Jonathan Steward Function - polls SNMP for the state of the Peer configured and returns details Inputs - string - device_ip - ip address of the device with the target peer string - remote_ip - ip address of neighbour object - device - Device object storing all details returns - bool - state of peer, if established true """ print"waiting for BGP to connect after configuration" time.sleep(30) result = SnmpPoll( "GET", ".1.3.6.1.2.1.15.3.1.2.{}".format(remote_ip), device_ip, device.community) print result.value if result.value == "1": print_error("neighbour is idle") elif result.value == "2": print_error("neighbour is in connect state") elif result.value == "3": print_error("neighbour is active") elif result.value == "4": print_error("neighbour is in open sent state") elif result.value == "5": print_error("neighbour is openconfirm") elif result.value == "6": print_error("neighbour is established") else: print_error("neighbour wasn't at all configured") if result.value == "6": return True return False
def configure_peer_cisco(peer, device): """ Author - Jonathan Steward Function - Steps through the different configuration commands to configure a peer on cisco Inputs - dict - peer - details of peer object - device - details of device returns - bool - state of configuration """ connection = ssh_connection(device) if not connection: return False # Attempt to log into config command = ("\nen\n{}\nconfig t\n\n\n\n\n".format(device.enablePassword)) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "#" not in output: print_error("password was wrong!, see below for the issue:\n{}".format(output)) return False print output command = "\nrouter bgp {}\n".format(peer["local_asn"]) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "(config-router)" not in output: print_error("Local BGP ASN defined in database is incorrect:\n{}".format(output)) return False print output command = "\nneighbor {} remote-as {}\n".format(peer["remote_ip"], peer["remote_asn"]) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "% Invalid" in output: print_error("Something went wrong with configuration:\n{}".format(output)) return False print output if peer["loopback_source"]: command = "\nneighbor {} update-source {}\n".format(peer["remote_ip"], peer["source_interface"]) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "% Invalid" in output: print_error("Something went wrong with configuration:\n{}".format(output)) return False print output if peer["remote_asn"] != device.asn: # Need to configure for ebgp multi hop command = "\nneighbor {} ebgp-multihop 5\n".format(peer["remote_ip"]) connection.send(command) time.sleep(0.5) output = connection.recv(8000) if "% Invalid" in output: print_error("Something went wrong with configuration:\n{}".format(output)) return False print output print_error("configured BGP neighbour") command = "\nend\ncopy run start\n" connection.send(command) time.sleep(1) return True