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 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()
def create_port(self, port_name, port_description): """Configures port_name as an access port with port_description configured on IFD """ port_vars={} port_vars['port_name'] = port_name port_vars['port_description'] = port_description cu = Config(self.connection) cu.load(template_path='service-templates/junos/ex/dot1ad-port.conf', template_vars=port_vars, merge=True)
def create_svlan(self, vlan_id, svlan_name, vlan_description): """Create Service VLAN on switch """ svlan_vars={} svlan_vars['vlan_stag'] = vlan_id svlan_vars['svlan_name'] = svlan_name svlan_vars['vlan_description'] = vlan_description cu = Config(self.connection) cu.load(template_path='service-templates/junos/ex/dot1ad-vlan.conf', template_vars=svlan_vars, merge=True)
def bind_service(self, cvlan_id, svlan_name, port_name): """Binds cvlan_id from port_name to svlan_name (one-to-one bundling) """ bind_service_vars={} bind_service_vars['cvlan_id'] = cvlan_id bind_service_vars['svlan_name'] = svlan_name bind_service_vars['port_name'] = port_name cu = Config(self.connection) cu.load(template_path='service-templates/junos/ex/dot1ad-service.conf', template_vars=bind_service_vars, merge=True)
def test_ignore_warning_string_3snf_warnings(self): self.dev._conn.rpc = MagicMock(side_effect= self._mock_manager_3snf_warnings) cu = Config(self.dev) config = """ delete interfaces ge-0/0/0 delete protocols ospf delete policy-options prefix-list foo """ self.assertTrue(cu.load(config, ignore_warning='statement not found'))
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 _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 test_ignore_warning_list_3warn_no_match(self): self.dev._conn.rpc = MagicMock(side_effect= self._mock_manager_3foobar_warnings) cu = Config(self.dev) config = """ delete interfaces ge-0/0/0 delete protcols ospf delete policy-options prefix-list foo """ with self.assertRaises(ConfigLoadError): cu.load(config, ignore_warning=['foo', 'foo bar'])
def test_ignore_warning_string_1snf_warning_1err(self): self.dev._conn.rpc = MagicMock(side_effect= self._mock_manager_1snf_warning_1err) cu = Config(self.dev) config = """ delete interfaces ge-0/0/0 delete protcols ospf delete policy-options prefix-list foo """ with self.assertRaises(ConfigLoadError): cu.load(config, ignore_warning='statement not found')
def update_configuration(dev, cfg, ticket, nwadmin): """ It carries out the configuration procedure , i.e. Lock-Load-Diff-Commit-Unlock This function is NOT intended to be used with Jinja2 templates but with Configuration Tables """ # Instantiate Class Config to get user friendly junos like diff output -------------- cu = Config(dev) cprint("Review the configuration changes to be applied on %s" % dev, 'yellow') agree = 'N' try: cfg.lock() cfg.load() # rather than cfg.diff() use cu.diff() - it creates more user friendly outputs print(cu.diff()) agree = input("Do you want to apply these changes? y/n[N]: " or 'N') except LockError as err: print("Unable to lock configuration: {0}".format(err)) except (ConfigLoadError, Exception) as err: print("Unable to load configuration changes: {0}".format(err)) print("Unlocking the configuration") try: cfg.unlock() except UnlockError: print("Unable to unlock configuration: {0}".format(err)) # Proceed with updating configuration ----------------------------------------------- if agree == "Y" or agree == "y": print("Committing the configuration") try: cfg.commit(comment=ticket + "/" + nwadmin) except CommitError as err: print("Unable to commit configuration: {0}".format(err)) print("Unlocking the configuration") try: print("Unlocking the configuration") cfg.rollback() cfg.unlock() except UnlockError as err: print("Unable to unlock configuration: {0}".format(err)) else: # Discard changes try: print("Discarding changes") cfg.rollback() cfg.unlock() except UnlockError as err: print("Unable to unlock configuration: {0}".format(err))
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 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 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)
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 def connect(self): self.handle = Device(host=self.host, user=self.username, password=self.password) 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): self.handle.close() def show_version(self): return self.handle.show_version() def config(self, stmts=[], commit=True, ignore_errors=False, timeout = 30): for stmt in stmts: try: self.config_handle.load(stmt, format='set', merge=True) except ConfigLoadError,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,e: self.logger.exception(e) return (False,e)
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 __init__(self): self.dev_Connect = Device(host='192.168.56.2', user='******', password='******') #192.168.56.2 self.dev_Connect.open() #pprint( dev.facts ) print"Connection Established" self._conf_JunOS=Config(self.dev_Connect)
def connect(self): self.handle = Device(host=self.host, user=self.username, password=self.password) 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
def __init__(self, dev=None, xml=None, path=None, mode=None): Table.__init__(self, dev, xml, path) # call parent constructor self._init_get() self._data_dict = self.DEFINE # crutch self.ITEM_NAME_XPATH = self._data_dict.get('key', 'name') self.view = self._data_dict.get('view') self._options = self._data_dict.get('options') self.mode = mode if 'set' in self._data_dict: Config.__init__(self, dev, mode) # call parent constructor self._init_set() if self._view: self.fields = self._view.FIELDS.copy() else: raise ValueError( "%s set table view is not defined.\n" % (self.__class__.__name__) ) if 'key-field' in self._data_dict: key_name = self._data_dict.get('key-field', None) if isinstance(key_name, list): self.key_field = key_name elif isinstance(key_name, str): self.key_field = [key_name] else: raise TypeError( "Key-field %s is of invalid type %s.\n" % (key_name, type(key_name)) ) else: raise ValueError( "Table should have key-field attribute defined\n" ) self._type = 'set' self._init_field() else: self._type = 'get' self.ITEM_XPATH = self._data_dict[self._type] # no new attributes. self._freeze()
def load_config_cmd_on_devices(fname): #import pdb;pdb.set_trace() global handles global hosts global dev print ("\n") i=0 j=0 #print ("to find") #print (handles) locallist = list(handles['resources'].keys()) #router_index = 0 for router in hosts: #import pdb; pdb.set_trace() #print ("find here") #dev[i].bind( cu=Config ) print ("Loading configuration changes on Device", hosts[i]) print ("\n") #import pdb;pdb.set_trace() try: #print ("run trough python") file_name = fname #print ("loading " + file_name + " configuration on DUT " + router) cfg = Config(dev[i]) print ("Configuring Below command on ",hosts[i]) #print (each_line.strip()) cfg.load(path=file_name, format="set", merge=True) #dev[k].cfg.load(each_line.strip(), format='set') #k = k + 1 #j = j + 1 except ValueError as err: print (err.message) except Exception as err: if err.rsp.find('.//ok') is None: rpc_msg = err.rsp.findtext('.//error-message') print ("Unable to load configuration changes: ", rpc_msg) print ("Unlocking the configuration on Device", hosts[i]) print ("\n") #dev[i].close() return print ("\n") i = i+1
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 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()
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 __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 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 __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.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativdSW(self.native)
def open(self): """サーバに接続 """ self.dev = Device( host=self.server.ipaddr, user=self.user_login, password=self.pass_login, ) self.dev.open(gather_facts=False) if self.dev.connected: # デフォルト30秒を更新 setattr(self.dev, 'timeout', self.rpc_timeout) self.cu = Config(self.dev) self.closed = False self.write_log(self.logger, 'info', "%s (%s): 接続しました." % (self.server.ipaddr, self.server.model, )) else: raise RuntimeError("%s: %s: unable to connect." % (self.__class__.__name__, self.server.ipaddr))
def connect(self, **kwargs): try: host = self.module.params['host'] port = self.module.params['port'] or 830 user = self.module.params['username'] passwd = self.module.params['password'] key_filename = self.module.params['ssh_keyfile'] self.device = Device(host, user=user, passwd=passwd, port=port, gather_facts=False, ssh_private_key_file=key_filename).open() self.config = Config(self.device) except Exception: exc = get_exception() self._fail('unable to connect to %s: %s' % (host, str(exc)))
def test_load_config(self): from jnpr.junos.utils.config import Config cu = Config(self.dev) data = """interfaces { ge-1/0/0 { description "MPLS interface"; unit 0 { family mpls; } } } """ cu.load(data, format='text') self.assertTrue(cu.commit_check()) if cu.commit_check(): cu.rollback()
def loadVRFConfig(VRF_number): if 1 < int(VRF_number) < 255: dev = Device(host="172.2.3.5", user="******", ssh_private_key_file="/root/.ssh/VRF") dev.open() conf = Config(dev) variables = {} variables["VRF_instance"] = VRF_number conf.load(template_path="templateVRF_set.conf", template_vars=variables, format="set", merge=True) conf.pdiff() if conf.commit_check(): print "This config would commit succesfully" else: print "Config puck`d up" dev.close() else: print "The VRF number must be between 2 and 254"
format="set", merge=True) cfg.load("delete routing-options static route 203.0.113.200/32", format="set", merge=True) print("deleting the routes") if cfg.diff() is not None: cfg.commit() cfg.unlock() def Compare_routes(routes, updated_routes): new_routes = [] for route in updated_routes.keys(): if route not in routes.keys(): new_routes.append(route) return new_routes if __name__ == "__main__": a_device = srx_device() a_device.timeout = 60 cfg = Config(a_device) route = gather_routes(a_device) Config_from_file(path="static_routes.conf", a_device=a_device, merge=True) updated_routes = gather_routes(a_device) new_routes = Compare_routes(route, updated_routes) print("The new routes are", new_routes) Del_routes(a_device)
from jnpr.junos.device import Device from jnpr.junos.utils.config import Config from pprint import pprint junos_hosts = ['172.25.11.1', '1.1.1.1'] for ip in junos_hosts: dev = Device(host=ip, user='******', password='******') dev.open() config = Config(dev) config.lock() config.load(path='add_snmp.conf', merge=True) config.pdiff() config.commit() config.unlock() dev.close()
from jnpr.junos import Device from jnpr.junos.utils.config import Config import getpass host = None uname = None pw = None if host == None: host = input("Hostname or IP: ") if uname == None: uname = input("Username: ") if pw == None: pw = getpass.getpass() dev = Device(host=host, user=uname, password=pw, gather_facts=False) dev.open() cu = Config(dev) diff = cu.diff() if diff: cu.rollback() dev.close()
dev = Device() dev.open() config_xml = """ <configuration> <system> <scripts> <op> <file> <name>demo.py</name> </file> </op> </scripts> </system> </configuration> """ cu = Config(dev) try: cu.lock() cu.load(config_xml, format="xml", merge=True) cu.commit() cu.unlock() # Catch configuration lock error except LockError: jcs.syslog("external.error, Unable to lock configuration") dev.close() except ConfigLoadError: jcs.syslog("external.error, Unable to load configuration") cu.unlock()
print(env.get_template('backbone.conf.template').render(vars)) print('--------------------------------------------') print('') ip = '192.168.1.12' print('connecting to ' + ip + '...') dev = Device(host=ip, user='******', password='******') try: dev.open() except ConnectError as err: print('Cannot connect to device: {0}\n'.format(err)) sys.exit() print('connected') cu = Config(dev) cu.load(template_path='backbone.conf.template', template_vars=vars, overwrite=True, format='text') print('configuration loaded') print('commit check: {0}'.format(cu.commit_check())) if cu.commit(confirm=10, timeout=60): print('committed') print( 'warning: you have to commit again in 10 minutes to confirm changes,') print(' or it will rollback automatically') else: print('commit check failed')
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 #set system services netconf ssh must be enabled, or it will error out #dev contains the box you want to open and the credentials dev = Device(host='NAME OF ROUTER HERE', user='******', password='******') dev.open() #Start config mode cu = Config(dev) #Here is an example of deleting something within the config - just give the full set command set_cmd = 'delete logical-systems CE2 protocols msdp export reject_source1' #this line is needed after the set command to actually apply it to the box cu.load(set_cmd, format='set') #Here is an example of adding something within the config set_cmd = 'set logical-systems CE2 protocols msdp export reject_source2' #Again, this loads the statement above to the box. cu.load(set_cmd, format='set') #This issues the commit. cu.commit()
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): class MyException(Exception): xml = etree.fromstring(""" <rpc-reply> <rpc-error> <error-type>protocol</error-type> <error-tag>operation-failed</error-tag> <error-severity>error</error-severity> <error-message>permission denied</error-message> <error-info> <bad-element>system</bad-element> </error-info> </rpc-error> </rpc-reply> """) self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.assertDictEqual( self.conf.commit_check(), { 'source': None, 'message': 'permission denied', 'bad_element': 'system', 'severity': 'error', 'edit_path': None }) 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'}, ignore_warning=False) 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_diff_rpc_timeout(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.get_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.diff) 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.rpc_error') def test_config_lock_ConnectClosedError(self, mock_jxml): ex = ConnectClosedError(dev=self) self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(ConnectClosedError, 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.rpc_error') def test_config_unlock_ConnectClosedError(self, mock_jxml): ex = ConnectClosedError(dev=self) self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(ConnectClosedError, 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_set_rename(self): self.conf.rpc.load_config = MagicMock() conf = """rename firewall family inet filter f1 to filter f2""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_insert(self): self.conf.rpc.load_config = MagicMock() conf = """insert policy-options policy-statement hop term 10 after 9""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_activate(self): self.conf.rpc.load_config = MagicMock() conf = """activate system services ftp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_deactivate(self): self.conf.rpc.load_config = MagicMock() conf = """deactivate system services ftp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_annotate(self): self.conf.rpc.load_config = MagicMock() conf = """annotate system \"Annotation test\"""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_copy(self): self.conf.rpc.load_config = MagicMock() conf = """copy firewall family inet filter f1 to filter f2""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_protect(self): self.conf.rpc.load_config = MagicMock() conf = """protect system services""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_unprotect(self): self.conf.rpc.load_config = MagicMock() conf = """unprotect system services""" 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)) 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 }]) @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_ephemeral_default(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='ephemeral') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(ephemeral=True) @patch('jnpr.junos.Device.execute') def test_config_mode_ephemeral_instance(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='ephemeral', ephemeral_instance='xyz') as \ conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with( ephemeral_instance='xyz') def test_config_unsupported_kwargs(self): self.dev.rpc.open_configuration = MagicMock() try: with Config(self.dev, mode='ephemeral', xyz='xyz') as conf: conf.load('conf', format='set') except Exception as ex: self.assertEqual(str(ex), 'Unsupported argument provided to Config class') @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) def test_config_mode_undefined(self): 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 test_config_load_url(self): self.conf.rpc.load_config = MagicMock() self.conf.load(url="/var/home/user/golden.conf") self.assertEqual(self.conf.rpc.load_config.call_args[1]['url'], '/var/home/user/golden.conf') @patch('jnpr.junos.Device.execute') def test_load_config_patch(self, mock_exec): conf = \ """[edit system] - host-name pakzds904; + host-name pakzds904_set; """ self.conf.load(conf, format='text', patch=True) self.assertEqual(mock_exec.call_args[0][0].tag, 'load-configuration') self.assertEqual(mock_exec.call_args[0][0].attrib, { 'format': 'text', 'action': 'patch' }) 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() raise RPCError(etree.XML(foo), errs=obj._errors) 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')
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)
from jnpr.junos import Device from jnpr.junos.utils.config import Config dev = Device(host='xxxx', user='******', password='******', gather_facts=False) dev.open() 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():
def main(): juniper_srx = { "host": "184.105.247.76", "user": "******", "password": "******" } 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 thisismytestname", 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()
3d. Rollback the staged configuration. Once again, print out the diff of the staged and the current configuration (which at this point should be None). """ from jnpr_devices import srx2 # SRX device dictionary from jnpr.junos import Device # Device class from jnpr.junos.utils.config import Config # Config class # Create device object device_conn = Device(**srx2) device_conn.open() # Establish NETCONF connection device_conn.timeout = 60 # Change device timeout # Pass in NETCONF connection to Config object cnfg = Config(device_conn) cnfg.lock() # Lock device to others so only we can be in config mode # Use load method to send and stage config on the device via set command - merge NOT replace cnfg.load("set system host-name test1", format='set', merge=True) # Exercise 3c # Print the difference between the candidate and running config to see if the config was applied or not print(cnfg.diff()) # Exercise 3d # Undo the change to the candidate config we just did cnfg.rollback(0) # Print the difference between the candidate and running config to see if the rollback was successful or not print(cnfg.diff())
f.close() # build the configuration file from a jinja2 template for this item using the variable item_vars 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. '''
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!"
def Del_routes(a_device): cfg = Config(a_device) cfg.lock() cfg.load("delete routing-options static route 203.0.113.5/32", format="set", merge=True) cfg.load("delete routing-options static route 203.0.113.200/32", format="set", merge=True) print("deleting the routes") if cfg.diff() is not None: cfg.commit() cfg.unlock()
def Config_from_file(path, a_device, merge=True): cfg = Config(a_device) cfg.lock() cfg.load(path="static_routes.conf", format="text", merge=True) if cfg.diff() is not None: cfg.commit() cfg.unlock()
def test_config_mode_ephemeral_default(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='ephemeral') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(ephemeral=True)
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)
def apply_candidate_policy(self, candidate_policy, merge=True): """ resolve the candidate policy and apply it to the device default method is to merge the generated config but 'replace' is used for deletions """ def get_or_create_address_element(address): a_obj = self.get_address_object_by_value(address) if a_obj is None: # need to create a new one address_book_element, address_book_element_name = create_new_address( address) # transparently append the new entry to the list address_book.append(address_book_element) return address_book_element_name else: return a_obj.name def get_or_create_service_element(service): s_obj = self.get_service_object_by_value(service) if s_obj is None: # need to create a new one service_book_element, service_book_element_name = create_new_service( service) # transparently append the new entry to the list service_book.append(service_book_element) return service_book_element_name else: return s_obj.name def build_policy(name, s_addresses, d_addresses, services, action, logging): # base elements sub_policy_element = create_element('policy') create_element('name', text=name, parent=sub_policy_element) p_match_element = create_element('match', parent=sub_policy_element) # address elements for a_type in [s_addresses, d_addresses]: for _a in a_type: __a_type = 'source-address' if a_type is s_addresses else 'destination-address' create_element(__a_type, text=get_or_create_address_element(_a), parent=p_match_element) # service elements for _s in services: create_element('application', text=get_or_create_service_element(_s), parent=p_match_element) # action and logging then_element = create_element('then', parent=sub_policy_element) create_element(action, parent=then_element) log_element = create_element('log', parent=then_element) create_element(logging, parent=log_element) return sub_policy_element # 1 - resolve zones - TODO is this really needed or can we enforce this as a requirement? # 2 - check all elements present (can actually build the policy) # 3 - build policy # 4 - apply and commit if not self._connected: raise ConnectionError("Device connection is not open") c_policy = candidate_policy.policy configuration = build_base() address_book = [] service_book = [] if candidate_policy.method is CandidatePolicy.NEW_POLICY: # this will be a new policy # check if we have a valid new policy if c_policy.src_zones is None or c_policy.dst_zones is None or c_policy.src_addresses is None \ or c_policy.dst_addresses is None or c_policy.services is None or c_policy.action is None \ or c_policy.name is None: # missing elements raise BadCandidatePolicyError() policy_element = build_policy(c_policy.name, c_policy.src_addresses, c_policy.dst_addresses, c_policy.services, c_policy.action, c_policy.logging) else: # we are adding new element(s) to an existing policy # base elements policy_element = create_element('policy') create_element('name', text=c_policy.name, parent=policy_element) match_element = create_element('match', parent=policy_element) # TODO currently only address and service additions are supported for k, v in candidate_policy.target_dict.iteritems(): if k == 'source-addresses' or k == 'destination-address': for a in v: _a_type = 'source-address' if k is 'source-addresses' else 'destination-address' create_element(_a_type, text=get_or_create_address_element(a), parent=match_element) elif k == 'services': for s in v: create_element('application', text=get_or_create_service_element(s), parent=match_element) else: raise PolicyImplementationError( 'Currently only address and service additions are supported.' ) # put the tree together for s_zone in c_policy.src_zones: for d_zone in c_policy.dst_zones: # security policy section zone_pair_element = build_zone_pair(s_zone, d_zone) zone_pair_element.append(policy_element) configuration[0][0].append(zone_pair_element) # services if service_book: config_service_element = letree.Element('applications') for s_el in service_book: config_service_element.append(s_el) configuration.append(config_service_element) # addresses if address_book: config_address_book_element = letree.Element( 'address-book') global_book_element = letree.SubElement( config_address_book_element, 'name') global_book_element.text = 'global' for a_el in address_book: config_address_book_element.append(a_el) # append within the security element configuration[0].append(config_address_book_element) # load the config and commit # this is done with a private session, meaning if there are uncommitted # changes on the box, this load will fail # print letree.tostring(configuration, pretty_print=True) with Config(self.device, mode='private') as cu: cu.load(configuration, format='xml', merge=merge) cu.pdiff() cu.commit()
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)
def install_config(path=None, **kwargs): """ Installs the given configuration file into the candidate configuration. Commits the changes if the commit checks or throws an error. path (required) Path where the configuration/template file is present. If the file has a ``.conf`` extension, the content is treated as text format. If the file has a ``.xml`` extension, the content is treated as XML format. If the file has a ``.set`` extension, the content is treated as Junos OS ``set`` commands. mode : exclusive The mode in which the configuration is locked. Can be one of ``private``, ``dynamic``, ``batch``, ``exclusive``. dev_timeout : 30 Set NETCONF RPC timeout. Can be used for commands which take a while to execute. overwrite : False Set to ``True`` if you want this file is to completely replace the configuration file. replace : False Specify whether the configuration file uses ``replace:`` statements. If ``True``, only those statements under the ``replace`` tag will be changed. format Determines the format of the contents update : False Compare a complete loaded configuration against the candidate configuration. For each hierarchy level or configuration object that is different in the two configurations, the version in the loaded configuration replaces the version in the candidate configuration. When the configuration is later committed, only system processes that are affected by the changed configuration elements parse the new configuration. This action is supported from PyEZ 2.1. comment Provide a comment for the commit confirm Provide time in minutes for commit confirmation. If this option is specified, the commit will be rolled back in the specified amount of time unless the commit is confirmed. diffs_file Path to the file where the diff (difference in old configuration and the committed configuration) will be stored. Note that the file will be stored on the proxy minion. To push the files to the master use :py:func:`cp.push <salt.modules.cp.push>`. template_vars Variables to be passed into the template processing engine in addition to those present in pillar, the minion configuration, grains, etc. You may reference these variables in your template like so: .. code-block:: jinja {{ template_vars["var_name"] }} CLI Examples: .. code-block:: bash salt 'device_name' junos.install_config 'salt://production/network/routers/config.set' salt 'device_name' junos.install_config 'salt://templates/replace_config.conf' replace=True comment='Committed via SaltStack' salt 'device_name' junos.install_config 'salt://my_new_configuration.conf' dev_timeout=300 diffs_file='/salt/confs/old_config.conf' overwrite=True salt 'device_name' junos.install_config 'salt://syslog_template.conf' template_vars='{"syslog_host": "10.180.222.7"}' """ conn = __proxy__["junos.conn"]() ret = {} ret["out"] = True if path is None: ret["message"] = "Please provide the salt path where the configuration is present" ret["out"] = False return ret op = {} if "__pub_arg" in kwargs: if kwargs["__pub_arg"]: if isinstance(kwargs["__pub_arg"][-1], dict): op.update(kwargs["__pub_arg"][-1]) else: op.update(kwargs) test = op.pop("test", False) template_vars = {} if "template_vars" in op: template_vars = op["template_vars"] template_cached_path = salt.utils.files.mkstemp() __salt__["cp.get_template"](path, template_cached_path, template_vars=template_vars) if not os.path.isfile(template_cached_path): ret["message"] = "Invalid file path." ret["out"] = False return ret if os.path.getsize(template_cached_path) == 0: ret["message"] = "Template failed to render" ret["out"] = False return ret write_diff = "" if "diffs_file" in op and op["diffs_file"] is not None: write_diff = op["diffs_file"] del op["diffs_file"] op["path"] = template_cached_path if "format" not in op: if path.endswith("set"): template_format = "set" elif path.endswith("xml"): template_format = "xml" else: template_format = "text" op["format"] = template_format if "replace" in op and op["replace"]: op["merge"] = False del op["replace"] elif "overwrite" in op and op["overwrite"]: op["overwrite"] = True elif "overwrite" in op and not op["overwrite"]: op["merge"] = True del op["overwrite"] db_mode = op.pop("mode", "exclusive") with Config(conn, mode=db_mode) as cu: try: cu.load(**op) except Exception as exception: # pylint: disable=broad-except ret["message"] = 'Could not load configuration due to : "{0}"'.format( exception) ret["format"] = op["format"] ret["out"] = False return ret finally: salt.utils.files.safe_rm(template_cached_path) config_diff = cu.diff() if config_diff is None: ret["message"] = "Configuration already applied!" ret["out"] = True return ret commit_params = {} if "confirm" in op: commit_params["confirm"] = op["confirm"] if "comment" in op: commit_params["comment"] = op["comment"] try: check = cu.commit_check() except Exception as exception: # pylint: disable=broad-except ret["message"] = 'Commit check threw the following exception: "{0}"'.format( exception) ret["out"] = False return ret if check and not test: try: cu.commit(**commit_params) ret["message"] = "Successfully loaded and committed!" except Exception as exception: # pylint: disable=broad-except ret["message"] = 'Commit check successful but commit failed with "{0}"'.format( exception) ret["out"] = False return ret elif not check: cu.rollback() ret["message"] = "Loaded configuration but commit check failed, hence rolling back configuration." ret["out"] = False else: cu.rollback() ret["message"] = "Commit check passed, but skipping commit for dry-run and rolling back configuration." ret["out"] = True try: if write_diff and config_diff is not None: with salt.utils.files.fopen(write_diff, "w") as fp: fp.write(salt.utils.stringutils.to_str(config_diff)) except Exception as exception: # pylint: disable=broad-except ret["message"] = 'Could not write into diffs_file due to: "{0}"'.format( exception) ret["out"] = False return ret
def test_config_mode_undefined(self): try: with Config(self.dev, mode='unknown') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, ValueError))
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()
device = Device(host='10.247.140.4', user='******', password='******') device.open() #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()
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")
from jnpr.junos import Device from jnpr.junos.utils.config import Config from getpass import getpass srx2 = Device(host = "srx2.lasthop.io", user = "******", password = getpass()) srx2.open() cfg = Config(srx2) cfg.lock() cfg.load(path = "set_config.conf", format = "set", merge = True) print(cfg.diff()) cfg.commit(comment = "Changing hostname via external text file.") cfg.unlock()
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 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() # 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")
# def __init__(self): # self.host = host # self.uname = uname # self.passwd = passwd # self.port = port # # def bgpConfig(self): # template_file = 'bgpconfig.j2' inventory_file = 'hostfile.yaml' with open(inventory_file) as data: inv = yaml.load(data) for node in inv['device']: try: dev = Device(host=node["ip"], user=node["username"], passwd=node["password"], port=node["port"]).open() with Config(dev, mode="private") as jp: jp.load(template_path=template_file, template_vars=node, format='set') jp.pdiff() jp.commit() dev.close() except ValueError as e: print(e)
def main(): ''' Exercise using Juniper's PyEZ to make changes to device in various ways ''' pwd = getpass('Enter 88newclass: ') ip_addr = raw_input("\nIP: 184.105.247.76\nEnter Juniper SRX IP: ") ip_addr = ip_addr.strip() juniper_srx = { "host": ip_addr, "user": '******', "password": pwd } print "\n\nConnecting to Juniper SRX...\n" # create device object with all the arguments in the dictionary 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