def test_load_console( self, mock_read_until, mock_select, mock_write, mock_parse): mock_select.return_value = ([self.dev._tty._rx], [], []) xml = """<policy-options> <policy-statement> <name>F5-in</name> <term> <name>testing</name> <then> <accept/> </then> </term> <from> <protocol>mpls</protocol> </from> </policy-statement> </policy-options>""" mock_read_until.return_value = six.b(""" <rpc-reply xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="http://xml.juniper.net/junos/15.2I0/junos"> <load-configuration-results> <ok/> </load-configuration-results> </rpc-reply> ]]>]]>""") cu = Config(self.dev) op = cu.load(xml, format='xml') cu.commit()
def _normal_device(dev): x=loadyaml(site.getsitepackages()[1]+'/jnpr/junos/op/phyport.yml') table=x['PhyPortTable'](dev) table.get() ke=table.keys() cu=Config(dev) print cu for i in ke: sw = dev.rpc.get_config(filter_xml=etree.XML('<configuration><interfaces><interface><name>'+i+'</name></interface></interfaces></configuration>')) s=etree.tostring(sw) #print s e = ET.XML(s) x=etree_to_dict(e) #print x if(x['configuration']==''): print 'Unused port '+i+ ' disabled' set_cmd='set interfaces '+i+' disable description "unused port"' cu.load(set_cmd, format='set') else: try: if(x['configuration']['interfaces']['interface']['unit']['family']['inet']==''): #print 'Unused port '+i+ ' disabled' set_cmd='set interfaces '+i+' disable description "unused port"' cu.load(set_cmd, format='set') except: pass cu.pdiff() cu.commit(confirm=1) print "the config has been committed"
def edit_config(self,dev,ip): conf='set policy-options prefix-list blacklisted-ips' _conf='' #print p,dev ips=ip.split() for i in ips: print "ip=",i if IPAddress(i) in IPNetwork("116.197.188.0/23") or IPAddress(i) in IPNetwork("116.197.190.0/23") or IPAddress(i) in IPNetwork("193.110.49.0/23") or IPAddress(i) in IPNetwork("193.110.55.0/23") or IPAddress(i) in IPNetwork("66.129.239.0/23") or IPAddress(i) in IPNetwork("66.129.241.0/23"): print "Internal IP" continue _conf=_conf+conf+' '+i+'\n' print "conf", _conf try: cu=Config(dev) #print '1' cu.load(_conf,format='set') #fp.write(str(datetime.now())+"the conf has been added to "+p[0]+" \n"+_conf+" \n") print dev.facts['hostname'] cu.pdiff() cu.commit(confirm=3) print "Waiting for 2 mins before final commit..." cu.commit() #fp.write(str(datetime.now())+" the commit has been done "+" \n") print "the config has been committed for",dev.facts['hostname'] except Exception as e: print "commit failed:",e
def main(): """Simple main method to change port status.""" routers = ['10.11.12.1', '10.11.12.2'] pyez_user = '******' pyez_pass = '******' sessions = [Device(host=router, user=pyez_user, password=pyez_pass) for router in routers] for session in sessions: session.open() port = PhyPortClassic(session, namevar='ge-0/0/3') # Step 1.1 # print(port.properties) # print(port.admin) # Step 1.2 port.admin = False port.write() print("Disabling interfaces!") cfg = Config(session) cfg.commit() time.sleep(10) port.admin = True port.write() print("Enabling interfaces!") cfg.commit() session.close()
class JuniperObject(object): def __init__(self, jnp_dev): self.conn = jnp_dev self.config = None self.ports = {} self.routes = {} def __get_ports(self): self.ports = EthPortTable(self.conn) self.ports.get() def __get_routes(self): self.routes = RouteTable(self.conn) self.routes.get() def config_mode(self): self.config = Config(self.conn) self.config.lock() def send_command(self, command, cmd_format, cmd_merge): self.config.load(command, format=cmd_format, merge=cmd_merge) def file_command(self, file_path, file_format, file_merge): self.config.load(path=file_path, format=file_format, merge=file_merge) def get_diff(self): return self.config.diff() def commit(self, comment=None): self.config.commit(comment=comment) def rollback(self): self.config.rollback(0) def unlock(self): self.config.unlock() def show_all_interfaces(self): self.__get_ports() print "Juniper SRX Interface Statistics" for my_key in self.ports.keys(): print "---------------------------------" print my_key + ":" print "Operational Status: " + self.ports[my_key]['oper'] print "Packets In: " + self.ports[my_key]['rx_packets'] print "Packets Out: " + self.ports[my_key]['tx_packets'] def show_all_routes(self): self.__get_routes() print "Juniper SRX Routing Table" for my_key in self.routes.keys(): print "---------------------------------" print my_key + ":" print " Next Hop: {}".format(self.routes[my_key]['nexthop']) print " Age: {}".format(self.routes[my_key]['age']) print " via: {}".format(self.routes[my_key]['via']) print " Protocol: {}".format(self.routes[my_key]['protocol'])
def run(self): self.logfile = open(os.getcwd() + '/' + 'linkfailure_log', 'a') while True: while self.failed() == False: time.sleep(1) # select a router r_number = random.randint(1,len(self.rtr)) - 1 # select a random interface i_number = random.randint(1, len(self.rtr[r_number]['interfaces'])) - 1 #set interfaces ge-1/0/3 disable cmd = 'set interfaces ' + self.rtr[r_number]['interfaces'][i_number]['name'] + ' disable' dev = Device(host=self.rtr[r_number]['ip'], user='******', password='******') dev.open() dev.timeout = 60 cu = Config(dev) cu.lock() cu.load(cmd, format='set', merge=True) cu.commit() cu.unlock() dev.close() link__data = { 'status': 'failed', 'timestamp': datetime.datetime.fromtimestamp(time.time()).strftime('%a:%H:%M:%S'), 'router_id': self.rtr[r_number]['router_id'], 'router_name': self.rtr[r_number]['name'], 'interface_address': self.rtr[r_number]['interfaces'][i_number]['address'], 'interface_name': self.rtr[r_number]['interfaces'][i_number]['name'] } jd = json.dumps(link__data) self.redis.publish('link_event', jd) self.logfile.write("Link failed: " + datetime.datetime.fromtimestamp(time.time()).strftime('%a:%H:%M:%S') + " " + self.rtr[r_number]['name'] + " " + self.rtr[r_number]['ip'] + " " + self.rtr[r_number]['interfaces'][i_number]['name'] + "\n") self.logfile.flush() # now repair the link while self.repaired() == False: time.sleep(1) cmd = 'delete interfaces ' + self.rtr[r_number]['interfaces'][i_number]['name'] + ' disable' dev = Device(host=self.rtr[r_number]['ip'], user='******', password='******') dev.open() dev.timeout = 60 cu = Config(dev) cu.lock() cu.load(cmd, format='set', merge=True) cu.commit() cu.unlock() dev.close() link__data = { 'status': 'healed', 'timestamp': datetime.datetime.fromtimestamp(time.time()).strftime('%a:%H:%M:%S'), 'router_id': self.rtr[r_number]['router_id'], 'router_name': self.rtr[r_number]['name'], 'interface_address': self.rtr[r_number]['interfaces'][i_number]['address'], 'interface_name': self.rtr[r_number]['interfaces'][i_number]['name'] } jd = json.dumps(link__data) self.redis.publish('link_event', jd) self.logfile.write("Link healed: " + datetime.datetime.fromtimestamp(time.time()).strftime('%a:%H:%M:%S') + " " + self.rtr[r_number]['name'] + " " + self.rtr[r_number]['ip'] + " " + self.rtr[r_number]['interfaces'][i_number]['name'] + "\n") self.logfile.flush()
def process_device(ip, **kwargs): dev = Device(host=ip, **kwargs) cu = Config(dev) print "Searching for active sessions on Device:", ip, "matching the following criteria" + '\n\n\t' + "Destination IP-Address:" + '\t' + destip + '\n\t' + "Destination-Port:" + '\t' + dport + '\n\t' + "Application:" + '\t\t' + application + '\n' try: dev.open() cluster_status = ClusterStatus(dev) cluster_status.get() session_table = SessionTable(dev) session_table.get() found = 'f' cluster = 'a' cu.lock() for c in cluster_status: if cluster_status.keys(): print "SRX Cluster has redundancy-group", c.redundancy_group_id if not cluster_status.keys(): print "Clustering is not Enabled" for s in session_table: if session_table.keys() and s.in_destination_address == destip and s.in_destination_port == dport and s.in_session_protocol == application: found = 't' print "Found Session on", ip, s.re_name + '\n\n\t' + "Source-Address:" + '\t' + s.in_source_address +'\n\t' + "Session-Id:" + '\t' + s.session_identifier + '\n\n' + "Creating Address-entry on Device:", ip + '\n\n' + "Clearing active session" + '\n\t' + "Session-Id:" + '\t' + s.session_identifier + '\n\t' + "Cluster-Node:" + '\t' + s.re_name + '\n' block_src = {'Address': s.in_source_address} jinja_data = open("jinjafile.conf", "wb") jinja_data.write(JinjaTemplate.render(**block_src)) jinja_data.close() rsp = cu.load( template_path="jinjafile.conf", merge=True ) clearflow = dev.rpc.clear_flow_session(destination_prefix=s.in_destination_address, source_prefix=s.in_source_address, destination_port=s.in_destination_port, protocol=s.in_session_protocol) cu.commit() cu.unlock() if found == 'f': print "No Active Sessions were found with the following criteria:" + '\n\n\t' + "Destination IP-Address:" + '\t' + destip + '\n\t' + "Destination Port:" + '\t' + dport +'\n\t' + "Application:" + '\t\t' + application + '\n' except RpcError: msg = "{0} was Skipped due to RPC Error. Device is not a Juniper SRX Series".format(ip.rstrip()) print msg dev.close() except Exception as err: msg = "{0} was skipped due to unhandled exception.\n{1}".format(ip.rstrip(), err) print msg traceback.print_exc(file=sys.stdout) dev.close()
class Jconfig: def __init__(self, host, user='******', password='******', t_vars={}): self.host = host self.user = user self.password = password self.t_vars = t_vars self.dev = Device(host=self.host, user=self.user, password=self.password, gather_facts=False) try: self.dev.open() self.dev.timeout = 300 self.cfg = Config(self.dev) except Exception as err: print err sys.exit(1) def loadconf(self, t_file): try: print "=> Loading file %s on %s" % (t_file, self.host) self.cfg.load(template_path=t_file, template_vars=self.t_vars, overwrite=False, merge=True) except Exception as err: print err def askcommit(self): try: print "== Configuration diff on %s" % (self.host) self.cfg.pdiff() answer = raw_input('Do you want to commit change ? [y/n]') if answer[0] == 'y': self.cfg.commit() except Exception as err: print err def commit(self): try: print "== Configuration diff on %s" % (self.host) self.cfg.pdiff() self.cfg.commit() except Exception as err: print err def getconf(self): try: conf = self.dev.rpc.get_configuration(dict(format='text')) return etree.tostring(conf, method="text") except Exception as err: print err
def deployConfig(my_device_list_dict, my_username, my_password, my_config_template_file): my_hostname="" try: my_hostname=my_device_list_dict["mgmt_ip"] printProgress("INFO",my_hostname,"Connecting to device through netconf.") dev=Device(my_hostname,user=my_username,password=my_password) dev.open() dev.timeout=3*60 cu = Config(dev) printProgress("INFO",my_hostname,"Going to load template the config now.") # Determine if template file is in "set" or "bracketed" format if isSet(my_config_template_file): rsp=cu.load(template_path=my_config_template_file,format='set',template_vars=my_device_list_dict) else: rsp=cu.load(template_path=my_config_template_file,template_vars=my_device_list_dict) printProgress("INFO",my_hostname,"Performing diff between active and candidate config.") cu.pdiff() printProgress("INFO",my_hostname,"Performing commit check") if cu.commit_check(): printProgress("INFO",my_hostname,"commit check was successfull.") printProgress("INFO",my_hostname,"performing commit now.") commit_status=cu.commit() printProgress("INFO",my_hostname,"disconnecting from device.") dev.close() return commit_status else: return False except Exception,err: printProgress("ERROR",my_hostname,"Encountered exception while deploying config") printProgress("ERROR",my_hostname,str(err)) return False
def main(): ''' Exercise using Juniper's PyEZ to make changes to device in various ways ''' pwd = getpass() ip_addr = raw_input("Enter Juniper SRX IP: ") ip_addr = ip_addr.strip() juniper_srx = { "host": ip_addr, "user": "******", "password": pwd } print "\n\nConnecting to Juniper SRX...\n" a_device = Device(**juniper_srx) a_device.open() cfg = Config(a_device) print "Setting hostname using set notation" cfg.load("set system host-name test1", format="set", merge=True) print "Current config differences: " print cfg.diff() print "Performing rollback" cfg.rollback(0) print "\nSetting hostname using {} notation (external file)" cfg.load(path="load_hostname.conf", format="text", merge=True) print "Current config differences: " print cfg.diff() print "Performing commit" cfg.commit() print "\nSetting hostname using XML (external file)" cfg.load(path="load_hostname.xml", format="xml", merge=True) print "Current config differences: " print cfg.diff() print "Performing commit" cfg.commit() print
def updateDeviceConfiguration(self): ''' Device Connection should be open by now, no need to connect again ''' logger.debug('updateDeviceConfiguration for %s' % (self.deviceLogStr)) l3ClosMediation = L3ClosMediation(conf = self._conf) config = l3ClosMediation.createLeafConfigFor2Stage(self.device) # l3ClosMediation used seperate db sessions to create device config # expire device from current session for lazy load with committed data self._session.expire(self.device) configurationUnit = Config(self.deviceConnectionHandle) try: configurationUnit.lock() logger.debug('Lock config for %s' % (self.deviceLogStr)) except LockError as exc: logger.error('updateDeviceConfiguration failed for %s, LockError: %s, %s, %s' % (self.deviceLogStr, exc, exc.errs, exc.rpc_error)) raise DeviceError(exc) try: # make sure no changes are taken from CLI candidate config left over configurationUnit.rollback() logger.debug('Rollback any other config for %s' % (self.deviceLogStr)) configurationUnit.load(config, format='text') logger.debug('Load generated config as candidate, for %s' % (self.deviceLogStr)) #print configurationUnit.diff() #print configurationUnit.commit_check() configurationUnit.commit() logger.info('Committed twoStage config for %s' % (self.deviceLogStr)) except CommitError as exc: #TODO: eznc Error handling is not giving helpful error message logger.error('updateDeviceConfiguration failed for %s, CommitError: %s, %s, %s' % (self.deviceLogStr, exc, exc.errs, exc.rpc_error)) configurationUnit.rollback() raise DeviceError(exc) except Exception as exc: logger.error('updateDeviceConfiguration failed for %s, %s' % (self.deviceLogStr, exc)) logger.debug('StackTrace: %s' % (traceback.format_exc())) configurationUnit.rollback() raise DeviceError(exc) finally: configurationUnit.unlock() logger.debug('Unlock config for %s' % (self.deviceLogStr))
def updateDeviceConfiguration(self): ''' Device Connection should be open by now, no need to connect again ''' logger.debug('updateDeviceConfiguration for %s' % (self.deviceLogStr)) config = self.getDeviceConfig() configurationUnit = Config(self.deviceConnectionHandle) try: configurationUnit.lock() logger.debug('Lock config for %s' % (self.deviceLogStr)) except LockError as exc: logger.error('updateDeviceConfiguration failed for %s, LockError: %s, %s, %s' % (self.deviceLogStr, exc, exc.errs, exc.rpc_error)) raise DeviceRpcFailed('updateDeviceConfiguration failed for %s' % (self.deviceLogStr), exc) try: # make sure no changes are taken from CLI candidate config left over configurationUnit.rollback() logger.debug('Rollback any other config for %s' % (self.deviceLogStr)) configurationUnit.load(config, format='text') logger.debug('Load generated config as candidate, for %s' % (self.deviceLogStr)) #print configurationUnit.diff() #print configurationUnit.commit_check() configurationUnit.commit() logger.info('Committed twoStage config for %s' % (self.deviceLogStr)) except CommitError as exc: #TODO: eznc Error handling is not giving helpful error message logger.error('updateDeviceConfiguration failed for %s, CommitError: %s, %s, %s' % (self.deviceLogStr, exc, exc.errs, exc.rpc_error)) configurationUnit.rollback() raise DeviceRpcFailed('updateDeviceConfiguration failed for %s' % (self.deviceLogStr), exc) except Exception as exc: logger.error('updateDeviceConfiguration failed for %s, %s' % (self.deviceLogStr, exc)) logger.debug('StackTrace: %s' % (traceback.format_exc())) configurationUnit.rollback() raise DeviceRpcFailed('updateDeviceConfiguration failed for %s' % (self.deviceLogStr), exc) finally: configurationUnit.unlock() logger.debug('Unlock config for %s' % (self.deviceLogStr))
class VlanDeployer(threading.Thread): def __init__(self , host , vlans): self.cred = host self.vlans = vlans threading.Thread.__init__(self) self.dev1 = None self.cu=None def run(self): self.dev1 = Device(host=self.cred[0] , user=self.cred[1] , password=self.cred[2]) self.dev1.open() self.cu = Config(self.dev1) print "CONNECTED TO "+self.cred[0] for term in self.vlans: config_text= 'vlans{ ' + term['Vlan-name'] + '{description "' + term['Desc'] + '"; vlan-id ' + term["Vlan-id"]+ ';}}' self.cu.load(config_text , format="text" , merge=True) self.cu.commit() self.dev1.close() print "CONF PUSHED TO "+ self.cred[0]
def main(): pwd = getpass() juniper = { "host": "50.76.53.27", "user": "******", "password": pwd } a_device = Device(**juniper) a_device.open() cfg = Config(a_device) print "Changing hostname with set command" cfg_load = cfg.load("set system host-name batz-jnpr-srx1", format ="set", merge=True) print cfg.diff() print print "Doing rollback" cfg.rollback(0) print "Changing hostname with conf method " cfg_load_conf = cfg.load(path='hostname.conf', format='text', merge=True) print cfg.diff() print print "Doing rollback" cfg.rollback(0) print "Changing hostname with xml method" cfg_load_xml = cfg.load(path='hostname.xml', format='xml', merge=True) print cfg.diff() print print "Doing changes" cfg.commit() print
def main(): ''' I will test the case with applying config for 1 minute ''' pwd = getpass() ip_addr = raw_input('''Enter Juniper SRX IP"(184.105.247.76)": ''') ip_addr = ip_addr.strip() juniper_srx = { "host": ip_addr, "user": "******", "password": pwd } try: a_device = Device(**juniper_srx) a_device.open() cfg = Config(a_device) cfg.lock() cfg.load(path="exercice4_config.xml" , format="xml", merge=True) print "#"*80 print "Displaying the differences between the running config and the candidate config:" print "#"*80 cfg.pdiff() print "+"*80 print "Applying config" print "+"*80 cfg.commit(comment="Applying config from exercice4_config.xml") print "-"*80 print "reverting config back" cfg.rollback(1) cfg.pdiff() cfg.commit() print "-"*80 print "\n"*2 print except: print print "Authentication Error" print
def commitConfiguration(self): dev = Device(host=self.srxip, user=self.username, password=self.password) dev.open() cu = Config(dev) config = """ set routing-options static route %s/32 next-hop %s set interfaces %s family inet set security zones security-zone vpn interfaces %s set security ike gateway gateway-%s ike-policy pol-basic set security ike gateway gateway-%s address %s set security ike gateway gateway-%s external-interface ge-0/0/0.0 set security ipsec vpn vpn-%s bind-interface %s set security ipsec vpn vpn-%s ike gateway gateway-%s set security ipsec vpn vpn-%s ike proxy-identity local 192.168.1.0/26 set security ipsec vpn vpn-%s ike proxy-identity remote %s/32 set security ipsec vpn vpn-%s ike ipsec-policy pol-basic set security ipsec vpn vpn-%s establish-tunnels immediately """ % (self.remoteipprivate, self.tunnelint, self.tunnelint, self.tunnelint, self.hostname, self.hostname, self.remoteippublic, self.hostname, self.hostname, self.tunnelint, self.hostname, self.hostname, self.hostname, self.hostname, self.remoteipprivate, self.hostname, self.hostname) cu.load(config, format="set") cu.commit() dev.close() return "committed config: \n" + config
def main(): ''' Main function ''' a_device = remote_conn(HOST, USER, PWD) if not a_device: sys.exit('Fix the above errors. Exiting...') print a_device.facts cfg = Config(a_device) cfg.lock() print 'Set hostname using set format' set_hostname(cfg, 'pytest-gmaz', 'set') print 'Show differences' print cfg.diff() print 'Rollback' cfg.rollback(0) print 'Check if rollback is ok' print cfg.diff() print 'Set hostname using cfg file' set_hostname(cfg, 'hostname.conf', 'text') print 'Show differences' print cfg.diff() print 'Commit' cfg.commit(comment='Text hostname commit by gmazioli') print 'Set hostname using external XML' set_hostname(cfg, 'hostname.xml', 'xml') print 'Show differences' print cfg.diff() print 'Commit' cfg.commit(comment='XML hostname commit by gmazioli') print 'Reverting changes and doing the final commit' set_hostname(cfg, 'pynet-jnpr-srx1', 'set') cfg.commit(comment='System commit by gmazioli') cfg.unlock()
def main(): ''' Main function ''' a_device = remote_conn(HOST, USER, PWD) if not a_device: sys.exit('Fix the above errors. Exiting...') print a_device.facts cfg = Config(a_device) cfg.lock() print 'Set hostname using set format' set_hostname(cfg, 'pytest-gmaz', 'set') print 'Show differences' print cfg.diff() print 'Rollback' cfg.rollback(0) print 'Check if rollback is ok' print cfg.diff() print 'Set hostname using cfg file' set_hostname(cfg, 'hostname.conf', 'text') print 'Show differences' print cfg.diff() print 'Commit' cfg.commit(comment='Text hostname commit by gmazioli') print 'Set hostname using external XML' set_hostname(cfg, 'hostname.xml', 'xml') print 'Show differences' print cfg.diff() print 'Commit' cfg.commit(comment='XML hostname commit by gmazioli') print 'Reverting changes and doing the final commit' set_hostname(cfg, 'pynet-jnpr-srx1', 'set') cfg.commit(comment='System commit by gmazioli') cfg.unlock()
config = Config(dev) ''' LOCK DEVICE CONFIG ''' print "Locking the configuration" time.sleep(3) try: config.lock() except LockError as err: print("Unable to lock configuration: {0}".format(err)) ''' LOAD DEVICE CONFIG ''' print "Loading configuration changes" time.sleep(3) try: config.load(template_path=template_file, template_vars=device_vars, merge=True) except (ConfigLoadError, Exception) as err: print("Unable to load configuration changes: {0}".format(err)) ''' COMMIT DEVICE CONFIG ''' print "Committing the configuration" time.sleep(3) try: config.commit(comment='Loaded by example.') except CommitError as err: print("Unable to commit configuration: {0}".format(err))
print item["host_name"] + '.oc.bgp.conf' conffile = open(item["host_name"] + '.oc.bgp.conf', 'w') conffile.write(template.render(item_vars)) conffile.close() print 'Done for all the devices!\n' # load and commit the configuration file for each device print 'Pushing and committing the configuration files to the devices ...' for item in my_list_of_devices: dev = Device(host=item["management_ip"], user='******', password='******') dev.open() cfg = Config(dev) cfg.load(path=item["host_name"] + '.oc.bgp.conf', format='text') if cfg.commit(comment="from PyEZ") == True: print('Configuration commited successfully on ' + item["host_name"]) else: print('Commit failed on ' + item["host_name"]) dev.close() print 'Done for all the devices!\n' # Wait for 20 seconds. so BGP sessions will be established. print 'Waiting 20 seconds before starting to audit the BGP sessions state ...\n' time.sleep(20) ''' audit BGP states with tables and view Please add table and view for bgp before as it is not provided by PyEZ. ''' print 'Auditing the BGP states using PyEZ Tables and Views:' for device in my_list_of_devices:
class JunosDevice(BaseDevice): def __init__(self, host, username, password, *args, **kwargs): super(JunosDevice, self).__init__(host, username, password, *args, vendor='juniper', device_type=JNPR_DEVICE_TYPE, **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.connected = False self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativdSW(self.native) def open(self): if not self.connected: self.native.open() self.connected = True def close(self): if self.connected: self.native.close() self.connected = False def show(self, command, raw_text=True): if not raw_text: raise ValueError('Juniper only supports raw text output. \ Append " | display xml" to your commands for a structured string.') if not command.startswith('show'): raise CommandError(command, 'Juniper "show" commands must begin with "show".') return self.native.cli(command, warning=False) def show_list(self, commands, raw_text=True): responses = [] for command in commands: responses.append(self.show(command, raw_text=raw_text)) return responses def backup_running_config(self, filename): with open(filename, 'w') as f: f.write(self.running_config) def config(self, command, format='set'): try: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandError(command, e.message) def config_list(self, commands, format='set'): try: for command in commands: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandListError(commands, command, e.message) def _uptime_components(self, uptime_full_string): match_days = re.search(r'(\d+) days?', uptime_full_string) match_hours = re.search(r'(\d+) hours?', uptime_full_string) match_minutes = re.search(r'(\d+) minutes?', uptime_full_string) match_seconds = re.search(r'(\d+) seconds?', uptime_full_string) days = int(match_days.group(1)) if match_days else 0 hours = int(match_hours.group(1)) if match_hours else 0 minutes = int(match_minutes.group(1)) if match_minutes else 0 seconds = int(match_seconds.group(1)) if match_seconds else 0 return days, hours, minutes, seconds def _uptime_to_string(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components(uptime_full_string) return '%02d:%02d:%02d:%02d' % (days, hours, minutes, seconds) def _uptime_to_seconds(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components(uptime_full_string) seconds += days * 24 * 60 * 60 seconds += hours * 60 * 60 seconds += minutes * 60 return seconds def _get_interfaces(self): eth_ifaces = EthPortTable(self.native) eth_ifaces.get() loop_ifaces = LoopbackTable(self.native) loop_ifaces.get() ifaces = eth_ifaces.keys() ifaces.extend(loop_ifaces.keys()) return ifaces def checkpoint(self, filename): self.save(filename) def rollback(self, filename): self.native.timeout = 60 temp_file = NamedTemporaryFile() with SCP(self.native) as scp: scp.get(filename, local_path=temp_file.name) self.cu.load(path=temp_file.name, format='text', overwrite=True) self.cu.commit() temp_file.close() self.native.timeout = 30 @property def facts(self): if hasattr(self, '_facts'): return self._facts native_facts = self.native.facts facts = {} facts['hostname'] = native_facts['hostname'] facts['fqdn'] = native_facts['fqdn'] facts['model'] = native_facts['model'] native_uptime_string = native_facts['RE0']['up_time'] facts['uptime'] = self._uptime_to_seconds(native_uptime_string) facts['uptime_string'] = self._uptime_to_string(native_uptime_string) facts['serial_number'] = native_facts['serialnumber'] facts['interfaces'] = self._get_interfaces() for fact_key in native_facts: if fact_key.startswith('version') and fact_key != 'version_info': facts['os_version'] = native_facts[fact_key] break facts['vendor'] = self.vendor self._facts = facts return self._facts def _file_copy_local_file_exists(self, filepath): return os.path.isfile(filepath) def _file_copy_local_md5(self, filepath, blocksize=2**20): if self._file_copy_local_file_exists(filepath): m = hashlib.md5() with open(filepath, "rb") as f: buf = f.read(blocksize) while buf: m.update(buf) buf = f.read(blocksize) return m.hexdigest() def _file_copy_remote_md5(self, filename): return self.fs.checksum(filename) def file_copy_remote_exists(self, src, dest=None): if dest is None: dest = os.path.basename(src) local_hash = self._file_copy_local_md5(src) remote_hash = self._file_copy_remote_md5(dest) if local_hash is not None: if local_hash == remote_hash: return True return False def file_copy(self, src, dest=None): if dest is None: dest = os.path.basename(src) with SCP(self.native) as scp: scp.put(src, remote_path=dest) def get_boot_options(self): return self.facts['os_version'] def set_boot_options(self, sys): raise NotImplementedError def reboot(self, timer=0, confirm=False): if confirm: self.sw.reboot(in_min=timer) else: print('Need to confirm reboot with confirm=True') @property def running_config(self): return self.show('show config') def save(self, filename=None): if filename is None: self.cu.commit() return temp_file = NamedTemporaryFile() temp_file.write(self.show('show config')) temp_file.flush() with SCP(self.native) as scp: scp.put(temp_file.name, remote_path=filename) temp_file.close() return True @property def startup_config(self): return self.show('show config')
class TestConfig(unittest.TestCase): @patch('ncclient.manager.connect') def setUp(self, mock_connect): mock_connect.side_effect = self._mock_manager self.dev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.dev.open() self.conf = Config(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm_true(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=True) self.conf.rpc.commit_configuration\ .assert_called_with(confirmed=True) def test_config_commit_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') def test_config_commit_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(synchronize=True) def test_config_commit_force_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(force_sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(**{'synchronize': True, 'force-synchronize': True}) def test_config_commit_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(timeout=60) self.conf.rpc.commit_configuration\ .assert_called_with(dev_timeout=60) def test_config_commit_full(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(full=True) self.conf.rpc.commit_configuration\ .assert_called_with(full=True) def test_config_commit_detail(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<mockdetail/>' self.assertEqual('<mockdetail/>', self.conf.commit(detail=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}) def test_config_commit_combination(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<moredetail/>' self.assertEqual( '<moredetail/>', self.conf.commit( detail=True, force_sync=True, full=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}, **{'synchronize': True, 'full': True, 'force-synchronize': True}) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_xml_exception(self, mock_jxml): class MyException(Exception): xml = etree.fromstring('<test/>') self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(CommitError, self.conf.commit) def test_config_commit_exception(self): class MyException(Exception): pass self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(MyException, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with( {'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_diff_exception_severity_warning(self): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>mgd: statement must contain additional statements</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) self.conf.rpc.get_configuration = MagicMock( side_effect=RpcError(rsp=rsp)) self.assertEqual(self.conf.diff(), "Unable to parse diff from response!") def test_config_diff_exception_severity_warning_still_raise(self): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>statement not found</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) self.conf.rpc.get_configuration = MagicMock( side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, self.conf.diff) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format_set(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') def test_config_load_len_with_format_xml(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') xmldata = """<snmp> <community> <name>iBGP</name> </community> </snmp>""" self.assertEqual(self.conf.load(xmldata, format='xml'), 'rpc_contents') def test_config_load_len_with_format_text(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') textdata = """policy-options { prefix-list TEST1-NETS { 100.0.0.0/24; } policy-statement TEST1-NETS { term TEST1 { from { prefix-list TEST1-NETS; } then accept; } term REJECT { then reject; } } }""" self.assertEqual(self.conf.load(textdata), 'rpc_contents') def test_config_load_with_format_json(self): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load('test.json', format='json') self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') @patch(builtin_string + '.open') def test_config_load_with_format_json_from_file_ext(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path='test.json') self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') @patch(builtin_string + '.open') def test_config_load_update(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path='test.conf', update=True) self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_update_merge_overwrite(self): self.assertRaises(ValueError, self.conf.load, path='test.jnpr', update=True, merge=True, overwrite=True) @patch(builtin_string + '.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch(builtin_string + '.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch(builtin_string + '.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch(builtin_string + '.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') @patch(builtin_string + '.open') def test_config_load_try_load_rpcerror(self, mock_open): ex = ConfigLoadError( rsp=etree.fromstring(( """<load-configuration-results> <rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error> </load-configuration-results>"""))) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(ConfigLoadError, self.conf.load, path='config.conf') @patch(builtin_string + '.open') def test_config_load_try_load_rpctimeouterror(self, mock_open): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.load, path='config.conf') @patch(builtin_string + '.open') def test_config_try_load_exception(self, mock_open): class OtherException(Exception): pass self.conf.rpc.load_config = MagicMock(side_effect=OtherException()) self.assertRaises(OtherException, self.conf.load, path='config.conf') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_template_path(self, mock_etree): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock(return_value='<test/>') self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1) @patch('jnpr.junos.Device.execute') def test_rescue_action_save(self, mock_exec): self.dev.request_save_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('save')) @patch('jnpr.junos.Device.execute') def test_rescue_action_get_exception(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock(side_effect=Exception) self.assertTrue(self.conf.rescue('get') is None) @patch('jnpr.junos.Device.execute') def test_rescue_action_get(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock() self.dev.rpc.get_rescue_information.return_value = 1 self.assertEqual(self.conf.rescue('get', format='xml'), 1) @patch('jnpr.junos.Device.execute') def test_rescue_action_delete(self, mock_exec): self.dev.rpc.request_delete_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('delete')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload(self, mock_exec): self.dev.rpc.load_configuration = MagicMock() self.dev.rpc.load_configuration.return_value = True self.assertTrue(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload_exception(self, mock_exec): self.dev.rpc.load_configuration = MagicMock(side_effect=Exception) self.assertFalse(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_unsupported_action(self, mock_exec): self.assertRaises(ValueError, self.conf.rescue, 'abc') def test_config_load_lset_from_rexp_xml(self): self.conf.rpc.load_config = MagicMock() conf = """<snmp><name>iBGP</name></snmp>""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_lset_from_rexp_json(self): self.conf.rpc.load_config = MagicMock() conf = """{ "configuration" : { "system" : { "services" : { "telnet" : [null] } } } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') def test_config_load_lset_from_rexp_set(self): self.conf.rpc.load_config = MagicMock() conf = """set system domain-name englab.nitin.net""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_delete(self): self.conf.rpc.load_config = MagicMock() conf = """delete snmp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_conf(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_lset_from_rexp_conf_replace_tag(self): self.conf.rpc.load_config = MagicMock() conf = """replace: snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'replace') def test_config_load_lset_from_rexp_error(self): self.conf.rpc.load_config = MagicMock() conf = """test>""" self.assertRaises(RuntimeError, self.conf.load, conf) def test_load_merge_true(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf, merge=True) self.assertFalse('action' in self.conf.rpc.load_config.call_args[1]) def test_commit_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit) def test_commit_check_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit_check) def test_commit_configuration_multi_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) try: self.dev.rpc.commit_configuration() except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) if ncclient.__version__ > (0, 4, 5): self.assertEqual(ex.message, "error: interface-range 'axp' is not defined\n" "error: interface-ranges expansion failed") self.assertEqual(ex.errs, [{'source': None, 'message': "interface-range 'axp' is not defined", 'bad_element': None, 'severity': 'error', 'edit_path': None}, {'source': None, 'message': 'interface-ranges expansion failed', 'bad_element': None, 'severity': 'error', 'edit_path': None}]) else: self.assertEqual(ex.message, "interface-range 'axp' is not defined") @patch('jnpr.junos.utils.config.Config.lock') @patch('jnpr.junos.utils.config.Config.unlock') def test_config_mode_exclusive(self, mock_unlock, mock_lock): with Config(self.dev, mode='exclusive') as conf: conf.rpc.load_config = MagicMock() conf.load('conf', format='set') self.assertTrue(mock_lock.called and mock_unlock.called) @patch('jnpr.junos.Device.execute') def test_config_mode_batch(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch('jnpr.junos.Device.execute') def test_config_mode_private(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='private') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(private=True) @patch('jnpr.junos.Device.execute') def test_config_mode_dynamic(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='dynamic') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(dynamic=True) @patch('jnpr.junos.Device.execute') def test_config_mode_close_configuration_ex(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() ex = RpcError(rsp='ok') ex.message = 'Configuration database is not open' self.dev.rpc.close_configuration = MagicMock(side_effect=ex) try: with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) self.assertTrue(self.dev.rpc.close_configuration.called) @patch('jnpr.junos.Device.execute') def test_config_mode_undefined(self, mock_exec): try: with Config(self.dev, mode='unknown') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, ValueError)) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.utils.config.warnings') def test_config_mode_batch_open_configuration_ex(self, mock_warnings, mock_exec): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.utils.config.warnings') def test_config_mode_private_open_configuration_ex(self, mock_warnings, mock_exec): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode='private') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(private=True) def test__enter__private_exception_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.open_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, Config.__enter__, Config(self.dev, mode='private')) def test__enter__private_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='private')) def test__enter__dyanamic_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='dynamic')) def test__enter__batch_exception_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.open_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, Config.__enter__, Config(self.dev, mode='batch')) def test__enter__batch_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='batch')) def _read_file(self, fname): fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() # specific to multi rpc error if fname == 'commit-configuration.xml': raw = etree.XML(foo) obj = RPCReply(raw) obj.parse() if ncclient.__version__ > (0, 4, 5): raise RPCError(etree.XML(foo), errs=obj._errors) else: raise RPCError(etree.XML(foo)) def _mock_manager(self, *args, **kwargs): if kwargs: device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: return self._read_file(args[0].tag + '.xml')
rollback_response = conf.rollback() print("Rollback config ... {}".format(rollback_response)) load_result = conf.load(command, format='set', ignore_warning=['statement not found']) load_result_tostring = etree.tostring(load_result, encoding='unicode', pretty_print=True) print("Load command ... \n{}".format(load_result_tostring)) commit_check_result = conf.commit_check() print("Check result ... {}".format(commit_check_result)) commit_result = conf.commit() print("Commit ... {}".format(commit_result)) unlock_response = conf.unlock() print("Unlocking config ... {}".format(unlock_response)) close_response = dev.close() print("Close connection ... {}".format( "Success" if not open_result.connected else "Failed")) print("DONE") except Exception, e: print(e)
# Copyright 2017, Juniper Networks Pvt Ltd. # All rights reserved. # from jnpr.junos import Device from jnpr.junos.utils.config import Config with Device(host='X.X.X.X', user='******', password='******', mode='telnet', port='XX', gather_facts=True) as dev: cu = Config(dev) cu.load(path='/var/tmp/mx001-svn.conf', format='text', overwrite=True) print "Configuration Committed:", cu.commit() # Script output # automation@automation:~/pyezcookbook$ python initialconf.py # Configuration Committed: True
</name-server> </system> """ for src_node, mgmt_ip in dev_mgmt.items(): dev = Device(host=mgmt_ip, user=login_username) dev.open() print("=" * 20 + src_node + "=" * 20) show_dns_conf = dev.rpc.get_config(filter_xml=xml_filter) show_dns_conf_text = dev.rpc.get_config(filter_xml=xml_filter, options={'format': 'text'}) if (show_dns_conf.find('system/name-server') is None): print("NO DNS configured, DNS configuration to be pushed!") conf = Config(dev) conf.lock() conf.load(setconf_dns) conf.commit() conf.unlock() print("DNS configuration pushed successfully!") else: print("DNS configuration found as below (formal XML):") print( etree.tostring(show_dns_conf_text, encoding='unicode', pretty_print=True)) print("=" * 20 + "=" * len(src_node) + "=" * 20) dev.close()
#----------------------------------------------------------------------------------------------------------------------- # DESCRIPTION: # Use PyEZ to enable LLDP on a subset of interfaces for a specific device. # # CONTACT: [email protected]; [email protected]; [email protected]; [email protected]; [email protected] # # CREATED: 2015-11-11 # # VERSION: 1 # # USAGE: enable_lldp.py # ----------------------------------------------------------------------------------------------------------------------- from jnpr.junos import Device # import the class Device from jnpr.junos.utils.config import Config # import the class Config import yaml s=open('configuration_management/interfaces.yml').read() #s is a string my_variables=yaml.load(s) # my_variables is a dictionary a_device=Device (host="172.30.179.113", user="******", password="******") a_device.open() cfg=Config(a_device) # cfg is the candidate configuration cfg.rollback() cfg.load(template_path='configuration_management/template_lldp.j2', template_vars=my_variables, format='set') cfg.pdiff() cfg.commit()
#pprint( device.facts ) device.bind(cfg=Config) try: device.rpc.open_configuration(private=True) except jnpr.junos.exception.RpcError as e: if 'severity: warning' in str(e): print str(e) pass else: raise for line in open("fila"): elhay = Config(device) set_cmd = line elhay.load(set_cmd, format='set') elhay.pdiff() elhay.commit() #for line in open("fila"): # print device.cli(line) #device.cfg.load(template_path=template, template_vars=customer) #device.bind(cu=Config) #device.rpc.open_configuration(private=True,normalize=True) #device.cu.load("set system host-name r0") #device.cu.commit() #device.rpc.close_configuration() device.close()
class JunosDevice(BaseDevice): """Juniper JunOS Device Implementation.""" vendor = "juniper" def __init__(self, host, username, password, *args, **kwargs): super().__init__(host, username, password, *args, device_type="juniper_junos_netconf", **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativeSW(self.native) def _file_copy_local_file_exists(self, filepath): return os.path.isfile(filepath) def _file_copy_local_md5(self, filepath, blocksize=2**20): if self._file_copy_local_file_exists(filepath): m = hashlib.md5() # nosec with open(filepath, "rb") as f: buf = f.read(blocksize) while buf: m.update(buf) buf = f.read(blocksize) return m.hexdigest() def _file_copy_remote_md5(self, filename): return self.fs.checksum(filename) def _get_interfaces(self): eth_ifaces = EthPortTable(self.native) eth_ifaces.get() loop_ifaces = LoopbackTable(self.native) loop_ifaces.get() ifaces = eth_ifaces.keys() ifaces.extend(loop_ifaces.keys()) return ifaces def _image_booted(self, image_name, **vendor_specifics): raise NotImplementedError def _uptime_components(self, uptime_full_string): match_days = re.search(r"(\d+) days?", uptime_full_string) match_hours = re.search(r"(\d+) hours?", uptime_full_string) match_minutes = re.search(r"(\d+) minutes?", uptime_full_string) match_seconds = re.search(r"(\d+) seconds?", uptime_full_string) days = int(match_days.group(1)) if match_days else 0 hours = int(match_hours.group(1)) if match_hours else 0 minutes = int(match_minutes.group(1)) if match_minutes else 0 seconds = int(match_seconds.group(1)) if match_seconds else 0 return days, hours, minutes, seconds def _uptime_to_seconds(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components( uptime_full_string) seconds += days * 24 * 60 * 60 seconds += hours * 60 * 60 seconds += minutes * 60 return seconds def _uptime_to_string(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components( uptime_full_string) return "%02d:%02d:%02d:%02d" % (days, hours, minutes, seconds) def _wait_for_device_reboot(self, timeout=3600): start = time.time() while time.time() - start < timeout: try: self.open() return except: # noqa E722 # nosec pass raise RebootTimeoutError(hostname=self.hostname, wait_time=timeout) def backup_running_config(self, filename): with open(filename, "w") as f: f.write(self.running_config) @property def boot_options(self): return self.os_version def checkpoint(self, filename): self.save(filename) def close(self): if self.connected: self.native.close() def config(self, commands, format="set"): """Send configuration commands to a device. Args: commands (str, list): String with single command, or list with multiple commands. Raises: ConfigLoadError: Issue with loading the command. CommandError: Issue with the command provided, if its a single command, passed in as a string. CommandListError: Issue with a command in the list provided. """ if isinstance(commands, str): try: self.cu.load(commands, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandError(commands, e.message) else: try: for command in commands: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandListError(commands, command, e.message) def config_list(self, commands, format="set"): """Send configuration commands in list format to a device. DEPRECATED - Use the `config` method. Args: commands (list): List with multiple commands. """ warnings.warn("config_list() is deprecated; use config().", DeprecationWarning) self.config(commands, format=format) @property def connected(self): return self.native.connected @property def uptime(self): try: native_uptime_string = self.native.facts["RE0"]["up_time"] except (AttributeError, TypeError): native_uptime_string = None if self._uptime is None: if native_uptime_string is not None: self._uptime = self._uptime_to_seconds(native_uptime_string) return self._uptime @property def uptime_string(self): try: native_uptime_string = self.native.facts["RE0"]["up_time"] except (AttributeError, TypeError): native_uptime_string = None if self._uptime_string is None: self._uptime_string = self._uptime_to_string(native_uptime_string) return self._uptime_string @property def hostname(self): if self._hostname is None: self._hostname = self.native.facts.get("hostname") return self._hostname @property def interfaces(self): if self._interfaces is None: self._interfaces = self._get_interfaces() return self._interfaces @property def fqdn(self): if self._fqdn is None: self._fqdn = self.native.facts.get("fqdn") return self._fqdn @property def model(self): if self._model is None: self._model = self.native.facts.get("model") return self._model @property def os_version(self): if self._os_version is None: self._os_version = self.native.facts.get("version") return self._os_version @property def serial_number(self): if self._serial_number is None: self._serial_number = self.native.facts.get("serialnumber") return self._serial_number def file_copy(self, src, dest=None, **kwargs): if not self.file_copy_remote_exists(src, dest, **kwargs): if dest is None: dest = os.path.basename(src) with SCP(self.native) as scp: scp.put(src, remote_path=dest) if not self.file_copy_remote_exists(src, dest, **kwargs): raise FileTransferError( message= "Attempted file copy, but could not validate file existed after transfer" ) # TODO: Make this an internal method since exposing file_copy should be sufficient def file_copy_remote_exists(self, src, dest=None, **kwargs): if dest is None: dest = os.path.basename(src) local_hash = self._file_copy_local_md5(src) remote_hash = self._file_copy_remote_md5(dest) if local_hash is not None and local_hash == remote_hash: return True return False def install_os(self, image_name, **vendor_specifics): raise NotImplementedError def open(self): if not self.connected: self.native.open() def reboot(self, timer=0, **kwargs): """ Reload the controller or controller pair. Args: timer (int, optional): The time to wait before reloading. Defaults to 0. Example: >>> device = JunosDevice(**connection_args) >>> device.reboot() >>> """ if kwargs.get("confirm"): warnings.warn("Passing 'confirm' to reboot method is deprecated.", DeprecationWarning) self.sw = JunosNativeSW(self.native) self.sw.reboot(in_min=timer) def rollback(self, filename): self.native.timeout = 60 temp_file = NamedTemporaryFile() with SCP(self.native) as scp: scp.get(filename, local_path=temp_file.name) self.cu.load(path=temp_file.name, format="text", overwrite=True) self.cu.commit() temp_file.close() self.native.timeout = 30 @property def running_config(self): return self.show("show config") def save(self, filename=None): if filename is None: self.cu.commit() return temp_file = NamedTemporaryFile() temp_file.write(self.show("show config")) temp_file.flush() with SCP(self.native) as scp: scp.put(temp_file.name, remote_path=filename) temp_file.close() return True def set_boot_options(self, sys): raise NotImplementedError def show(self, commands): """Send configuration commands to a device. Args: commands (str, list): String with single command, or list with multiple commands. Raises: CommandError: Issue with the command provided. CommandListError: Issue with a command in the list provided. """ original_commands_is_str = isinstance(commands, str) if original_commands_is_str: commands = [commands] responses = [] for command in commands: if not command.startswith("show"): if original_commands_is_str: raise CommandError( command, 'Juniper "show" commands must begin with "show".') raise CommandListError( commands, command, 'Juniper "show" commands must begin with "show".') response = self.native.cli(command, warning=False) responses.append(response) if original_commands_is_str: return responses[0] return responses def show_list(self, commands, raw_text=True): """Send show commands in list format to a device. DEPRECATED - Use the `show` method. Args: commands (list): List with multiple commands. """ warnings.warn("show_list() is deprecated; use show().", DeprecationWarning) return self.show(commands) @property def startup_config(self): return self.show("show config")
cu.load( 'set interfaces ge-0/0/23.0 family ethernet-switching native-vlan-id default', format='set') print('set interface ge-0/0/23.0 native vlan to default') for i in range(23): cu.load( 'set interfaces ge-0/0/{0}.0 family ethernet-switching'.format(i), format='set') print('set interface ge-0/0/0 to ge-0/0/22 unit 0 vlan to default') cu.load('delete vlans {0}'.format(default_vlan_name), format='set') print('delete vlan {0}'.format(default_vlan_name)) cu.load('set vlans default description Default_Vlan', format='set') cu.load('set vlans default vlan-id 1', format='set') cu.load('set vlans default l3-interface vlan.1', format='set') print('set vlan default') if cu.commit(confirm=30, timeout=60): print('committed') print( 'warning: you have to commit again in 30 minutes to confirm changes,' ) print(' or it will rollback automatically') else: print('commit check failed') print('') dev.close()
def run(self): self.logfile = open(os.getcwd() + '/' + 'linkfailure_log', 'a') while True: while self.failed() == False: time.sleep(1) # select a router r_number = random.randint(1, len(self.rtr)) - 1 # select a random interface i_number = random.randint(1, len( self.rtr[r_number]['interfaces'])) - 1 #set interfaces ge-1/0/3 disable cmd = 'set interfaces ' + self.rtr[r_number]['interfaces'][ i_number]['name'] + ' disable' dev = Device(host=self.rtr[r_number]['ip'], user='******', password='******') dev.open() dev.timeout = 60 cu = Config(dev) cu.lock() cu.load(cmd, format='set', merge=True) cu.commit() cu.unlock() dev.close() link__data = { 'status': 'failed', 'timestamp': datetime.datetime.fromtimestamp( time.time()).strftime('%a:%H:%M:%S'), 'router_id': self.rtr[r_number]['router_id'], 'router_name': self.rtr[r_number]['name'], 'interface_address': self.rtr[r_number]['interfaces'][i_number]['address'], 'interface_name': self.rtr[r_number]['interfaces'][i_number]['name'] } jd = json.dumps(link__data) self.redis.publish('link_event', jd) self.logfile.write( "Link failed: " + datetime.datetime.fromtimestamp( time.time()).strftime('%a:%H:%M:%S') + " " + self.rtr[r_number]['name'] + " " + self.rtr[r_number]['ip'] + " " + self.rtr[r_number]['interfaces'][i_number]['name'] + "\n") self.logfile.flush() # now repair the link while self.repaired() == False: time.sleep(1) cmd = 'delete interfaces ' + self.rtr[r_number]['interfaces'][ i_number]['name'] + ' disable' dev = Device(host=self.rtr[r_number]['ip'], user='******', password='******') dev.open() dev.timeout = 60 cu = Config(dev) cu.lock() cu.load(cmd, format='set', merge=True) cu.commit() cu.unlock() dev.close() link__data = { 'status': 'healed', 'timestamp': datetime.datetime.fromtimestamp( time.time()).strftime('%a:%H:%M:%S'), 'router_id': self.rtr[r_number]['router_id'], 'router_name': self.rtr[r_number]['name'], 'interface_address': self.rtr[r_number]['interfaces'][i_number]['address'], 'interface_name': self.rtr[r_number]['interfaces'][i_number]['name'] } jd = json.dumps(link__data) self.redis.publish('link_event', jd) self.logfile.write( "Link healed: " + datetime.datetime.fromtimestamp( time.time()).strftime('%a:%H:%M:%S') + " " + self.rtr[r_number]['name'] + " " + self.rtr[r_number]['ip'] + " " + self.rtr[r_number]['interfaces'][i_number]['name'] + "\n") self.logfile.flush()
class JunosDevice(BaseDevice): """Juniper JunOS Device Implementation.""" vendor = "juniper" def __init__(self, host, username, password, *args, **kwargs): super().__init__(host, username, password, *args, device_type="juniper_junos_netconf", **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativeSW(self.native) def _file_copy_local_file_exists(self, filepath): return os.path.isfile(filepath) def _file_copy_local_md5(self, filepath, blocksize=2**20): if self._file_copy_local_file_exists(filepath): m = hashlib.md5() with open(filepath, "rb") as f: buf = f.read(blocksize) while buf: m.update(buf) buf = f.read(blocksize) return m.hexdigest() def _file_copy_remote_md5(self, filename): return self.fs.checksum(filename) def _get_interfaces(self): eth_ifaces = EthPortTable(self.native) eth_ifaces.get() loop_ifaces = LoopbackTable(self.native) loop_ifaces.get() ifaces = eth_ifaces.keys() ifaces.extend(loop_ifaces.keys()) return ifaces def _image_booted(self, image_name, **vendor_specifics): raise NotImplementedError def _uptime_components(self, uptime_full_string): match_days = re.search(r"(\d+) days?", uptime_full_string) match_hours = re.search(r"(\d+) hours?", uptime_full_string) match_minutes = re.search(r"(\d+) minutes?", uptime_full_string) match_seconds = re.search(r"(\d+) seconds?", uptime_full_string) days = int(match_days.group(1)) if match_days else 0 hours = int(match_hours.group(1)) if match_hours else 0 minutes = int(match_minutes.group(1)) if match_minutes else 0 seconds = int(match_seconds.group(1)) if match_seconds else 0 return days, hours, minutes, seconds def _uptime_to_seconds(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components( uptime_full_string) seconds += days * 24 * 60 * 60 seconds += hours * 60 * 60 seconds += minutes * 60 return seconds def _uptime_to_string(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components( uptime_full_string) return "%02d:%02d:%02d:%02d" % (days, hours, minutes, seconds) def _wait_for_device_reboot(self, timeout=3600): start = time.time() while time.time() - start < timeout: try: self.open() return except: # noqa E722 pass raise RebootTimeoutError(hostname=self.facts["hostname"], wait_time=timeout) def backup_running_config(self, filename): with open(filename, "w") as f: f.write(self.running_config) @property def boot_options(self): return self.facts["os_version"] def checkpoint(self, filename): self.save(filename) def close(self): if self.connected: self.native.close() def config(self, command, format="set"): try: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandError(command, e.message) def config_list(self, commands, format="set"): try: for command in commands: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandListError(commands, command, e.message) @property def connected(self): return self.native.connected @property def facts(self): if self._facts is None: native_facts = self.native.facts try: native_uptime_string = native_facts["RE0"]["up_time"] except (AttributeError, TypeError): native_uptime_string = None self._facts = { "hostname": native_facts.get("hostname"), "fqdn": native_facts.get("fqdn"), "model": native_facts.get("model"), "uptime": None, "uptime_string": None, "serial_number": native_facts.get("serialnumber"), "interfaces": self._get_interfaces(), "vendor": self.vendor, "version": native_facts.get("version"), } # TODO: Use a more reliable method for determining uptime (show system uptime) if native_uptime_string is not None: self._facts["uptime"] = self._uptime_to_seconds( native_uptime_string) self._facts["uptime_string"] = self._uptime_to_string( native_uptime_string) return self._facts def file_copy(self, src, dest=None, **kwargs): if not self.file_copy_remote_exists(src, dest, **kwargs): if dest is None: dest = os.path.basename(src) with SCP(self.native) as scp: scp.put(src, remote_path=dest) if not self.file_copy_remote_exists(src, dest, **kwargs): raise FileTransferError( message= "Attempted file copy, but could not validate file existed after transfer" ) # TODO: Make this an internal method since exposing file_copy should be sufficient def file_copy_remote_exists(self, src, dest=None, **kwargs): if dest is None: dest = os.path.basename(src) local_hash = self._file_copy_local_md5(src) remote_hash = self._file_copy_remote_md5(dest) if local_hash is not None and local_hash == remote_hash: return True return False def install_os(self, image_name, **vendor_specifics): raise NotImplementedError def open(self): if not self.connected: self.native.open() def reboot(self, timer=0, confirm=False): self.sw = JunosNativeSW(self.native) if confirm: self.sw.reboot(in_min=timer) else: print("Need to confirm reboot with confirm=True") def rollback(self, filename): self.native.timeout = 60 temp_file = NamedTemporaryFile() with SCP(self.native) as scp: scp.get(filename, local_path=temp_file.name) self.cu.load(path=temp_file.name, format="text", overwrite=True) self.cu.commit() temp_file.close() self.native.timeout = 30 @property def running_config(self): return self.show("show config") def save(self, filename=None): if filename is None: self.cu.commit() return temp_file = NamedTemporaryFile() temp_file.write(self.show("show config")) temp_file.flush() with SCP(self.native) as scp: scp.put(temp_file.name, remote_path=filename) temp_file.close() return True def set_boot_options(self, sys): raise NotImplementedError def show(self, command, raw_text=True): if not raw_text: raise ValueError('Juniper only supports raw text output. \ Append " | display xml" to your commands for a structured string.' ) if not command.startswith("show"): raise CommandError( command, 'Juniper "show" commands must begin with "show".') return self.native.cli(command, warning=False) def show_list(self, commands, raw_text=True): responses = [] for command in commands: responses.append(self.show(command, raw_text=raw_text)) return responses @property def startup_config(self): return self.show("show config")
class NetconfConnection(AbstractConnection): ''' Netconf connection class ''' def __init__(self, host, username='******', password='******', logger=None, **kwargs): self.host = host self.username = username self.password = password self.handle = None self.logger = kwargs.get('logger', contrail_logging.getLogger(__name__)) self.config_handle = None self.mode = kwargs.get('mode') self.port = kwargs.get('port',None) def connect(self): if self.port: self.handle = Device(host=self.host, user=self.username, password=self.password, mode=self.mode, port=self.port) else: self.handle = Device(host=self.host, user=self.username, password=self.password, mode=self.mode) try: self.handle.open(gather_facts=False) self.config_handle = Config(self.handle) except (ConnectAuthError,ConnectRefusedError, ConnectTimeoutError, ConnectError) as e: self.logger.exception(e) return self.handle # end connect def disconnect(self): with gevent.Timeout(15.0, False): self.handle.close() def show_version(self): return self.handle.show_version() def zeroize(self): with gevent.Timeout(15.0, False): try: self.handle.zeroize() except Exception as e: pass def get_config(self, mode='set',filter=None): configs = self.handle.rpc.get_config(filter_xml=filter,options={'database' : 'committed', 'format': mode}) return configs.text def get_interfaces(self, terse=True): output = self.handle.rpc.get_interface_information(terse=terse) return EtreeToDict('physical-interface').get_all_entry(output) def get_bgp_peer_count(self): output = self.handle.rpc.get_bgp_summary_information() return EtreeToDict('peer-count').get_all_entry(output) def config(self, stmts=[], commit=True, merge=True, overwrite=False, path=None, ignore_errors=False, timeout=30, url=None): if url: try: self.config_handle.load(url=url,format='text',overwrite=True) self.config_handle.commit(override=True) except RpcTimeoutError as e: self.logger.debug('Exception %s ignored' % (e)) return (True, None) elif path: self.config_handle.load(path=path, overwrite=overwrite, timeout=timeout) else: for stmt in stmts: try: self.config_handle.load(stmt, format='set', merge=True) except ConfigLoadError as e: if ignore_errors: self.logger.debug('Exception %s ignored' % (e)) self.logger.exception(e) else: raise e if commit: try: self.config_handle.commit(timeout=timeout) except CommitError as e: self.logger.exception(e) return (False,e) return (True, None) def configure_interface(self, pi_name, address, mask): stmt = "set interfaces %s unit 0 family inet address %s/%s"%( pi_name, address, mask) self.config([stmt]) def delete_interface(self, pi_name): stmt = "delete interfaces %s unit 0"%pi_name self.config([stmt]) def restart(self, process_name): #TODO Not sure of apis other than cli self.handle.cli('restart %s' % (process_name)) def get_mac_address(self, interface): # Use physical interface interface = interface.split('.')[0] xml_resp = self.handle.rpc.get_interface_information(interface_name=interface) mac_address = xml_resp.findtext( 'physical-interface/current-physical-address') return mac_address.rstrip('\n').lstrip('\n') # end get_mac_address def get_mac_in_arp_table(self, ip_address): # From 'show arp' output, get the MAC address # of a IP xml_resp = self.handle.rpc.get_arp_table_information(no_resolve=True) arp_entries = xml_resp.findall('arp-table-entry') for arp_entry in arp_entries: if arp_entry.find('ip-address').text.strip() == ip_address: mac = arp_entry.find('mac-address').text.strip() self.logger.debug('Found MAC %s for IP %s in arp table of ' '%s' % (mac, ip_address, self.host)) return mac self.logger.warn('IP %s not found in arp table of %s' % ( ip_address, self.host)) return None # end get_mac_in_arp_table def get_assisted_replicated_role(self): output = self.handle.rpc.get_evpn_multicast_snooping_ar_replicators_data() return EtreeToDict('evpn-multicast-snooping-ar-replicators-per-instance').get_all_entry(output) def get_interfaces_vtep(self): output = self.handle.rpc.get_interface_information(interface_name='vtep') return EtreeToDict('physical-interface/logical-interface').get_all_entry(output) def clear_interfaces_statistics(self): return self.handle.rpc.clear_interfaces_statistics_all()
from jnpr.junos import Device from jnpr.junos.utils.config import Config from getpass import getpass srx1 = Device(host="srx1.lasthop.io", user="******", password=getpass()) srx1.open() cfg = Config(srx1) cfg.lock() cfg.load("set system host-name test123", format="set", merge=True) print(cfg.diff()) cfg.commit(comment="Changing the hostname") cfg.unlock()
cu = Config(dev) data = """interfaces { ge-1/0/1 { description "MPLS interface"; unit 0 { family mpls; } } ge-1/0/2 { description "MPLS interface"; unit 0 { family mpls; } } } protocols { mpls { interface ge-1/0/1; interface ge-1/0/2; } } """ cu.load(data, format='text') cu.pdiff() if cu.commit_check(): cu.commit() else: cu.rollback() dev.close()
class TestConfig(unittest.TestCase): @patch('ncclient.manager.connect') def setUp(self, mock_connect): mock_connect.side_effect = self._mock_manager self.dev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.dev.open() self.conf = Config(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm_true(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=True) self.conf.rpc.commit_configuration\ .assert_called_with(confirmed=True) def test_config_commit_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') def test_config_commit_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(synchronize=True) def test_config_commit_force_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(force_sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(**{'synchronize': True, 'force-synchronize': True}) def test_config_commit_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(timeout=60) self.conf.rpc.commit_configuration\ .assert_called_with(dev_timeout=60) def test_config_commit_full(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(full=True) self.conf.rpc.commit_configuration\ .assert_called_with(full=True) def test_config_commit_detail(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<mockdetail/>' self.assertEqual('<mockdetail/>', self.conf.commit(detail=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}) def test_config_commit_combination(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<moredetail/>' self.assertEqual( '<moredetail/>', self.conf.commit( detail=True, force_sync=True, full=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}, **{'synchronize': True, 'full': True, 'force-synchronize': True}) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_xml_exception(self, mock_jxml): class MyException(Exception): xml = etree.fromstring('<test/>') self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(CommitError, self.conf.commit) def test_config_commit_exception(self): class MyException(Exception): pass self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(MyException, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with( {'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format_set(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') def test_config_load_len_with_format_xml(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') xmldata = """<snmp> <community> <name>iBGP</name> </community> </snmp>""" self.assertEqual(self.conf.load(xmldata, format='xml'), 'rpc_contents') def test_config_load_len_with_format_text(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') textdata = """policy-options { prefix-list TEST1-NETS { 100.0.0.0/24; } policy-statement TEST1-NETS { term TEST1 { from { prefix-list TEST1-NETS; } then accept; } term REJECT { then reject; } } }""" self.assertEqual(self.conf.load(textdata), 'rpc_contents') def test_config_load_with_format_json(self): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load('test.json', format='json') self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') @patch(builtin_string + '.open') def test_config_load_with_format_json_from_file_ext(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path='test.json') self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') @patch(builtin_string + '.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch(builtin_string + '.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch(builtin_string + '.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch(builtin_string + '.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') @patch(builtin_string + '.open') def test_config_load_try_load_rpcerror(self, mock_open): ex = ConfigLoadError( rsp=etree.fromstring(( """<load-configuration-results> <rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error> </load-configuration-results>"""))) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(ConfigLoadError, self.conf.load, path='config.conf') @patch(builtin_string + '.open') def test_config_load_try_load_rpctimeouterror(self, mock_open): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.load, path='config.conf') @patch(builtin_string + '.open') def test_config_try_load_exception(self, mock_open): class OtherException(Exception): pass self.conf.rpc.load_config = MagicMock(side_effect=OtherException()) self.assertRaises(OtherException, self.conf.load, path='config.conf') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_template_path(self, mock_etree): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock(return_value='<test/>') self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1) @patch('jnpr.junos.Device.execute') def test_rescue_action_save(self, mock_exec): self.dev.request_save_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('save')) @patch('jnpr.junos.Device.execute') def test_rescue_action_get_exception(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock(side_effect=Exception) self.assertTrue(self.conf.rescue('get') is None) @patch('jnpr.junos.Device.execute') def test_rescue_action_get(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock() self.dev.rpc.get_rescue_information.return_value = 1 self.assertEqual(self.conf.rescue('get', format='xml'), 1) @patch('jnpr.junos.Device.execute') def test_rescue_action_delete(self, mock_exec): self.dev.rpc.request_delete_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('delete')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload(self, mock_exec): self.dev.rpc.load_configuration = MagicMock() self.dev.rpc.load_configuration.return_value = True self.assertTrue(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload_exception(self, mock_exec): self.dev.rpc.load_configuration = MagicMock(side_effect=Exception) self.assertFalse(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_unsupported_action(self, mock_exec): self.assertRaises(ValueError, self.conf.rescue, 'abc') def test_config_load_lset_from_rexp_xml(self): self.conf.rpc.load_config = MagicMock() conf = """<snmp><name>iBGP</name></snmp>""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_lset_from_rexp_set(self): self.conf.rpc.load_config = MagicMock() conf = """set system domain-name englab.nitin.net""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_delete(self): self.conf.rpc.load_config = MagicMock() conf = """delete snmp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_conf(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_lset_from_rexp_conf_replace_tag(self): self.conf.rpc.load_config = MagicMock() conf = """replace: snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'replace') def test_config_load_lset_from_rexp_error(self): self.conf.rpc.load_config = MagicMock() conf = """test>""" self.assertRaises(RuntimeError, self.conf.load, conf) def test_load_merge_true(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf, merge=True) self.assertFalse('action' in self.conf.rpc.load_config.call_args[1]) def test_commit_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit) def test_commit_check_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit_check) def test_commit_configuration_multi_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) try: self.dev.rpc.commit_configuration() except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) if ncclient.__version__ > (0, 4, 5): self.assertEqual(ex.message, "error: interface-range 'axp' is not defined\n" "error: interface-ranges expansion failed") self.assertEqual(ex.errs, [{'source': None, 'message': "interface-range 'axp' is not defined", 'bad_element': None, 'severity': 'error', 'edit_path': None}, {'source': None, 'message': 'interface-ranges expansion failed', 'bad_element': None, 'severity': 'error', 'edit_path': None}]) else: self.assertEqual(ex.message, "interface-range 'axp' is not defined") @patch('jnpr.junos.utils.config.Config.lock') @patch('jnpr.junos.utils.config.Config.unlock') def test_config_mode_exclusive(self, mock_unlock, mock_lock): with Config(self.dev, mode='exclusive') as conf: conf.rpc.load_config = MagicMock() conf.load('conf', format='set') self.assertTrue(mock_lock.called and mock_unlock.called) @patch('jnpr.junos.Device.execute') def test_config_mode_batch(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch('jnpr.junos.Device.execute') def test_config_mode_private(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='private') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(private=True) @patch('jnpr.junos.Device.execute') def test_config_mode_dynamic(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='dynamic') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(dynamic=True) @patch('jnpr.junos.Device.execute') def test_config_mode_close_configuration_ex(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() ex = RpcError(rsp='ok') ex.message = 'Configuration database is not open' self.dev.rpc.close_configuration = MagicMock(side_effect=ex) try: with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) self.assertTrue(self.dev.rpc.close_configuration.called) @patch('jnpr.junos.Device.execute') def test_config_mode_undefined(self, mock_exec): try: with Config(self.dev, mode='unknown') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, ValueError)) @patch('jnpr.junos.Device.execute') def test_config_mode_batch_open_configuration_ex(self, mock_exec): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch('jnpr.junos.Device.execute') def test_config_mode_private_open_configuration_ex(self, mock_exec): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode='private') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(private=True) def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() # specific to multi rpc error if fname == 'commit-configuration.xml': raw = etree.XML(foo) obj = RPCReply(raw) obj.parse() if ncclient.__version__ > (0, 4, 5): raise RPCError(etree.XML(foo), errs=obj._errors) else: raise RPCError(etree.XML(foo)) def _mock_manager(self, *args, **kwargs): if kwargs: device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: return self._read_file(args[0].tag + '.xml')
a_device = getdevice(ip_addr, user, pwd) myconfig = Config(a_device) myconfig.lock() print "Test using set method" print "-" * 30 myconfig.load("set system host-name pytest123", format="set", merge=True) print "Print difference" print myconfig.diff() print '-' * 30 print 'Rollback' myconfig.rollback(0) print "Test using config method" print "-" * 30 myconfig.load(path="test_hostname.conf", format="text", merge=True) print "Print difference" print myconfig.diff() print "commit changes" myconfig.commit(comment="Testing conf commit BE") print "Test using xml method" print "-" * 30 myconfig.load(path="test_hostname.xml", format="xml", merge=True) print "Print difference" print myconfig.diff() print "commit changes" myconfig.commit(comment="Testing xml commit BE") myconfig.unlock()
def get_vlan_vni(message, **kwargs): # Get previous values temp = re.search(r'set vlans v(\d+) vxlan vni (\d+)', message) vni_num = int(temp.group(2)) vlan_num = int(temp.group(1)) print(kwargs, file=sys.stderr) r = requests.get('http://config-server:9000/api/v2/device-group/%s/' % kwargs['device_group'], verify=False) #print(r.status_code, file=sys.stderr) if r.status_code != 200: return False device_group_info = r.json() devices_list = device_group_info['devices'] d = requests.get('http://config-server:9000/api/v2/device/%s/' % kwargs['device_id'], verify=False) if d.status_code != 200: return False device_info = d.json() device_name = device_info['device-id'] for dev in devices_list: if dev != device_name: rd = requests.get('http://config-server:9000/api/v2/device/%s/' % dev, verify=False) if r.status_code != 200: return False devices_info = rd.json() hostname = devices_info['host'] userid = devices_info['authentication']['password']['username'] password = devices_info['authentication']['password']['password'] dev = Device(host=hostname, user=userid, password=password, normalize=True) dev.open() sw = dev.cli("show vlans v%s" % vlan_num, warning=False) try: tmp = re.search(r'default-switch\s+v(\d*)\s+', sw) vlan = int(tmp.group(1)) except: vlan = None print(vlan) if (vlan is vlan_num): print("VNI configuration exists") else: cu = Config(dev) config = """ set vlans v{0} vlan-id {0} set vlans v{0} vxlan vni {1} set vlans v{0} l3-interface irb.{0} set vlans v{0} description "Tenant_1 - brdige domain id {0}" set protocols evpn extended-vni-list {1} set policy-options policy-statement OVERLAY-IMPORT term vni-Tenant_1-v{0} from community com-vni-Tenant_1-v{0} set policy-options policy-statement OVERLAY-IMPORT term vni-Tenant_1-v{0} then accept set policy-options community com-vni-Tenant_1-v{0} members target:1:{0} set policy-options policy-statement TENANT_1-EXPORT term vni-Tenant_1-v{0} then community add com-vni-Tenant_1-v{0} set policy-options policy-statement TENANT_1-EXPORT term vni-Tenant_1-v{0} then accept set policy-options policy-statement TENANT_1-EXPORT term vni-Tenant_1-v{0} from interface irb.{0} set policy-options policy-statement TENANT_1-IMPORT term vni-Tenant_1-v{0} from community com-vni-Tenant_1-v{0} set policy-options policy-statement TENANT_1-IMPORT term vni-Tenant_1-v{0} then accept """.format(vlan_num, vni_num) cu.load(config, format='set') if cu.commit_check(): res = cu.commit() print("Added config") else: print("commit check failed") return False else: print("Local device") return True
def push_config(conf_string, ip, user, pw): dev = get_device_reference(ip, user, pw) # try to determine the format of our config_string config_format = 'set' if re.search(r'^\s*<.*>$', conf_string, re.MULTILINE): config_format = 'xml' elif re.search(r'^\s*(set|delete|replace|rename)\s', conf_string): config_format = 'set' elif re.search(r'^[a-z:]*\s*\w+\s+{', conf_string, re.I) and re.search( r'.*}\s*$', conf_string): config_format = 'text' logger.debug("using format: " + config_format) cu = Config(dev) try: cu.lock() except LockError as le: logger.debug("Could not lock database!") logger.debug(str(le)) dev.close() return False try: cu.load(conf_string, format=config_format) except Exception as e: logger.debug("Could not load configuration") logger.debug(str(e)) dev.close() return False diff = cu.diff() logger.debug(diff) if diff is not None: try: cu.commit_check() logger.debug("Committing config!") cu.commit(comment="Commit via wistar") except CommitError as ce: logger.debug("Could not load config!") cu.rollback() logger.debug(repr(ce)) return False else: # nothing to commit logger.debug("Nothing to commit - no diff found") return True try: logger.debug("Unlocking database!") cu.unlock() except UnlockError as ue: logger.debug("Could not unlock database") logger.debug(str(ue)) return False logger.debug("Closing device handle") dev.close() return True
def main(args, loglevel): logging.basicConfig(format="%(levelname)s: %(message)s", level=loglevel) # # Do template-based config changes # # Open connection logging.info('Opening connection to {0} as {1}...'.format(args.host, args.user)) dev = Device(args.host, user=args.user) try: dev.open() except Exception as err: logging.error('Unable to connect to device {0},'.format(args.host) + \ ' aborting! Error: {0}'.format(err)) return False # Bind config object to device conf = Config(dev) # Parse options for config template, if present if args.data: data = json.loads(args.data) else: data = {} # Lock configuration to make sure noone else alter it at the same time try: conf.lock() except LockError: logging.error('Unable to lock configuration! Aborting.') dev.close() return False # Push template-based change to device logging.info('Pushing configuration change to device {0}...'.format(args.host)) try: conf.load(template_path=args.templatefile, template_vars=data) except ValueError as err: logging.error('Error when pushing configuration change: ' + \ '{0}'.format(err.message)) except Exception as err: if err.rsp.find('.//ok') is None: rpc_msg = err.rsp.findtext('.//error-message') logging.error('Unable to load configuration changes on device: ' + \ '{0}'.format(rpc_msg)) else: logging.error('Unable to load configuration changes on device.') # Close device and return failure dev.close() return False # Commit changes to device try: conf.commit() except CommitError: logging.error('Unable to commit configuration!') dev.close() return False # Unlock configuration after change try: conf.unlock() except UnlockError: logging.error('Unable to unlock configuration, exiting.') dev.close() # Return success logging.info('Finished configuration change of {0} successfully.'.format(args.host)) return True
fh = fp = open('hosts.txt', 'r') line = fp.readline() while line: h = line.split(" ") hosts[h[0]]=h[1] line = fp.readline() cfbase=args.fname jfile = "jtemplates/"+cfbase+".j2" for x in hosts.keys(): '''Connect to device''' print 'Connecting to {0}...'.format(x) dev = Device(host=hosts[x], user=args.username, password=args.password) dev.open(gather_facts=False) cfg = Config(dev) yfile = "ytemplates/"+x+"_"+cfbase+".yaml" s=open(yfile).read() myvars=yaml.load(s) cfg.load(template_path=str(jfile), template_vars=myvars, format='set') if cfg.commit_check(): if cfg.commit: print 'Committing...' cfg.commit(timeout=300) print 'Successfully Committed' else: print 'Commit Failed' else: print 'Commit Check Failed' dev.close()
description "MPLS interface"; unit 0 { family mpls; } } } """ cu.load(data, format='text') print "\nconfig# show | compare" cu.pdiff() if cu.commit_check(): print "\nCommiting..\n" cu.commit(comment="Configuring ge-1/0/1 interfaces", detail=True) else: cu.rollback() print "cli> show configuration interfaces", dev.cli( "show configuration interfaces", warning=False) print "Rolling back the configuration" cu.rollback(rb_id=1) cu.commit(detail=True) print "cli> show configuration interfaces", dev.cli( "show configuration interfaces", warning=False) dev.close()
class Netconf(object): def __init__(self): if not HAS_PYEZ: raise NetworkError( msg= 'junos-eznc >= 1.2.2 is required but does not appear to be installed. ' 'It can be installed using `pip install junos-eznc`') if not HAS_JXMLEASE: raise NetworkError( msg='jxmlease is required but does not appear to be installed. ' 'It can be installed using `pip install jxmlease`') self.device = None self.config = None self._locked = False self._connected = False self.default_output = 'xml' def raise_exc(self, msg): if self.device: if self._locked: self.config.unlock() self.disconnect() raise NetworkError(msg) def connect(self, params, **kwargs): host = params['host'] kwargs = dict() kwargs['port'] = params.get('port') or 830 kwargs['user'] = params['username'] if params['password']: kwargs['passwd'] = params['password'] if params['ssh_keyfile']: kwargs['ssh_private_key_file'] = params['ssh_keyfile'] kwargs['gather_facts'] = False try: self.device = Device(host, **kwargs) self.device.open() except ConnectError: exc = get_exception() self.raise_exc('unable to connect to %s: %s' % (host, str(exc))) self.config = Config(self.device) self._connected = True def disconnect(self): try: self.device.close() except AttributeError: pass self._connected = False ### Command methods ### def run_commands(self, commands): responses = list() for cmd in commands: meth = getattr(self, cmd.args.get('command_type')) responses.append(meth(str(cmd), output=cmd.output)) for index, cmd in enumerate(commands): if cmd.output == 'xml': responses[index] = etree.tostring(responses[index]) elif cmd.args.get('command_type') == 'rpc': responses[index] = str(responses[index].text).strip() return responses def cli(self, commands, output='xml'): '''Send commands to the device.''' try: return self.device.cli(commands, format=output, warning=False) except (ValueError, RpcError): exc = get_exception() self.raise_exc('Unable to get cli output: %s' % str(exc)) def rpc(self, command, output='xml'): name, kwargs = rpc_args(command) meth = getattr(self.device.rpc, name) reply = meth({'format': output}, **kwargs) return reply ### Config methods ### def get_config(self, config_format="text"): if config_format not in SUPPORTED_CONFIG_FORMATS: self.raise_exc(msg='invalid config format. Valid options are ' '%s' % ', '.join(SUPPORTED_CONFIG_FORMATS)) ele = self.rpc('get_configuration', output=config_format) if config_format == 'text': return str(ele.text).strip() else: return ele def load_config(self, config, commit=False, replace=False, confirm=None, comment=None, config_format='text'): if replace: merge = False overwrite = True else: merge = True overwrite = False if overwrite and config_format == 'set': self.raise_exc( 'replace cannot be True when config_format is `set`') self.lock_config() try: candidate = '\n'.join(config) self.config.load(candidate, format=config_format, merge=merge, overwrite=overwrite) except ConfigLoadError: exc = get_exception() self.raise_exc('Unable to load config: %s' % str(exc)) diff = self.config.diff() self.check_config() if all((commit, diff)): self.commit_config(comment=comment, confirm=confirm) self.unlock_config() return diff def save_config(self): raise NotImplementedError ### end of Config ### def get_facts(self, refresh=True): if refresh: self.device.facts_refresh() return self.device.facts def unlock_config(self): try: self.config.unlock() self._locked = False except UnlockError: exc = get_exception() raise NetworkError('unable to unlock config: %s' % str(exc)) def lock_config(self): try: self.config.lock() self._locked = True except LockError: exc = get_exception() raise NetworkError('unable to lock config: %s' % str(exc)) def check_config(self): if not self.config.commit_check(): self.raise_exc(msg='Commit check failed') def commit_config(self, comment=None, confirm=None): try: kwargs = dict(comment=comment) if confirm and confirm > 0: kwargs['confirm'] = confirm return self.config.commit(**kwargs) except CommitError: exc = get_exception() raise NetworkError('unable to commit config: %s' % str(exc)) def confirm_commit(self, checkonly=False): try: resp = self.rpc('get_commit_information') needs_confirm = 'commit confirmed, rollback' in resp[0][4].text if checkonly: return needs_confirm return self.commit_config() except IndexError: # if there is no comment tag, the system is not in a commit # confirmed state so just return pass def rollback_config(self, identifier, commit=True, comment=None): self.lock_config() try: self.config.rollback(identifier) except ValueError: exc = get_exception() self.raise_exc('Unable to rollback config: $s' % str(exc)) diff = self.config.diff() if commit: self.commit_config(comment=comment) self.unlock_config() return diff
device.bind(cfg=Config) try: device.rpc.open_configuration(private=True) except jnpr.junos.exception.RpcError as e: if 'severity: warning' in str(e): print str(e) pass else: raise for line in open("fila"): elhay = Config(device) set_cmd = line elhay.load(set_cmd, format='set') elhay.pdiff() elhay.commit() #for line in open("fila"): # print device.cli(line) #device.cfg.load(template_path=template, template_vars=customer) #device.bind(cu=Config) #device.rpc.open_configuration(private=True,normalize=True) #device.cu.load("set system host-name r0") #device.cu.commit() #device.rpc.close_configuration()
for HOST in JUNOS_HOSTS: try: # Open and read the Jinja2 template file with open('Interface_Config.j2', 'r') as TEMPLATE_FH: TEMPLATE_FORMAT = TEMPLATE_FH.read() # Open and read the YAML file with open('Interface_Answ.yml', 'r') as ANSWER_FH: DATA = yaml.load(ANSWER_FH.read()) # Associate TEMPLATE_FORMAT file with Template TEMPLATE = Template(TEMPLATE_FORMAT) # Merge the data with the Template TEMP_CONFIG = TEMPLATE.render(DATA) print "\nResults for device " + HOST print "------------------------------" print TEMP_CONFIG DEVICE = Device(host=HOST, user='******', password='******').open() CONFIG = Config(DEVICE) CONFIG.lock() #CONFIG.load(TEMP_CONFIG, merge=True, format='text') #merge existing config with this config CONFIG.load(TEMP_CONFIG, override=True, format='text') # #CONFIG.load(TEMP_CONFIG, replace=True, format='text') # #CONFIG.load(TEMP_CONFIG, update=True, format='text') #replaces with this config CONFIG.pdiff() CONFIG.commit() CONFIG.unlock() DEVICE.close() except LockError as e: print "The config database was locked!" except ConnectTimeoutError as e: print "Connection time out!"
#!/usr/bin/python ''' Script para hacer un cambio de hosntame ''' from jnpr.junos import Device from jnpr.junos.utils.config import Config import time if __name__ == '__main__': dev = Device(host='192.168.108.199', user='******') dev.open() mi_cfg = Config(dev) mi_cfg.load(path="config_set.set") mi_cfg.commit(confirm=2) time.sleep(2) dev.close()
before_route_table = gather_routes(device) print("") print("4b") print("") f = open("4_conf.txt", "r") new_config = f.read() f.close() device_config.load(new_config, format="text", merge=True) print(device_config.diff()) print("4c") print("") device_config.commit() after_route_table = gather_routes(device) print("route differences:") diff_routes = [] for route in after_route_table.keys(): if not (route in before_route_table.keys()): diff_routes.append(route) pprint(diff_routes) print("") print("4d") print("") delete_config = """
import sys import time import datetime from pprint import pprint from jnpr.junos import Device from jnpr.junos.utils.config import Config from jnpr.junos import exception as EzErrors counter = 0 while True: #Start config mode dev = Device(host='vienne-re0.ultralab.juniper.net', user='******', password='******') dev.open() dev.timeout = 600 cu = Config(dev) cu.rollback(1) cu.commit(timeout=600) counter += 1 print "Round %s" % counter time.sleep(60)
class TestConfig(unittest.TestCase): def setUp(self): self.dev = Device(host='1.1.1.1') self.conf = Config(self.dev) def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit(confirm=True)) def test_config_commit_confirm_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(AttributeError, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with({'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() print self.conf.diff.call_args self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch('__builtin__.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch('__builtin__.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_template_path(self): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.conf.dev.Template.assert_called_with('test.xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock() self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1)
for line in f: vqfx = line.split(" ", 1)[0] if "vqfx" in vqfx and "pfe" not in vqfx: vqfxDict[vqfx] = {} m = re.search('\w*.*ansible_host=(\w*.*?) ', line) host = m.group(1) vqfxDict[vqfx]['host'] = host m = re.search('\w*.*ansible_port=(\w*.*?) ', line) port = m.group(1) vqfxDict[vqfx]['port'] = port print vqfxDict for key, value in vqfxDict.iteritems(): print "\n##### Configuring: " + key + " #####\n" print "host " + value['host'] print "port " + value['port'] dev = Device(host=value['host'], user='******', password='******', port=value['port']) dev.open() pprint(dev.facts) cu = Config(dev) cmd = "set system host-name " + key cu.load(cmd, format='set') cu.commit() dev.close()
a_device.facts from jnpr.junos.utils.config import Config cfg = Config(a_device) cfg.lock() cfg.load("set system host-name pytest", format="set", merge=True) cfg.rollback(0) print cfg.diff() cfg.commit(comment="testing commit comment using PyEZ") '''loading from a file''' cfg.load(path="test_config.conf", format="text", merge=True) '''loading from a file but this time using the replace option''' cfg.load(path="test_replace.conf", format="text", merge=False) '''loading from an .xml file''' cfg.load(path="test_config.xml", format="xml", merge=True)
from jnpr.junos import Device from jnpr.junos.utils.config import Config switch = {'host': '10.10.10.150', 'user': '******', 'pw': ''} device = Device(host=switch['host'], user=switch['user'], password=switch['pw']) device.open() config = Config(device) payload = """vlans{ vlan101{ vlan-id 101; } } """ config.lock() config.load(payload, format='text') config.pdiff() if config.commit_check() == True: config.commit() else: config.rollback() config.unlock() device.close()
def update_keychain(): """ Update the keychain with information from the checks """ # Check that no private or exclusive configs are in use for router in cfg["HOSTS"]: logger.info(f"Checking configuration lock on {router}") try: with Device( host=router, user=cfg["USER"], ssh_private_key_file=cfg["KEY"], port=22, ) as dev: conf = Config(dev, mode="exclusive") conf.commit_check() except CommitError as exc: logger.error(f"Configuration lock error, {exc}") sys.exit(2) except Exception as exc: logger.error(f"Error, {exc}") sys.exit(2) with open("temp.j2", mode="w") as twr: for index in range(31): if index >= int(used_id[0]): twr.write( f'set security authentication-key-chains key-chain {cfg["KEYCHAIN-NAME"]} key {index+1} secret {{{{CAK{index}}}}}\n' ) twr.write( f'set security authentication-key-chains key-chain {cfg["KEYCHAIN-NAME"]} key {index+1} key-name {{{{CKN{index}}}}}\n' ) twr.write( f'set security authentication-key-chains key-chain {cfg["KEYCHAIN-NAME"]} key {index+1} start-time "{{{{ROLL{index}}}}}"\n' ) continue twr.write( f'set security authentication-key-chains key-chain {cfg["KEYCHAIN-NAME"]} key {index} secret {{{{CAK{index}}}}}\n' ) twr.write( f'set security authentication-key-chains key-chain {cfg["KEYCHAIN-NAME"]} key {index} key-name {{{{CKN{index}}}}}\n' ) twr.write( f'set security authentication-key-chains key-chain {cfg["KEYCHAIN-NAME"]} key {index} start-time "{{{{ROLL{index}}}}}"\n' ) with open("temp.j2") as t_fh: t_format = t_fh.read() template = Template(t_format) if cfg["DEBUG"]: logger.info(template.render(keychain_data)) for router in cfg["HOSTS"]: logger.info(f"Configuring {router}") try: with Device( host=router, user=cfg["USER"], ssh_private_key_file=cfg["KEY"], port=22, ) as dev: conf = Config(dev, mode="private") conf.load(template.render(keychain_data), format="set") conf.commit( timeout=120, comment=f'Updated {cfg["KEYCHAIN-NAME"]} keychain', ) committed.append(router) except (ConfigLoadError, CommitError, ConnectError) as exc: logger.error(f"PyEZ configuration exception, {exc}") if committed: rollback_changed(committed, router) else: sys.exit(2) except Exception as exc: logger.critical(f"PyEZ configuration exception, {exc}") sys.exit(2)
cfg.load("set system host-name juniper-test-name", format="set", merge=True) # Show the differences between running-config and candidate config print cfg.diff() # cfg.commit() # Rollback the candidate config changes cfg.rollback(0) # 2. Load new config via 'test_config.conf' file (using curly braces) # Create test_config.conf file first in the currently-running Linux directory cfg.load(path="test_config.conf", format="text", merge=True) # Show the differences between running-config and candidate config print cfg.diff() cfg.rollback(0) # 3. Load new config via 'test_config.xml' file (in XML format) # Create test_config.xml file first in the currently-running Linux directory cfg.load(path="test_config.xml", format="xml", merge=True) # Show the differences between running-config and candidate-config print cfg.diff() # commit will rollback the changes after 1 minute time interval specified below cfg.commit(comment="Testing commit command", confirm=1)
srx2_dev.open() route_t = gather_routes(srx2_dev) print("Route table before change:") print(route_t.keys()) srx2_cfg = Config(srx2_dev) srx2_cfg.lock() srx2_cfg.load(path="set_juniper.conf", format="text", merge=True) print("Config diff:") print(srx2_cfg.diff()) srx2_cfg.commit() print("Change committed") print("Route table after change:") print(route_t.keys()) srx2_cfg.load(path="del_juniper.conf", format="set", merge=True) print("Config diff:") print(srx2_cfg.diff()) srx2_cfg.commit() print("Route table change reverted:") print(route_t.keys())
class TestConfig(unittest.TestCase): def setUp(self): self.dev = Device(host='1.1.1.1') self.conf = Config(self.dev) def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm_true(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=True) self.conf.rpc.commit_configuration\ .assert_called_with(confirmed=True) def test_config_commit_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') def test_config_commit_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(synchronize=True) def test_config_commit_force_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(force_sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(**{'synchronize': True, 'force-synchronize': True}) def test_config_commit_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(timeout=60) self.conf.rpc.commit_configuration\ .assert_called_with(dev_timeout=60) def test_config_commit_full(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(full=True) self.conf.rpc.commit_configuration\ .assert_called_with(full=True) def test_config_commit_detail(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<mockdetail/>' self.assertEqual('<mockdetail/>', self.conf.commit(detail=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}) def test_config_commit_combination(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<moredetail/>' self.assertEqual('<moredetail/>', self.conf.commit(detail=True, force_sync=True, full=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}, **{'synchronize': True, 'full': True, 'force-synchronize': True}) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(AttributeError, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with( {'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format_set(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') def test_config_load_len_with_format_xml(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') xmldata = """<snmp> <community> <name>iBGP</name> </community> </snmp>""" self.assertEqual(self.conf.load(xmldata, format='xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch('__builtin__.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch('__builtin__.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') @patch('__builtin__.open') def test_config_load_try_load_rpcerror(self, mock_open): ex = ConfigLoadError( rsp=etree.fromstring(( """<load-configuration-results> <rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error> </load-configuration-results>"""))) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(ConfigLoadError, self.conf.load, path='config.conf') @patch('__builtin__.open') def test_config_try_load_exception(self, mock_open): class OtherException(Exception): pass self.conf.rpc.load_config = MagicMock(side_effect=OtherException()) self.assertRaises(OtherException, self.conf.load, path='config.conf') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_template_path(self, mock_etree): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock(return_value='<test/>') self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1) @patch('jnpr.junos.Device.execute') def test_rescue_action_save(self, mock_exec): self.dev.request_save_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('save')) @patch('jnpr.junos.Device.execute') def test_rescue_action_get_exception(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock(side_effect=Exception) self.assertTrue(self.conf.rescue('get') is None) @patch('jnpr.junos.Device.execute') def test_rescue_action_get(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock() self.dev.rpc.get_rescue_information.return_value = 1 self.assertEqual(self.conf.rescue('get', format='xml'), 1) @patch('jnpr.junos.Device.execute') def test_rescue_action_delete(self, mock_exec): self.dev.rpc.request_delete_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('delete')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload(self, mock_exec): self.dev.rpc.load_configuration = MagicMock() self.dev.rpc.load_configuration.return_value = True self.assertTrue(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload_exception(self, mock_exec): self.dev.rpc.load_configuration = MagicMock(side_effect=Exception) self.assertFalse(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_unsupported_action(self, mock_exec): self.assertRaises(ValueError, self.conf.rescue, 'abc') def test_config_load_lset_from_rexp_xml(self): self.conf.rpc.load_config = MagicMock() conf = """<snmp><name>iBGP</name></snmp>""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_lset_from_rexp_set(self): self.conf.rpc.load_config = MagicMock() conf = """set system domain-name englab.nitin.net""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_delete(self): self.conf.rpc.load_config = MagicMock() conf = """delete snmp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_conf(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_lset_from_rexp_conf_replace_tag(self): self.conf.rpc.load_config = MagicMock() conf = """replace: snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'replace') def test_config_load_lset_from_rexp_error(self): self.conf.rpc.load_config = MagicMock() conf = """nitin>""" self.assertRaises(RuntimeError, self.conf.load, conf) def test_load_merge_true(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf, merge=True) self.assertFalse('action' in self.conf.rpc.load_config.call_args[1]) def test_commit_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit)
def main(): # Get script name for logging script = os.path.basename(__file__) # Setup argument parsing for dynamic config parser = argparse.ArgumentParser() parser.add_argument('-interface', required=True) args = parser.parse_args() try: # create device object dev = Device(gather_facts=False) # open connection to device dev.open() # create configuration object cu = Config(dev) # Send syslog from facility external with severity info to say main IF is down jcs.syslog("external.warn", "{0}: Cette interface est tombee".format(script)) # Set configuration data # Stripping out the single quote from argument (this may be a bug that's fixed) conf = "delete interfaces {0} disable".format( args.interface.strip('\'')) try: # Get configuration lock cu.lock() # Load configuration cu.load(conf, format='set') # Commit configuration cu.commit(comment='Event script {0}'.format(script)) # Unlock config cu.unlock() # Catch configuration lock error except LockError: jcs.syslog("external.error", "{0}: Unable to lock configuration".format(script)) dev.close() return # Catch configuration load error # Requires PyEZ >= 1.1.0 # except ConfigLoadError as err: # jcs.syslog("external.error", # "{0}: Unable to load configuration - {1},{2},{3}".format(script, # err.errs['severity'], # err.errs['bad_element'], # err.errs['message'])) # dev.close() # return # Catch configuration commit error # More details are available in PyEZ >= 1.1.0 except CommitError: jcs.syslog("external.error", "{0}: Unable to commit configuration".format(script)) pass # Catch unlock error except UnlockError: jcs.syslog("external.error", "{0}: Unable to commit configuration".format(script)) dev.close() return dev.close() except Exception as err: jcs.syslog("external.error", "{0}: Uncaught excpetion - {1}".format(script, err))
class Netconf(object): def __init__(self): if not HAS_PYEZ: raise NetworkError( msg='junos-eznc >= 1.2.2 is required but does not appear to be installed. ' 'It can be installed using `pip install junos-eznc`' ) if not HAS_JXMLEASE: raise NetworkError( msg='jxmlease is required but does not appear to be installed. ' 'It can be installed using `pip install jxmlease`' ) self.device = None self.config = None self._locked = False self._connected = False self.default_output = 'xml' def raise_exc(self, msg): if self.device: if self._locked: self.config.unlock() self.disconnect() raise NetworkError(msg) def connect(self, params, **kwargs): host = params['host'] kwargs = dict() kwargs['port'] = params.get('port') or 830 kwargs['user'] = params['username'] if params['password']: kwargs['passwd'] = params['password'] if params['ssh_keyfile']: kwargs['ssh_private_key_file'] = params['ssh_keyfile'] kwargs['gather_facts'] = False try: self.device = Device(host, **kwargs) self.device.open() except ConnectError: exc = get_exception() self.raise_exc('unable to connect to %s: %s' % (host, str(exc))) self.config = Config(self.device) self._connected = True def disconnect(self): try: self.device.close() except AttributeError: pass self._connected = False ### Command methods ### def run_commands(self, commands): responses = list() for cmd in commands: meth = getattr(self, cmd.args.get('command_type')) responses.append(meth(str(cmd), output=cmd.output)) for index, cmd in enumerate(commands): if cmd.output == 'xml': responses[index] = xml_to_json(responses[index]) elif cmd.args.get('command_type') == 'rpc': responses[index] = str(responses[index].text).strip() elif 'RpcError' in responses[index]: raise NetworkError(responses[index]) return responses def cli(self, commands, output='xml'): '''Send commands to the device.''' try: return self.device.cli(commands, format=output, warning=False) except (ValueError, RpcError): exc = get_exception() self.raise_exc('Unable to get cli output: %s' % str(exc)) def rpc(self, command, output='xml'): name, kwargs = rpc_args(command) meth = getattr(self.device.rpc, name) reply = meth({'format': output}, **kwargs) return reply ### Config methods ### def get_config(self, config_format="text"): if config_format not in SUPPORTED_CONFIG_FORMATS: self.raise_exc(msg='invalid config format. Valid options are ' '%s' % ', '.join(SUPPORTED_CONFIG_FORMATS)) ele = self.rpc('get_configuration', output=config_format) if config_format == 'text': return unicode(ele.text).strip() else: return ele def load_config(self, config, commit=False, replace=False, confirm=None, comment=None, config_format='text', overwrite=False): if all([replace, overwrite]): self.raise_exc('setting both replace and overwrite to True is invalid') if replace: merge = False overwrite = False elif overwrite: merge = True overwrite = False else: merge = True overwrite = False if overwrite and config_format == 'set': self.raise_exc('replace cannot be True when config_format is `set`') self.lock_config() try: candidate = '\n'.join(config) self.config.load(candidate, format=config_format, merge=merge, overwrite=overwrite) except ConfigLoadError: exc = get_exception() self.raise_exc('Unable to load config: %s' % str(exc)) diff = self.config.diff() self.check_config() if all((commit, diff)): self.commit_config(comment=comment, confirm=confirm) self.unlock_config() return diff def save_config(self): raise NotImplementedError ### end of Config ### def get_facts(self, refresh=True): if refresh: self.device.facts_refresh() return self.device.facts def unlock_config(self): try: self.config.unlock() self._locked = False except UnlockError: exc = get_exception() raise NetworkError('unable to unlock config: %s' % str(exc)) def lock_config(self): try: self.config.lock() self._locked = True except LockError: exc = get_exception() raise NetworkError('unable to lock config: %s' % str(exc)) def check_config(self): if not self.config.commit_check(): self.raise_exc(msg='Commit check failed') def commit_config(self, comment=None, confirm=None): try: kwargs = dict(comment=comment) if confirm and confirm > 0: kwargs['confirm'] = confirm return self.config.commit(**kwargs) except CommitError: exc = get_exception() raise NetworkError('unable to commit config: %s' % str(exc)) def confirm_commit(self, checkonly=False): try: resp = self.rpc('get_commit_information') needs_confirm = 'commit confirmed, rollback' in resp[0][4].text if checkonly: return needs_confirm return self.commit_config() except IndexError: # if there is no comment tag, the system is not in a commit # confirmed state so just return pass def rollback_config(self, identifier, commit=True, comment=None): self.lock_config() try: self.config.rollback(identifier) except ValueError: exc = get_exception() self.raise_exc('Unable to rollback config: $s' % str(exc)) diff = self.config.diff() if commit: self.commit_config(comment=comment) self.unlock_config() return diff
def apply_template(self, template): print self.dev conf_string = template.strip() print conf_string if re.search(r"^<", conf_string): print "Found a encoded string" conf_string = self.unescape(conf_string) print conf_string # try to determine the format of our config_string config_format = "set" if re.search(r"^\s*<.*>$", conf_string, re.MULTILINE): print "found xml style config" config_format = "xml" elif re.search(r"^\s*(set|delete|replace|rename)\s", conf_string): print "found set style config" config_format = "set" elif re.search(r"^[a-z:]*\s*\w+\s+{", conf_string, re.I) and re.search(r".*}\s*$", conf_string): print "found a text style config" config_format = "text" print "using format: " + config_format cu = Config(self.dev) try: cu.lock() except LockError as le: print "Could not lock database!" print str(le) self.dev.close() return "Failed to lock configuration database! %s" % str(le) try: print "loading config" cu.load(conf_string, format=config_format) except Exception as e: print "Could not load configuration" print str(e) try: cu.unlock() except UnlockError as ue: print str(ue) self.dev.close() return "Failed, could not load the configuration template. %s" % str(e) diff = cu.diff() print diff if diff is not None: try: cu.commit_check() print "Committing config!" cu.commit(comment="Commit via a_frame") except CommitError as ce: print "Could not load config! %s" % str(ce) cu.rollback() try: print "Unlocking database!" cu.unlock() except UnlockError as ue: print "Could not unlock database" print str(ue) print repr(ce) self.dev.close() return "Failed, commit check failed. %s" % str(ce) else: # nothing to commit print "Nothing to commit - no diff found" cu.unlock() self.dev.close() return "Nothing to commit!" try: print "Unlocking database!" cu.unlock() except UnlockError as ue: print "Could not unlock database" print str(ue) self.dev.close() return "Committed, but could not unlock db" print "Closing device handle" self.dev.close() return "Completed with diff: %s" % diff