def main(): # initialize logging logging.basicConfig(filename=logfile, level=logging.INFO, format='%(asctime)s:%(name)s: %(message)s') logging.getLogger().name = host logging.getLogger().addHandler(logging.StreamHandler()) logging.info('Information logged in {0}'.format(logfile)) # verify package exists if not (os.path.isfile(package)): msg = 'Software package does not exist: {0}. '.format(package) logging.error(msg) sys.exit() dev = Device(host=host, user=junos_username, passwd=junos_password) try: dev.open() except ConnectError as err: logging.error('Cannot connect to device: {0}\n'.format(err)) return # Create an instance of SW sw = SW(dev) try: logging.info( 'Starting the software upgrade process: {0}'.format(package)) #ok = sw.install(package=package,progress=update_progress) except Exception as err: msg = 'Unable to install software, {0}'.format(err) logging.error(msg) ok = False #UPGRADED SUCCESSFULLY logging.info("!!!!!!!!!!!!!") #logging.info(dev.cli("request system firmware upgrade pic pic-slot 0 fpc-slot 1")) print dev.cli("show system firmware") logging.info("!!!!!!!!!!!!!") if ok is True: logging.info('Software installation complete. Rebooting') #rsp = sw.reboot() logging.info('Upgrade pending reboot cycle, please be patient.') logging.info(rsp) else: msg = 'Unable to install software, {0}'.format(ok) logging.error(msg) # End the NETCONF session and close the connection dev.close()
class TestCore(unittest.TestCase): @classmethod def setUpClass(self): from jnpr.junos import Device self.dev = Device(host='snuggums.englab.juniper.net', user='******', password='******') self.dev.open() @classmethod def tearDownClass(self): self.dev.close() def test_device_open(self): self.assertEqual(self.dev.connected, True) def test_device_facts(self): assert self.dev.facts['hostname'] == 'snuggums' def test_device_get_timeout(self): assert self.dev.timeout == 30 def test_device_set_timeout(self): self.dev.timeout = 35 assert self.dev.timeout == 35 def test_device_cli(self): self.assertIn('qfx5100', self.dev.cli('show version')) def test_device_rpc(self): sw = self.dev.rpc.get_software_information() hostname = sw.findtext('.//host-name') self.assertEqual(hostname, 'snuggums')
def collect_junos_commands(dev): if not os.path.exists('data_collected/' + dev): os.makedirs('data_collected/' + dev) f = open('configure_appformix/network_devices.yml', 'r') my_vars = load(f.read()) f.close() if my_vars['use_snmp_2c']: for item in my_vars['snmp_2c']['devices']: if item['name'] == dev: dev_ip = item['ip'] if my_vars['use_jti']: for item in my_vars['jti']['devices']: if item['name'] == dev: dev_ip = item['out_of_band'] device = Device(host=dev_ip, user='******', password='******') device.open() commands = [ "show version", "show chassis hardware", "show interfaces extensive" ] for item in commands: cli = device.cli(item, warning=False) f = open('data_collected/' + dev + '/' + item + '.txt', 'w') f.write(cli) f.close() device.close() return 'done'
def get_juniper_isis_database(): #Get isis database from a Juniper and clean it a bit #Tested on Juniper MX 480 runnnig 14.2R5.8 isis_database = [] try : dev = Device(host=router, user=routerusername, passwd=routerpassword) dev.open() isisdb = dev.cli("show isis database detail") dev.close() except: print 'Unable to connect to %s' % router sys.exit(2) for line in isisdb.splitlines(): if re.match('.*Sequence.*', line): a_router = re.search('.*\.', line) a_router = a_router.group()[:-1] a_router = a_router.replace('-re0', '') a_router = a_router.replace('-re1', '') if re.match('.*IS neighbor:.*', line): b_router = re.search('(.*IS neighbor: )(.*)(\.0.*Metric:)(.*\d)'\ , line) metric = b_router.group(4).strip() b_router = b_router.group(2) b_router = b_router.replace('-re0', '') b_router = b_router.replace('-re1', '') isis_database.append((a_router, b_router, metric)) return isis_database
class TestCore(unittest.TestCase): @classmethod def setUpClass(self): from jnpr.junos import Device self.dev = Device(host='pabst.englab.juniper.net', user='******', password='******') self.dev.open() @classmethod def tearDownClass(self): self.dev.close() def test_device_open(self): self.assertEqual(self.dev.connected, True) def test_device_facts(self): assert self.dev.facts['hostname'] == 'pabst' def test_device_get_timeout(self): assert self.dev.timeout == 30 def test_device_set_timeout(self): self.dev.timeout = 35 assert self.dev.timeout == 35 def test_device_cli(self): self.assertTrue('srx210' in self.dev.cli('show version')) def test_device_rpc(self): sw = self.dev.rpc.get_software_information() hostname = sw.findtext('.//host-name') self.assertEqual(hostname, 'pabst')
def getJunosCLI(cmd): hostname = "tango.ultralab.juniper.net" username = "******" dev = Device(host=hostname, user=username, passwd='lab123') try: dev.open() print("***Connected to device***") except Exception as err: print(err) print("***collect debug CLI output***\n>" + cmd + "\n") print("***round 1***") output1 = (dev.cli(cmd, warning=False)) print(output1) time.sleep(3) print("***round 2***") output2 = (dev.cli(cmd, warning=False)) print(output2) dev.close()
def connect(ip_address, u_name, pwd): try: dev = Device(host=ip_address, user=u_name, passwd=pwd) dev.open() except ConnectError as err: print("Cannot connect to device: {0}".format(err)) return cmd = open('commands.txt', 'r').readlines() with open('{}.txt'.format(ip_address), 'w+') as f: f.write('IP address: ' + ip_address + '\n') version = dev.cli("show version") version = version.split('\n') for v in version: if "Model" in v: f.write(v + '\n' + '\n') break for c in cmd: command = c.strip() a = dev.cli(command) f.write('Command: ' + command) f.write(a + '\n' + '\n' + '\n') dev.close()
def main(): """main function""" # parse arguments ---------------------------------------------------------- parser = argparse.ArgumentParser() parser.add_argument('-command') parser.add_argument('-round', default=1) args, unknown_args = parser.parse_known_args() if unknown_args: raise ValueError("unknown argument %s" % unknown_args[0][1:]) if not args.command: raise ValueError("missing argument command") try: decimal = int(args.round) if decimal < 0: raise Exception except: raise ValueError("invalid value '%s' for argument round" % args.round) # execute command ---------------------------------------------------------- try: dev = Device(gather_facts=False) dev.open() output = dev.cli(args.command, format='text', warning=False) finally: try: dev.close() except: pass # humanize output ---------------------------------------------------------- counter_pattern = re.compile("(\s+\d+)") for line in output.splitlines(): l_line = line.lower() for x in EXCEPT: # skip line based on keywords if x in l_line: print(line) break else: # humanize values matches = counter_pattern.finditer(line) if matches: i = 0 # string position humanized_line = [] for match in matches: # replace subscring humanized_line.append(line[i:match.start()]) humanized_line.append(humanize(match.group(1), decimal)) i = match.start() + len(match.group(1)) humanized_line.append(line[i:]) # append remaining print("".join(humanized_line)) else: print(line)
class TestCore(unittest.TestCase): @classmethod def setUpClass(self): from jnpr.junos import Device self.dev = Device(host='pabst.englab.juniper.net', user='******', password='******') self.dev.open() @classmethod def tearDownClass(self): self.dev.close() def test_device_open(self): self.assertEqual(self.dev.connected, True) def test_device_facts(self): assert self.dev.facts['hostname'] == 'pabst' def test_device_get_timeout(self): assert self.dev.timeout == 30 def test_device_set_timeout(self): self.dev.timeout = 35 assert self.dev.timeout == 35 def test_device_cli(self): self.assertTrue('srx210' in self.dev.cli('show version')) def test_device_rpc(self): res = self.dev.rpc.traceroute(noresolve=True, host='8.8.8.8', wait='1') self.assertEqual(res.tag, 'traceroute-results') def test_device_rpc_timeout(self): with self.assertRaises(RpcTimeoutError): self.dev.rpc.traceroute(noresolve=True, host='8.8.8.8', dev_timeout=1) def test_device_rpc_normalize_true(self): rsp = self.dev.rpc.get_interface_information(interface_name='ge-0/0/0', normalize=True) self.assertEqual( rsp.xpath('physical-interface/name')[0].text, 'ge-0/0/0') def test_device_rpc_normalize_false(self): rsp = self.dev.rpc.get_interface_information(interface_name='ge-0/0/0', normalize=False) self.assertEqual( rsp.xpath('physical-interface/name')[0].text, '\nge-0/0/0\n')
def get_configuration(host, pre, command): dev = Device(host, user='******', password='******', port='22') try: dev.open() content = dev.cli(command) except: print(host + 'can not connect to device') content = 'can not connect to device' finally: dev.close() #return content file_name = pre + ".txt" file = open(file_name, 'w') file.write(content) file.close()
def run_commands(devices, user, password, commands, todir): if not os.path.exists(todir): os.mkdir(todir) for device in devices: # Open each device print 'Trying device: %s \n' % device outfile = file(os.path.join(todir, device + time.strftime ('%Y%m%d.%H:%M:%S') + '.txt'), 'w') dev = Device(device, user=user, password=password, gather_facts=False) try: dev.open() except ConnectError: print "ERROR: Unable to connect to %s." % device continue for command in commands: print 'Running command: %s\n' % command outfile.write('\n**** %s ****' % command) outfile.write(dev.cli(command, warning=False)) dev.close() return
class TestCore(unittest.TestCase): @classmethod def setUpClass(self): from jnpr.junos import Device self.dev = Device(host='pabst.englab.juniper.net', user='******', password='******') self.dev.open() @classmethod def tearDownClass(self): self.dev.close() def test_device_open(self): self.assertEqual(self.dev.connected, True) def test_device_facts(self): assert self.dev.facts['hostname'] == 'pabst' def test_device_get_timeout(self): assert self.dev.timeout == 30 def test_device_set_timeout(self): self.dev.timeout = 35 assert self.dev.timeout == 35 def test_device_cli(self): self.assertTrue('srx210' in self.dev.cli('show version')) def test_device_rpc(self): res = self.dev.rpc.traceroute(noresolve=True, host='8.8.8.8', wait='1') self.assertEqual(res.tag, 'traceroute-results') def test_device_rpc_timeout(self): with self.assertRaises(RpcTimeoutError): self.dev.rpc.traceroute(noresolve=True, host='8.8.8.8', dev_timeout=1) def test_device_rpc_normalize_true(self): rsp = self.dev.rpc.get_interface_information(interface_name='ge-0/0/0', normalize=True) self.assertEqual(rsp.xpath('physical-interface/name')[0].text, 'ge-0/0/0') def test_device_rpc_normalize_false(self): rsp = self.dev.rpc.get_interface_information(interface_name='ge-0/0/0', normalize=False) self.assertEqual(rsp.xpath('physical-interface/name')[0].text, '\nge-0/0/0\n')
class TestCore(unittest.TestCase): @classmethod def setUpClass(self): from jnpr.junos import Device self.dev = Device(host='pabst.englab.juniper.net', user='******', password='******') self.dev.open() @classmethod def tearDownClass(self): self.dev.close() def test_device_open(self): self.assertEqual(self.dev.connected, True) def test_device_facts(self): assert self.dev.facts['hostname'] == 'pabst' def test_device_get_timeout(self): assert self.dev.timeout == 30 def test_device_set_timeout(self): self.dev.timeout = 35 assert self.dev.timeout == 35 def test_device_cli(self): self.assertTrue('srx210' in self.dev.cli('show version')) def test_device_rpc(self): res = self.dev.rpc.traceroute(noresolve=True, host='8.8.8.8', wait='1') self.assertEqual(res.tag, 'traceroute-results') def test_device_rpc_timeout(self): with self.assertRaises(RpcTimeoutError): self.dev.rpc.traceroute(noresolve=True, host='8.8.8.8', dev_timeout=1)
description "MPLS interface"; unit 0 { family mpls; } } } """ cu.load(data, format='text') print "\nconfig# show | compare" cu.pdiff() if cu.commit_check(): print "\nCommiting..\n" # cu.commit(comment="Configuring ge-1/0/1 interfaces") cu.commit(sync=True) else: cu.rollback() print "cli> show configuration interfaces", dev.cli("show configuration interfaces", warning=False) #print "Rolling back the configuration" #cu.rollback(rb_id=1) #cu.commit(detail=True) #cu.commit(sync=True) #print "cli> show configuration interfaces", dev.cli("show configuration interfaces", warning=False) dev.close()
class pybot_jrouter(object): ROBOT_LIBRARY_SCOPE = 'TEST SUITE' ROBOT_LISTENER_API_VERSION = 2 # ----------------------------------------------------------------------- # CONSTRUCTOR # ----------------------------------------------------------------------- def __init__(self,**kvargs): """ Constructor method. It takes a user, password and a target (port is optional) arguments to create an instance of a JunOS device that will be used by RF """ # Setting credentials self.user = kvargs['user'] self.target = kvargs['target'] self.password = kvargs['password'] try: self.port = int(kvargs['port']) except KeyError: self.port = 22 self.ROBOT_LIBRARY_LISTENER = self self.max_retries = 2 self._conn = Device(user=self.user, host=self.target, password=self.password, port=self.port, gather_facts=False) # ----------------------------------------------------------------------- # OVERLOADS # ----------------------------------------------------------------------- def __repr__ (self): """ Function that returns a representation of an instance of a JunOS device used by RF """ return "pybot_jrouter: user=%s, target=%s, password=%s, port=%s, connection=%s" % (self.user, self.target, self.password, self.port, self._conn) # ----------------------------------------------------------------------- # FUNCTIONS START HERE # ----------------------------------------------------------------------- def open_connection(self): """ Function that opens a connection to a JunOS device """ try: self._conn.open(auto_probe=10) self._conn.timeout = 120*120 return self except ConnectError as c_error: print ("WARN Connection problems %s target: %s port: %s" % (c_error, self.target, self.port)) raise ContinuableError("Connection problems %s target: %s port: %s" %(c_error, self.target, self.port)) def close_connection(self): """ Function that closes a connection to a JunOS device """ try: self._conn.close() return self except ConnectError as c_error: print ("WARN Connection problems %s" %c_error) raise ContinuableError("Connection problems %s" %c_error) def load_configuration_from_file(self, synchronize=True, overwrite=False, **kvargs): """ Function that load configuration on router from a file path : where the configuration file is located format: possible values 'set' or 'xml' or 'bracket' (so far only format 'set' is supported) """ #overwrite = kvargs.pop ('overwrite',False) args = dict(data='') args.update(kvargs) if overwrite: return self.load_configuration(overwrite=True, **args) else: return self.load_configuration(overwrite=False, **args) def load_configuration_from_template(self, commit_comment='pybot_jrouter_load_configuration_from_template', format='set', conf_mode='exclusive', overwrite=False, merge=False, synchronize=True, force_synchronize=False, full=False, print_conf_diff=False, print_conf_detail=False, **kvargs): """ # General Options: # - format can be text/set/xml # - print_conf_diff will print the diff if desired # - print_conf_detail will print the committed configuration if desired # Configuration Options: # - conf_mode: can be exclusive/private/dynamic/batch # Load Options: # - overwrite: Determines if the contents completely replace the existing configuration. Default is False # - merge: If set to True will set the load-config action to merge the default load-config action is 'replace' # Commit Options: # - kvargs synchronize: Default True. On dual control plane systems, requests that the candidate configuration on one control plane be copied to the other control plane, checked for correct syntax, and committed on both Routing Engines. Default is True. # - kvargs force_synchronize: Default False. On dual control plane systems, forces the candidate configuration on one control plane to be copied to the other control plane. Default is False # - kvargs full: Default False. When True requires all the daemons to check and evaluate the new configuration """ print ("*INFO* Host %s|load_configuration_from_template|General Options: format=%s, print_conf_diff=%s, print_conf_detail=%s" % (self.target, format, print_conf_diff, print_conf_detail)) synchronize = True force_synchronize = False full = False if 'force_synchronize' in kvargs.keys(): force_synchronize = kvargs['force_synchronize'] if 'synchronize' in kvargs.keys(): synchronize = kvargs['synchronize'] if 'full' in kvargs.keys(): full = kvargs['full'] ##Hidden variable: DO NOT USE DO NOT EDIT #It will be set to True ONLY if routers.load_configuration_from_template_in_parallel is executed if 'parallel' in kvargs.keys(): parallel = kvargs['parallel'] else: parallel = False if force_synchronize: synchronize = True print ("*INFO* Host %s|load_configuration_from_template|Force Synchronized Commit requested" % (self.target)) if synchronize: print ("*INFO* Host %s|load_configuration_from_template|Synchronized Commit requested" % (self.target)) if full: print ("*INFO* Host %s|load_configuration_from_template|Commit Full requested" % (self.target)) print ("*INFO* Host %s|load_configuration_from_template|Load Options: merge=%s, overwrite=%s" % (self.target, merge, overwrite)) if format == 'set' and overwrite: overwrite = False print ("*WARN* Host %s|load_configuration_from_template|Not possible to override the configuration with format=set. Overwriting disabled." % (self.target)) yaml_file = kvargs['template_vars'] # Loading files and rendering myvars = yaml.load(open(yaml_file).read()) loadResp = '' commitResp = False print ("*INFO* Host %s|load_configuration_from_template|Initializing variables. template_path=%s." % (self.target, kvargs['jinja2_file'])) try: #Unlock/close configuration is managed by Config context manager with Config(self._conn, mode=conf_mode) as candidate: begin_load_datetime = datetime.now() if overwrite: loadResp = candidate.load(template_path=kvargs['jinja2_file'], template_vars=myvars, format=format, overwrite=True, merge=merge) else: loadResp = candidate.load(template_path=kvargs['jinja2_file'], template_vars=myvars, format=format, overwrite=False, merge=merge) finish_load_datetime = datetime.now() if loadResp.find("ok") is None: print ("*WARN* Host %s|load_configuration_from_template|Load Response did not throw an exception but something unexpected occurred: %s" % (self.target, etree.tostring(loadResp))) return False if print_conf_diff: try: print ('*INFO* Host %s|load_configuration_from_template|DIFF configuration to be committed %s' % (self.target, candidate.diff())) except lxml.etree.XMLSyntaxError as error: print ("*WARN* Host %s|load_configuration_from_template|Unable to retrieve the DIFF configuration to be committed. Printout will be skipped, trying to commit....: %s" % (self.target, error)) begin_commit_datetime = datetime.now() if print_conf_detail: try: #begin_commit_datetime=datetime.now() commitResp = candidate.commit(comment=commit_comment, sync=synchronize, force_sync=force_synchronize, full=full, detail=True) #finish_commit_datetime=datetime.now() print ('*INFO* Host %s|load_configuration_from_template|Configuration to be committed: %s' % (self.target, etree.tostring(commitResp))) except lxml.etree.XMLSyntaxError as error: print ("*WARN* Host %s|load_configuration_from_template|Unable to retrieve the committed configuration. Printout will be skipped, check the node or try again with print_conf_detail=False....: %s" % (self.target, error)) return False else: begin_commit_datetime = datetime.now() commitResp = candidate.commit(comment=commit_comment, sync=synchronize, force_sync=force_synchronize, full=full, detail=False) finish_commit_datetime = datetime.now() except LockError as lockError: print ("*WARN* Host %s|load_configuration_from_template|Problems locking configuration: %s" % (self.target, lockError)) if parallel: return "Exception %s:" %lockError else: raise FatalError("Host %s|load_configuration_from_template|Unable to lock configuration.....exiting: %s" % (self.target, lockError)) except (RpcError, RpcTimeoutError) as rpcError: #warnings severity is already being ignored in the Config context manager print ("*WARN* Host %s|load_configuration_from_template|Problems opening configuration: %s" % (self.target, rpcError)) if parallel: return "Exception %s:" %rpcError else: raise FatalError("Host %s|load_configuration_from_template|Unable to open configuration.....exiting: %s" % (self.target, rpcError)) except ConfigLoadError as configError: print( "*WARN* Host %s|load_configuration_from_template|Template %s|Problems loading the configuration: %s.....exiting" % (self.target, kvargs['jinja2_file'], configError)) if print_conf_diff: try: print ('*INFO* Host %s|load_configuration_from_template|DIFF configuration to be committed %s' % (self.target, candidate.diff())) except lxml.etree.XMLSyntaxError as error: print ("*WARN* Host %s|load_configuration_from_template|Unable to retrieve the DIFF configuration to be committed. Printout will be skipped, trying to commit....: %s" % (self.target, error)) if parallel: return "Exception %s:" %configError else: raise FatalError("Host %s|load_configuration_from_template|Template %s|Unable to load the configuration.....exiting: %s" % (self.target, kvargs['jinja2_file'], configError)) except CommitError as commitError: print ("*WARN* Host %s|load_configuration_from_template|Template %s|Problems committing the configuration: %s.....exiting" % (self.target, kvargs['jinja2_file'], commitError)) if parallel: return "Exception %s:" %commitError else: raise FatalError("Host %s|load_configuration_from_template|Template %s|Unable to commit the configuration.....exiting: %s" % (self.target, kvargs['jinja2_file'], commitError)) except UnlockError as unlockError: print ("*WARN* Host %s|load_configuration_from_template|Problems unlocking the configuration: %s.....exiting" % (self.target, unlockError)) if parallel: return "Exception %s:" %unlockError else: raise FatalError("Host %s|load_configuration_from_template|Unable to unlock the configuration.....exiting: %s" % (self.target, unlockError)) except Exception as error: if 'Opening and ending tag mismatch: routing-engine ' in error: print ('*INFO* Host %s|load_configuration_from_template|%s' %(self.target, error)) pass return True else: print ("*WARN* Host %s|load_configuration_from_template|An unhandled exception occurred: %s.....exiting" % (self.target, error)) if parallel: return "Exception %s:" %error else: raise FatalError("Host %s|load_configuration_from_template|Unhandled Exception occurred.....exiting: %s" % (self.target, error)) diff_load_time = finish_load_datetime - begin_load_datetime diff_commit_time = finish_commit_datetime - begin_commit_datetime total_time = finish_commit_datetime - finish_load_datetime print ('*INFO* Host %s|load_configuration_from_template|Configuration successfully committed|Template: %s|Load Time: %s|Commit Time: %s| Total Time: %s' % (self.target, kvargs['jinja2_file'], self.pretty_time_delta(diff_load_time.seconds), self.pretty_time_delta(diff_commit_time.seconds), self.pretty_time_delta(total_time.seconds))) return True def load_configuration(self, commit_comment ='pybot_jrouter_load_configuration', path=None, format='set', conf_mode='exclusive', overwrite=False, merge=False, synchronize=True, force_synchronize=False, full=False, print_conf_diff=False, print_conf_detail=False, **kvargs): """ Function that load configuration on a JunOS device **kvargs format:set|text|xml data: data to load in the router """ print ("*INFO* Host %s|load_configuration|General Options: format=%s, print_conf_diff=%s, print_conf_detail=%s" % (self.target, format, print_conf_diff, print_conf_detail)) data = kvargs['data'] format = kvargs['format'] if 'force_synchronize' in kvargs.keys(): force_synchronize = kvargs['force_synchronize'] if 'synchronize' in kvargs.keys(): synchronize = kvargs['synchronize'] if 'full' in kvargs.keys(): full = kvargs['full'] if force_synchronize: synchronize = True print ("*INFO* Host %s|load_configuration|Force Synchronized Commit requested" % (self.target)) if synchronize: print ("*INFO* Host %s|load_configuration|Synchronized Commit requested" % (self.target)) if full: print ("*INFO* Host %s|load_configuration|Commit Full requested" % (self.target)) print ("*INFO* Host %s|load_configuration|Load Options: merge=%s, overwrite=%s" % (self.target, merge, overwrite)) if format == 'set' and overwrite: overwrite = False print ("*WARN* Host %s|load_configuration|Not possible to override the configuration with format=set. Overwriting disabled." % (self.target)) loadResp = '' commitResp = False print ("*INFO* Host %s|load_configuration|Initializing variables. path=%s." % (self.target,path)) print ("*INFO* Host %s|load_configuration|Initializing variables. data=%s." % (self.target,data)) try: #Unlock/close configuration is managed by Config context manager with Config(self._conn, mode=conf_mode) as candidate: #begin_load_datetime=datetime.now() if ((data == "") and (path != None)): if overwrite: loadResp=candidate.load(path=path, format=format, overwrite=True, merge=merge) else: loadResp=candidate.load(path=path, format=format, overwrite=False, merge=merge) #finish_load_datetime=datetime.now() if loadResp.find("ok") is None: print ("*WARN* Host %s|load_configuration|Load Response did not throw an exception but something unexpected occurred: %s" % (self.target, etree.tostring(loadResp))) return False if print_conf_diff: try: print ('*INFO* Host %s|load_configuration|DIFF configuration to be committed %s' % (self.target, candidate.diff())) except lxml.etree.XMLSyntaxError as error: print ("*WARN* Host %s|load_configuration|Unable to retrieve the DIFF configuration to be committed. Printout will be skipped, trying to commit....: %s" % (self.target, error)) else: if overwrite: loadResp=candidate.load(data, format=format, overwrite=True, merge=merge) else: loadResp=candidate.load(data, format=format, overwrite=False, merge=merge) #finish_load_datetime=datetime.now() if loadResp.find("ok") is None: print ("*WARN* Host %s|load_configuration|Load Response did not throw an exception but something unexpected occurred: %s" % (self.target, etree.tostring(loadResp))) return False if print_conf_diff: try: print ('*INFO* Host %s|load_configuration|DIFF configuration to be committed %s' % (self.target, candidate.diff())) except lxml.etree.XMLSyntaxError as error: print ("*WARN* Host %s|load_configuration|Unable to retrieve the DIFF configuration to be committed. Printout will be skipped, trying to commit....: %s" % (self.target, error)) #begin_commit_datetime=datetime.now() if print_conf_detail: try: #begin_commit_datetime=datetime.now() commitResp=candidate.commit(comment=commit_comment, sync=synchronize, force_sync=force_synchronize, full=full, detail=True) #finish_commit_datetime=datetime.now() print ('*INFO* Host %s|load_configuration|Configuration to be committed: %s' % (self.target, etree.tostring(commitResp))) except lxml.etree.XMLSyntaxError as error: print ("*WARN* Host %s|load_configuration|Unable to retrieve the commited configuration. Printout will be skipped, check the node or try again with print_conf_detail=False....: %s" % (self.target, error)) return False else: #begin_commit_datetime=datetime.now() commitResp=candidate.commit(comment=commit_comment, sync=synchronize, force_sync=force_synchronize, full=full, detail=False) #finish_commit_datetime=datetime.now() except LockError as lockError: print ("*WARN* Host %s|load_configuration|Problems locking configuration: %s" % (self.target, lockError)) raise FatalError("Host %s|load_configuration|Unable to lock configuration.....exiting: %s" % (self.target, lockError)) except (RpcError,RpcTimeoutError) as rpcError: #warnings severity is already being ignored in the Config context manager print ("*WARN* Host %s|load_configuration|Problems opening configuration: %s" % (self.target, rpcError)) raise FatalError("Host %s|load_configuration|Unable to open configuration.....exiting: %s" % (self.target, rpcError)) except ConfigLoadError as configError: print ("*WARN* Host %s|load_configuration|Problems loading the configuration: %s.....exiting" % (self.target, configError)) if print_conf_diff: try: print ('*INFO* Host %s|load_configuration|DIFF configuration to be committed %s' % (self.target, candidate.diff())) except lxml.etree.XMLSyntaxError as error: print ("*WARN* Host %s|load_configuration|Unable to retrieve the DIFF configuration to be committed. Printout will be skipped, trying to commit....: %s" % (self.target, error)) raise FatalError("Host %s|load_configuration|Unable to load the configuration.....exiting: %s" % (self.target, configError)) except CommitError as commitError: print ("*WARN* Host %s|load_configuration|Problems committing the configuration: %s.....exiting" % (self.target, commitError)) raise FatalError("Host %s|load_configuration|Unable to commit the configuration.....exiting: %s" % (self.target, commitError)) except UnlockError as unlockError: print ("*WARN* Host %s|load_configuration|Problems unlocking the configuration: %s.....exiting" % (self.target, unlockError)) raise FatalError("Host %s|load_configuration|Unable to unlock the configuration.....exiting: %s" % (self.target, unlockError)) except Exception as error: if 'Opening and ending tag mismatch: routing-engine ' in error: print ('*INFO* Host %s|load_configuration|%s' % (self.target, error)) pass return True else: print ("*WARN* Host %s|load_configuration|An unhandled exception occurred: %s.....exiting" % (self.target, error)) raise FatalError("Host %s|load_configuration|Unhandled Exception occurred.....exiting: %s" % (self.target, error)) print ('*INFO* Host %s|load_configuration|Configuration successfully committed' % (self.target)) #diff_load_time=begin_load_datetime-finish_load_datetime #diff_commit_time=begin_commit_datetime-finish_commit_datetime return True def jsnap(self, **kvargs): """ Function that makes use of JSNAP """ variables = BuiltIn().get_variables() # Assigning kvargs section = None if 'section' in kvargs.keys(): section = kvargs['section'] tag = kvargs['tag'] snaptype = kvargs['snaptype'] test = kvargs['test'] mode = kvargs['mode'] output_directory = variables['${path}'] test_case = variables['${testname}'] tmp_dir = tempfile.mkdtemp(prefix='_') dirpath = output_directory + "/" + tmp_dir + "/" + test_case.replace(" ","_") + "/" + self.target + "/snapshot/" #PARENT_ROOT=os.path.abspath(os.path.join(self.logdir, os.pardir)) #GRANDPA=os.path.abspath(os.path.join(PARENT_ROOT, os.pardir)) if not os.path.exists(dirpath): os.makedirs(dirpath, mode=777) timestamp = datetime.now().strftime("%Y-%m-%d") if snaptype == "snap": if section: cmd = 'jsnap --'+ snaptype + " " + timestamp + '_'+ tag + ' -l ' + self.user + ' -p ' + self.password + ' -t ' + self.target + ' -s' + section + ' ' + test else: cmd = 'jsnap --'+ snaptype + " " + timestamp + '_'+ tag + ' -l ' + self.user + ' -p ' + self.password + ' -t ' + self.target + ' ' + test print ("Executing: %s" %cmd) jsnap_command = sub.Popen(cmd, stdout=sub.PIPE, stderr=sub.PIPE, shell=True, cwd=dirpath) output, errors = jsnap_command.communicate() if ((("Exiting." in errors)) or("Unable to connect to device: " in errors) or ("jsnap: not found" in errors) or ("appears to be missing" in output)): print (output) print (errors) raise FatalError("Unable to execute jsnap.....exiting") else: return True print (output, errors) return True elif snaptype == "snapcheck": if section: cmd = 'jsnap --'+ snaptype + " " + timestamp + '_'+ tag + ' -l ' + self.user + ' -p ' + self.password + ' -t ' + self.target + ' -s' + section + ' ' + test else: cmd = 'jsnap --'+ snaptype + " " + timestamp + '_'+ tag + ' -l ' + self.user + ' -p ' + self.password + ' -t ' + self.target + ' ' + test print ("Executing: %s" %cmd) jsnap_command = sub.Popen(cmd, stdout=sub.PIPE, stderr=sub.PIPE, shell=True, cwd=dirpath) output, errors = jsnap_command.communicate() print (output) print (errors) if ((("Exiting." in errors)) or ("Unable to connect to device: " in errors) or ("jsnap: not found" in errors) or ("appears to be missing" in output)): print (output) print (errors) raise FatalError("Unable to execute jsnap.....exiting") else: if mode == "strict": if "ERROR" in output or "ERROR" in errors: raise FatalError("ERROR found in jsnap mode strict.....exiting") else: return True else: return True elif snaptype == "check": if section: cmd_check = 'jsnap --'+ snaptype + " " + timestamp + '_pre' + ',' + timestamp + '_post' + ' -l ' + self.user + ' -p ' + self.password + ' -t ' + self.target + ' -s' + section + ' ' + test else: cmd_check = 'jsnap --'+ snaptype + " " + timestamp + '_pre' + ',' + timestamp + '_post' + ' -l ' + self.user + ' -p ' + self.password + ' -t ' + self.target + ' ' + test print ("Executing: %s" %cmd_check) jsnap_command = sub.Popen(cmd_check, stdout=sub.PIPE, stderr=sub.PIPE, shell=True, cwd=dirpath) output, errors = jsnap_command.communicate() print (output) print (errors) if ((("Exiting." in errors)) or ("Unable to connect to device: " in errors) or ("jsnap: not found" in errors) or ("appears to be missing" in output)): print (output) print (errors) raise FatalError("Unable to execute jsnap.....exiting") else: if mode == "strict": if "ERROR" in output or "ERROR" in errors: raise FatalError("ERROR found in jsnap mode strict.....exiting") else: return True else: return True else: raise FatalError("Invalid snap type.....exiting") def rescue_configuration(self, print_diff=False, **kvargs): """ Function that issues Save/Load a Rescue Configuration """ if 'action' in kvargs.keys(): action = kvargs['action'] # Saving rescue configuration if action == 'save': try: self._conn.rpc.request_save_rescue_configuration() except RpcError as err: rpc_error = err.__repr__() print (rpc_error) return self # Checking if this attribute was already attached to Device if hasattr(self._conn, "candidate"): pass else: self._conn.bind(candidate=Config) # Locking configuration try: self._conn.candidate.lock() except LockError as l_error: print ("*WARN* Problems locking configuration: %s" % (l_error)) raise FatalError("Unable to lock configuration.....exiting") # Loading rescue configuration if action == 'load': try: self._conn.rpc.load_configuration({'rescue': 'rescue'}) except RpcError as err: rpc_error = err.__repr__() print (rpc_error) except ConfigLoadError as error: print ("*WARN* Problems loading configuration: %s" % (error)) raise FatalError("Unable to load configuration.....exiting") if print_diff: print ('*INFO* Configuration to be commited %s' % (self._conn.candidate.diff())) try: self._conn.candidate.commit(comment='loading rescue configuration') self._conn.candidate.unlock() return True except (CommitError, LockError) as err: print (err) raise FatalError("Unable to commit or unlock configuration......exiting") def commands_executor(self, **kvargs): """ Function that issues commands """ # Getting RF built-in variables variables = BuiltIn().get_variables() regex = '' xpath = '' if 'xpath' in kvargs.keys(): xpath = kvargs['xpath'] if 'regex' in kvargs.keys(): regex = kvargs['regex'] if 'output_dir' in kvargs.keys(): output_directory = kvargs['output_dir'] else: output_directory = variables['${path}'] command = kvargs['command'] format = kvargs['format'] root_dir = variables['${OUTPUT_DIR}'] test_case = variables['${testname}'] if format == "text": # tmp_dir = tempfile.mkdtemp(prefix='_') # if output_directory == None: # dirpath = "/collector/" + tmp_dir + "/" + timestamp + "/" # else: # dirpath = output_directory + "/" + tmp_dir + "/" + test_case.replace(" ", "_") + "/commands" # Create directory if does not exist # if not os.path.exists(dirpath): # os.makedirs(dirpath, mode=0777) if regex: try: cmd_to_execute = self._conn.rpc.cli(command) except RpcError as err: rpc_error = err.__repr__() print (xmltodict.parse(rpc_error)['rpc-error']['error-message']) raise FatalError("Error executing RPC,exiting...") operations = command.split("|")[1:] result_tmp = cmd_to_execute.text lines = result_tmp.strip().split('\n') for operation in operations: if re.search("count", operation, re.IGNORECASE): print ('*INFO* Count: %s lines' % len(lines)) return len(lines) match = re.search('match "?(.*)"?', operation, re.IGNORECASE) if match: regex = match.group(1).strip() lines_filtered = [] for line in lines: if re.search(regex, line, re.IGNORECASE): lines_filtered.append(line) lines = lines_filtered match = re.search('except "?(.*)"?', operation, re.IGNORECASE) if match: regex = match.group(1).strip() lines_filtered = [] for line in lines: if re.search(regex, line, re.IGNORECASE): pass else: lines_filtered.append(line) lines = lines_filtered text_matches = re.search(regex, cmd_to_execute.text, re.MULTILINE) if text_matches: print (text_matches.groups()) return text_matches.groups() else: print ("Executing: %s" %command) try: cmd_to_execute = self._conn.rpc.cli(command) except RpcError as err: rpc_error = err.__repr__() print (xmltodict.parse(rpc_error)['rpc-error']['error-message']) raise FatalError("Error executing RPC,exiting...") # #print (type(cmd_to_execute)) # if isinstance(cmd_to_execute, bool): # return True # else: # cmd_clean = command.replace(" ", "_").replace('_"', '_').replace('"_', '_').replace('"', '').replace("/", "_") # filename = timestamp2 + '_'+ self.target + "_" + cmd_clean + "." + "txt" # path = os.path.join(dirpath, filename).replace(root_dir, '.') # print ("Saving file as: %s" %path) # print ('*HTML* <a href="%s" target="_blank">%s</a>' % (path, path)) # try: # with open(path, 'w') as file_to_save: # file_to_save.write(cmd_to_execute.text) # return True # except IOError as err: # print (err.errno, err.strerror) # raise FatalError("Error opening File, exiting...") elif format == "xml": if xpath: print ("Executing: %s [%s]" %(command, xpath)) try: cmd_to_execute = self._conn.rpc.cli(command, format='xml') xml_result = etree.tostring(cmd_to_execute) except RpcError as err: rpc_error = err.__repr__() print (xmltodict.parse(rpc_error)['rpc-error']['error-message']) raise FatalError("Error executing RPC, exiting...") xpath_result = cmd_to_execute.xpath(xpath)[0].text.strip() if xpath_result == None: raise FatalError("XPATH malformed, exiting...") else: print (xpath_result) return xpath_result else: try: cmd_to_execute = self._conn.rpc.cli(command, format='xml') xml_result = etree.tostring(cmd_to_execute) except RpcError as err: rpc_error = err.__repr__() print (xmltodict.parse(rpc_error)['rpc-error']['error-message']) raise FatalError("Error executing RPC, exiting...") return xml_result else: raise FatalError("Format not valid, exiting...") def save_config_to_file(self, **kvargs): """ Function that saves a configuration to a file in a JunOS device """ directory = kvargs['directory'] + '/' + timestamp4 print ("*INFO* Saving current configuration...") file_obj = StartShell(self._conn) file_obj.open() got = file_obj.run("cli -c 'show configuration | save " + directory + "_config.txt' ") file_obj.close() print ("*INFO* %s" % (got)) return got[-2].split("'")[1] def rollback(self, commit_comment='__JRouter__', **kvargs): """ Function that performs rollback rollback_num = number """ rollback_num = kvargs['rollback_num'] try: rollback_num = int(rollback_num) if rollback_num > 50: raise FatalError("Sorry. 'rollback_num' must lower than 50") except Exception as e: raise FatalError("Sorry. 'rollback_num' must be an integer.") if hasattr(self._conn, "candidate"): pass else: self._conn.bind(candidate=Config) try: self._conn.candidate.lock() except LockError as l_error: print ("*WARN* Problems locking configuration: %s" % (l_error)) raise FatalError("Unable to lock configuration... exiting") try: print ("Rolling back configuration....") self._conn.candidate.rollback(rollback_num) self._conn.candidate.commit(comment=commit_comment) self._conn.candidate.unlock() return True except RpcError as err: rpc_error = err.__repr__() raise FatalError(xmltodict.parse(rpc_error)['rpc-error']['error-message']) def _is_dual_RE (self): """ Auxiliar function that returns True if the system is dual-RE and both RE are available """ if self._conn.facts['2RE']: return True else: return False def reboot_re (self,**kvargs): """ Function for rebooting backup RE **kvargs role: master/backup """ try: role = kvargs['role'] except KeyError: raise ContinuableError("Missing Key....role") # Dual RE and role backup if self._is_dual_RE () and role == 'backup': try: print ("Rebooting Backup Routing Engine....") self._conn.rpc.request_reboot(other_routing_engine=True) # sleeping to avoid quick return sleep (60) return True except RpcError as err: raise ContinuableError("Error executing RPC... {0}".format(err)) # Single RE or DUAL-RE system capabable with only 1 available RE else: try: print ("Rebooting Master Routing Engine....") self._conn.rpc.request_reboot() self._conn.close () # sleeping to avoid quick return sleep (60) try: self._conn.open(auto_probe=600) return True except ConnectError as c_error: raise ContinuableError("ERROR: Routing Engine is not Online after 10 min" + str(c_error)) except RpcError as err: raise ContinuableError("Error executing RPC... {0}".format(err)) def switchover(self): """ Function to perfom RE switchover """ # We need to verify that backup RE is ready before proceed b_slot = self.get_slot('backup') b_state = self._conn.rpc.get_route_engine_information(slot=b_slot) state = b_state.findtext('route-engine/mastership-state') if (state != "backup"): raise FatalError("Backup RE is not ready") try: self.open_connection() print ('Executing switchover to complete the SW upgrade !!!') switchover_cmd = self._conn.cli("request chassis routing-engine master switch no-confirm", format='xml', warning=False) self.close_connection() except ConnectError as c_error: raise FatalError(c_error) # except TError.TimeoutExpiredError as Terr: # print (Terr) # pass # except NcErrors.SessionCloseError as Serr: # print (Serr) # pass except SocketError as S_err: print (S_err) pass except ConnectClosedError as CC_error: print (CC_error) pass sleep(60) try: # WA for dealing with in band connections print ("Re-opening connection.......") self._conn.open(auto_probe=900) return True except ConnectError as c_error: raise FatalError(c_error) def reboot (self): """ Function for rebooting both RE """ # Dual RE and role backup try: print ("Rebooting Both Routing Engines....") cmd = self._conn.rpc.request_reboot(both_routing_engines=True) # sleeping to avoid quick return sleep (60) return True except RpcError as err: raise FatalError("Error executing RPC... %s" %err) def get_routing_table(self, **kvargs): """ Function that gathers the routing table from a device. It returns the whole routing table if no route is specified. If route is specified, next_hop can be also specified and routing table nexthop output will be compared against it. """ try: tbl = RouteTable(self._conn) except ConnectError as c_error: raise FatalError(c_error) complete_rt = tbl.get() if 'route' in kvargs.keys(): route = kvargs['route'] print ('route', route) if route != 'None': single_rt = tbl.get(route) # Routing Table dictionary rt = {} for item in tbl: # Remove "RouteTableView:" from item = RouteTableView:0.0.0.0/0 destination = str(item).split(":")[1] rt[destination] = [item.nexthop, item.age, item.via, item.protocol] return rt def pretty_time_delta(self, seconds): """ Helper function that returns formatted time """ sign_string = '-' if seconds < 0 else '' seconds = abs(int(seconds)) days, seconds = divmod(seconds, 86400) hours, seconds = divmod(seconds, 3600) minutes, seconds = divmod(seconds, 60) if days > 0: return '%s%dd%dh%dm%ds' % (sign_string, days, hours, minutes, seconds) elif hours > 0: return '%s%dh%dm%ds' % (sign_string, hours, minutes, seconds) elif minutes > 0: return '%s%dm%ds' % (sign_string, minutes, seconds) else: return '%s%ds' % (sign_string, seconds) def get_config(self, xml_filter=None): """ Function that returns a piece of a JunOS device configuration """ if xml_filter is None: cnf = self._conn.rpc.get_config() else: # Should user wants to filter out configuration and extract only a piece of it # e.g. SNMP #cnf = dev.rpc.get_config(filter_xml=etree.XML('<snmp></snmp>')) # interfaces #cnf = dev.rpc.get_config(filter_xml=etree.XML('<configuration><interfaces/></configuration>')) cnf = self._conn.rpc.get_config(filter_xml=etree.XML(xml_filter)) #print (etree.tostring(cnf)) config = etree.tostring(cnf) #print (config) return config
from jnpr.junos import Device dev = Device('host', user='******', password='******') dev.open() print dev.cli("show version | match py")
class TestCore(unittest.TestCase): @classmethod def setUpClass(self): from jnpr.junos import Device self.dev = Device(host='xxxx', user='******', password='******') self.dev.open() @classmethod def tearDownClass(self): self.dev.close() def test_device_open(self): self.assertEqual(self.dev.connected, True) def test_device_facts(self): assert self.dev.facts['hostname'] == 'highlife' def test_device_get_timeout(self): assert self.dev.timeout == 30 def test_device_set_timeout(self): self.dev.timeout = 35 assert self.dev.timeout == 35 def test_device_cli(self): self.assertTrue('qfx5100' in self.dev.cli('show version')) def test_device_rpc(self): res = self.dev.rpc.get_route_information(destination='10.48.21.71') self.assertEqual(res.tag, 'route-information') def test_device_rpc_format_text(self): res = self.dev.rpc.get_interface_information({'format': 'text'}) self.assertEqual(res.tag, 'output') def test_device_rpc_timeout(self): with self.assertRaises(RpcTimeoutError): self.dev.rpc.get_route_information(dev_timeout=0.01) def test_device_rpc_normalize_true(self): rsp = self.dev.rpc.get_interface_information(interface_name='ge-0/0/1', normalize=True) self.assertEqual( rsp.xpath('physical-interface/name')[0].text, 'ge-0/0/1') 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()
class TestDevice(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() @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectAuthError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.AuthenticationError self.assertRaises(EzErrors.ConnectAuthError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectRefusedError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError self.assertRaises(EzErrors.ConnectRefusedError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') @patch('jnpr.junos.device.datetime') def test_device_ConnectTimeoutError(self, mock_datetime, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError( "Could not open socket to 1.1.1.1:830") from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectTimeoutError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') @patch('jnpr.junos.device.datetime') def test_device_diff_err_message(self, mock_datetime, mock_manager): NcErrors.SSHError.message = 'why are you trying :)' mock_manager.connect.side_effect = NcErrors.SSHError from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectUnknownHostError(self, mock_manager): import socket mock_manager.connect.side_effect = socket.gaierror self.assertRaises(EzErrors.ConnectUnknownHostError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_other_error(self, mock_manager): mock_manager.connect.side_effect = TypeError self.assertRaises(EzErrors.ConnectError, self.dev.open) def test_device_probe_error(self): mock_probe = MagicMock() mock_probe.return_value = None self.dev.probe = mock_probe def fn(): self.dev.open(auto_probe=1) self.assertRaises(EzErrors.ProbeError, fn) def test_device_property_logfile_isinstance(self): mock = MagicMock() with patch(builtin_string + '.open', mock): if sys.version >'3': builtin_file = 'io.TextIOWrapper' else: builtin_file = builtin_string + '.file' with patch(builtin_file, MagicMock): handle = open('filename', 'r') self.dev.logfile = handle self.assertEqual(self.dev.logfile, handle) def test_device_host_mand_param(self): self.assertRaises(ValueError, Device, user='******', password='******', gather_facts=False) def test_device_property_logfile_close(self): self.dev._logfile = MagicMock() self.dev._logfile.close.return_value = 0 self.dev.logfile = None self.assertFalse(self.dev._logfile) def test_device_property_logfile_exception(self): try: self.dev.logfile = True except Exception as ex: self.assertEqual(type(ex), ValueError) def test_device_repr(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.assertEqual(repr(localdev), 'Device(1.1.1.1)') def test_device_local(self): Device.ON_JUNOS = True localdev = Device() self.assertEqual(localdev._hostname, 'localhost') @patch('jnpr.junos.device.os') @patch(builtin_string + '.open') @patch('paramiko.config.SSHConfig.lookup') def test_device__sshconf_lkup(self, os_mock, open_mock, mock_paramiko): os_mock.path.exists.return_value = True self.dev._sshconf_lkup() mock_paramiko.assert_called_any() @patch('jnpr.junos.device.os') @patch(builtin_string + '.open') @patch('paramiko.config.SSHConfig.lookup') def test_device__sshconf_lkup_def(self, os_mock, open_mock, mock_paramiko): os_mock.path.exists.return_value = True self.dev._ssh_config = '/home/rsherman/.ssh/config' self.dev._sshconf_lkup() mock_paramiko.assert_called_any() @patch('os.getenv') def test_device__sshconf_lkup_path_not_exists(self, mock_env): mock_env.return_value = '/home/test' self.assertEqual(self.dev._sshconf_lkup(), None) @patch('os.getenv') def test_device__sshconf_lkup_home_not_defined(self, mock_env): mock_env.return_value = None self.assertEqual(self.dev._sshconf_lkup(), None) mock_env.assert_called_with('HOME') @patch('ncclient.manager.connect') @patch('jnpr.junos.Device.execute') def test_device_open(self, mock_connect, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_cat.return_value = """ domain jls.net """ mock_connect.side_effect = self._mock_manager mock_execute.side_effect = self._mock_manager self.dev2 = Device( host='2.2.2.2', user='******', password='******') self.dev2.open() self.assertEqual(self.dev2.connected, True) @patch('jnpr.junos.Device.execute') def test_device_facts(self, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.return_value = """ domain jls.net """ self.dev.facts_refresh() assert self.dev.facts['version'] == facts['version'] @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.device.warnings') def test_device_facts_error(self, mock_warnings, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.side_effect = IOError('File cant be handled') self.dev.facts_refresh() self.assertTrue(mock_warnings.warn.called) def test_device_hostname(self): self.assertEqual(self.dev.hostname, '1.1.1.1') def test_device_user(self): self.assertEqual(self.dev.user, 'rick') def test_device_get_password(self): self.assertEqual(self.dev.password, None) def test_device_set_password(self): self.dev.password = '******' self.assertEqual(self.dev._auth_password, 'secret') def test_device_get_timeout(self): self.assertEqual(self.dev.timeout, 30) def test_device_set_timeout(self): self.dev.timeout = 10 self.assertEqual(self.dev.timeout, 10) def test_device_manages(self): self.assertEqual(self.dev.manages, [], 'By default manages will be empty list') @patch('ncclient.manager.connect') @patch('jnpr.junos.Device.execute') def test_device_open_normalize(self, mock_connect, mock_execute): mock_connect.side_effect = self._mock_manager self.dev2 = Device(host='2.2.2.2', user='******', password='******') self.dev2.open(gather_facts=False, normalize=True) self.assertEqual(self.dev2.transform, self.dev2._norm_transform) def test_device_set_facts_exception(self): try: self.dev.facts = 'test' except RuntimeError as ex: self.assertEqual(RuntimeError, type(ex)) @patch('jnpr.junos.Device.execute') def test_device_cli(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli('show cli directory').tag, 'cli') @patch('jnpr.junos.Device.execute') def test_device_cli_conf_info(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('ge-0/0/0' in self.dev.cli('show configuration')) @patch('jnpr.junos.Device.execute') def test_device_cli_output(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Alarm' in self.dev.cli('show system alarms')) @patch('jnpr.junos.Device.execute') def test_device_cli_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli('show system uptime | display xml rpc') .tag, 'get-system-uptime-information') def test_device_cli_exception(self): self.dev.rpc.cli = MagicMock(side_effect=AttributeError) val = self.dev.cli('show version') self.assertEqual(val, 'invalid command: show version') @patch('jnpr.junos.Device.execute') def test_device_display_xml_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual( self.dev.display_xml_rpc('show system uptime ').tag, 'get-system-uptime-information') @patch('jnpr.junos.Device.execute') def test_device_display_xml_rpc_text(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertIn( '<get-system-uptime-information>', self.dev.display_xml_rpc( 'show system uptime ', format='text').decode('utf-8')) @patch('jnpr.junos.Device.execute') def test_device_display_xml_exception(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual( self.dev.display_xml_rpc('show foo'), 'invalid command: show foo| display xml rpc') def test_device_execute(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) print (self.dev.execute('<get-system-core-dumps/>').tag) self.assertEqual(self.dev.execute('<get-system-core-dumps/>').tag, 'directory-list') def test_device_execute_topy(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute('<get-system-core-dumps/>', to_py=self._do_nothing), 'Nothing') # This test is for the commented out rpc-error code # def test_device_execute_exception(self): # self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) # self.assertRaises(RpcError, self.dev.execute, # '<load-configuration-error/>') def test_device_execute_unknown_exception(self): class MyException(Exception): pass self.dev._conn.rpc = MagicMock(side_effect=MyException) self.assertRaises(MyException, self.dev.execute, '<get-software-information/>') def test_device_execute_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises(RpcError, self.dev.rpc.get_rpc_error) def test_device_execute_permission_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises( EzErrors.PermissionError, self.dev.rpc.get_permission_denied) def test_device_execute_index_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertTrue(self.dev.rpc.get_index_error()) def test_device_execute_ValueError(self): self.assertRaises(ValueError, self.dev.execute, None) def test_device_execute_unopened(self): self.dev.connected = False self.assertRaises(EzErrors.ConnectClosedError, self.dev.execute, None) def test_device_execute_timeout(self): self.dev._conn.rpc = MagicMock(side_effect=TimeoutExpiredError) self.assertRaises( EzErrors.RpcTimeoutError, self.dev.rpc.get_rpc_timeout) def test_device_execute_closed(self): self.dev._conn.rpc = MagicMock(side_effect=NcErrors.TransportError) self.assertRaises( EzErrors.ConnectClosedError, self.dev.rpc.get_rpc_close) self.assertFalse(self.dev.connected) def test_device_rpcmeta(self): self.assertEqual(self.dev.rpc.get_software_information.__doc__, 'get-software-information') def test_device_probe_timeout_zero(self): with patch('jnpr.junos.device.socket'): self.assertFalse(self.dev.probe(0)) def test_device_probe_timeout_gt_zero(self): with patch('jnpr.junos.device.socket'): self.assertTrue(self.dev.probe(1), 'probe fn is not working for' ' timeout greater than zero') def test_device_probe_timeout_exception(self): with patch('jnpr.junos.device.socket') as mock_socket: with patch('jnpr.junos.device.time.sleep') as mock_time: mock_socket.socket.return_value.close.side_effect \ = RuntimeError mock_time.return_value = None self.assertFalse(self.dev.probe(.01)) def test_device_bind_varg(self): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic_mock' self.dev.bind(mock) self.assertEqual(self.dev.magic_mock.__name__, 'magic_mock') def test_device_bind_kvarg(self): self.dev.bind() mock = MagicMock() mock.return_value = 'Test' self.dev.bind(kw=mock) self.assertEqual(self.dev.kw, 'Test') def test_device_bind_varg_exception(self): def varg(): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic mock' # for *args self.dev.bind(mock) self.dev.bind(mock) self.assertRaises(ValueError, varg) def test_device_bind_kvarg_exception(self): def kve(): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic mock' # for **kwargs self.dev.bind(kw=mock) self.dev.bind(kw=mock) self.assertRaises(ValueError, kve) def test_device_template(self): # Try to load the template relative to module base try: template = self.dev.Template( 'tests/unit/templates/config-example.xml') except: # Try to load the template relative to test base try: template = self.dev.Template('templates/config-example.xml') except: raise self.assertEqual(template.render({'host_name': '1', 'domain_name': '2'}), 'system {\n host-name 1;\n domain-name 2;\n}') def test_device_close(self): def close_conn(): self.dev.connected = False self.dev.close = MagicMock(name='close') self.dev.close.side_effect = close_conn self.dev.close() self.assertEqual(self.dev.connected, False) @patch('ncclient.manager.connect') def test_device_context_manager(self, mock_connect): mock_connect.side_effect = self._mock_manager try: with Device(host='3.3.3.3', user='******', password='******', gather_facts=False) as dev: self.assertTrue(dev.connected) dev._conn = MagicMock(name='_conn') dev._conn.connected = True def close_conn(): dev.connected = False dev.close = MagicMock(name='close') dev.close.side_effect = close_conn raise RpcError except Exception as e: self.assertIsInstance(e, RpcError) self.assertFalse(dev.connected) def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) with open(fpath) as fp: foo = fp.read() if fname == 'get-rpc-error.xml': # Raise ncclient exception for error raise RPCError(etree.XML(foo)) elif fname == 'get-permission-denied.xml': # Raise ncclient exception for error raise RPCError(etree.XML(foo)) elif (fname == 'get-index-error.xml' or fname == 'get-system-core-dumps.xml' or fname == 'load-configuration-error.xml'): rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply()) elif (fname == 'show-configuration.xml' or fname == 'show-system-alarms.xml'): rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply())._NCElement__doc else: rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply())._NCElement__doc[0] return rpc_reply 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: if args[0].tag == 'command': if args[0].text == 'show cli directory': return self._read_file('show-cli-directory.xml') elif args[0].text == 'show configuration': return self._read_file('show-configuration.xml') elif args[0].text == 'show system alarms': return self._read_file('show-system-alarms.xml') elif args[0].text == 'show system uptime | display xml rpc': return self._read_file('show-system-uptime-rpc.xml') else: raise RpcError else: return self._read_file(args[0].tag + '.xml') def _do_nothing(self, *args, **kwargs): return 'Nothing'
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")
import jnpr.junos import os import sys from pprint import pprint from jnpr.junos import Device Host = raw_input('Enter Hostname or IP address of Device: ') r0 = Device(host=Host, user='******', password='******').open() response = r0.cli('show bgp group NTT') print response # # response = r0.cli('show interfaces terse | match NTT') print response # # response = r0.cli('show interfaces detail ge-0/0/0.0') print response
class Netconf(object): def __init__(self, module): self.module = module self.device = None self.config = None self._locked = False def _fail(self, msg): if self.device: if self._locked: self.config.unlock() self.disconnect() self.module.fail_json(msg=msg) 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 run_commands(self, commands, **kwargs): response = list() fmt = kwargs.get('format') or 'xml' for cmd in to_list(commands): try: resp = self.device.cli(command=cmd, format=fmt) response.append(resp) except (ValueError, RpcError): exc = get_exception() self._fail('Unable to get cli output: %s' % str(exc)) except Exception: exc = get_exception() self._fail('Uncaught exception - please report: %s' % str(exc)) return response def unlock_config(self): try: self.config.unlock() self._locked = False except UnlockError: exc = get_exception() self.module.log('unable to unlock config: {0}'.format(str(exc))) def lock_config(self): try: self.config.lock() self._locked = True except LockError: exc = get_exception() self.module.log('unable to lock config: {0}'.format(str(exc))) def check_config(self): if not self.config.commit_check(): self._fail(msg='Commit check failed') def commit_config(self, comment=None, confirm=None): try: kwargs = dict(comment=comment) if confirm and confirm > 0: kwargs['confirm'] = confirm return self.config.commit(**kwargs) except CommitError: exc = get_exception() msg = 'Unable to commit configuration: {0}'.format(str(exc)) self._fail(msg=msg) def load_config(self, candidate, action='replace', comment=None, confirm=None, format='text', commit=True): merge = action == 'merge' overwrite = action == 'overwrite' self.lock_config() try: self.config.load(candidate, format=format, merge=merge, overwrite=overwrite) except ConfigLoadError: exc = get_exception() msg = 'Unable to load config: {0}'.format(str(exc)) self._fail(msg=msg) diff = self.config.diff() self.check_config() if commit and diff: self.commit_config(comment=comment, confirm=confirm) self.unlock_config() return diff def rollback_config(self, identifier, commit=True, comment=None): self.lock_config() try: result = self.config.rollback(identifier) except Exception: exc = get_exception() msg = 'Unable to rollback config: {0}'.format(str(exc)) self._fail(msg=msg) diff = self.config.diff() if commit: self.commit_config(comment=comment) self.unlock_config() return diff def disconnect(self): if self.device: self.device.close() def get_facts(self, refresh=True): if refresh: self.device.facts_refresh() return self.device.facts def get_config(self, config_format="text"): if config_format not in ['text', 'set', 'xml']: msg = 'invalid config format... must be one of xml, text, set' self._fail(msg=msg) ele = self.rpc('get_configuration', format=config_format) if config_format in ['text', 'set']: return str(ele.text).strip() elif config_format == "xml": return ele def rpc(self, name, format='xml', **kwargs): meth = getattr(self.device.rpc, name) reply = meth({'format': format}, **kwargs) return reply
class TestCore(unittest.TestCase): @classmethod def setUpClass(self): from jnpr.junos import Device self.dev = Device(host='highlife.englab.juniper.net', user='******', password='******') self.dev.open() @classmethod def tearDownClass(self): self.dev.close() def test_device_open(self): self.assertEqual(self.dev.connected, True) def test_device_facts(self): assert self.dev.facts['hostname'] == 'highlife' def test_device_get_timeout(self): assert self.dev.timeout == 30 def test_device_set_timeout(self): self.dev.timeout = 35 assert self.dev.timeout == 35 def test_device_cli(self): self.assertTrue('qfx5100' in self.dev.cli('show version')) def test_device_rpc(self): res = self.dev.rpc.get_route_information(destination='10.48.21.71') self.assertEqual(res.tag, 'route-information') def test_device_rpc_format_text(self): res = self.dev.rpc.get_interface_information({'format': 'text'}) self.assertEqual(res.tag, 'output') def test_device_rpc_timeout(self): with self.assertRaises(RpcTimeoutError): self.dev.rpc.get_route_information(dev_timeout=0.01) def test_device_rpc_normalize_true(self): rsp = self.dev.rpc.get_interface_information( interface_name='ge-0/0/1', normalize=True) self.assertEqual(rsp.xpath('physical-interface/name')[0].text, 'ge-0/0/1') 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()
''' Do selective imports from Python Packages from x import y #imports only the y package from the greater package set of x ''' from pprint import pprint from jnpr.junos import Device ''' Create a new device object. This represents the SRX we are going to connect to. The hostname/IP, username, and password are required. ''' dev = Device(host='172.23.230.204', user='******', password='******' ) ''' Creates a Netconf session to the SRX ''' dev.open() ''' Prints out the output of the show version command ''' print dev.cli("show version") ''' Closes the netconf connection to the SRX ''' dev.close()
class TestDevice(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() @patch("ncclient.operations.session.CloseSession.request") def tearDown(self, mock_session): self.dev.close() @patch("jnpr.junos.device.netconf_ssh") def test_device_ConnectAuthError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.AuthenticationError self.assertRaises(EzErrors.ConnectAuthError, self.dev.open) @patch("jnpr.junos.device.netconf_ssh") def test_device_ConnectRefusedError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError self.assertRaises(EzErrors.ConnectRefusedError, self.dev.open) @patch("jnpr.junos.device.netconf_ssh") @patch("jnpr.junos.device.datetime") def test_device_ConnectTimeoutError(self, mock_datetime, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError("Could not open socket to 1.1.1.1:830") from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectTimeoutError, self.dev.open) @patch("jnpr.junos.device.netconf_ssh") @patch("jnpr.junos.device.datetime") def test_device_diff_err_message(self, mock_datetime, mock_manager): NcErrors.SSHError.message = "why are you trying :)" mock_manager.connect.side_effect = NcErrors.SSHError from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectError, self.dev.open) @patch("jnpr.junos.device.netconf_ssh") def test_device_ConnectUnknownHostError(self, mock_manager): import socket mock_manager.connect.side_effect = socket.gaierror self.assertRaises(EzErrors.ConnectUnknownHostError, self.dev.open) @patch("jnpr.junos.device.netconf_ssh") def test_device_other_error(self, mock_manager): mock_manager.connect.side_effect = TypeError self.assertRaises(EzErrors.ConnectError, self.dev.open) def test_device_probe_error(self): mock_probe = MagicMock() mock_probe.return_value = None self.dev.probe = mock_probe def fn(): self.dev.open(auto_probe=1) self.assertRaises(EzErrors.ProbeError, fn) def test_device_property_logfile_isinstance(self): mock = MagicMock() with patch("__builtin__.open", mock): with patch("__builtin__.file", MagicMock): handle = open("filename", "r") self.dev.logfile = handle self.assertEqual(self.dev.logfile, handle) def test_device_host_mand_param(self): self.assertRaises(ValueError, Device, user="******", password="******", gather_facts=False) def test_device_property_logfile_close(self): self.dev._logfile = MagicMock() self.dev._logfile.close.return_value = 0 self.dev.logfile = None self.assertFalse(self.dev._logfile) def test_device_property_logfile_exception(self): try: self.dev.logfile = True except Exception as ex: self.assertEqual(type(ex), ValueError) def test_device_repr(self): localdev = Device(host="1.1.1.1", user="******", password="******", gather_facts=False) self.assertEqual(repr(localdev), "Device(1.1.1.1)") def test_device_local(self): Device.ON_JUNOS = True localdev = Device() self.assertEqual(localdev._hostname, "localhost") @patch("jnpr.junos.device.os") @patch("__builtin__.open") @patch("paramiko.config.SSHConfig.lookup") def test_device__sshconf_lkup(self, os_mock, open_mock, mock_paramiko): os_mock.path.exists.return_value = True self.dev._sshconf_lkup() mock_paramiko.assert_called_any() @patch("jnpr.junos.device.os") @patch("__builtin__.open") @patch("paramiko.config.SSHConfig.lookup") def test_device__sshconf_lkup_def(self, os_mock, open_mock, mock_paramiko): os_mock.path.exists.return_value = True self.dev._ssh_config = "/home/rsherman/.ssh/config" self.dev._sshconf_lkup() mock_paramiko.assert_called_any() @patch("os.getenv") def test_device__sshconf_lkup_path_not_exists(self, mock_env): mock_env.return_value = "/home/test" self.assertEqual(self.dev._sshconf_lkup(), None) @patch("os.getenv") def test_device__sshconf_lkup_home_not_defined(self, mock_env): mock_env.return_value = None self.assertEqual(self.dev._sshconf_lkup(), None) mock_env.assert_called_with("HOME") @patch("ncclient.manager.connect") @patch("jnpr.junos.Device.execute") def test_device_open(self, mock_connect, mock_execute): with patch("jnpr.junos.utils.fs.FS.cat") as mock_cat: mock_cat.return_value = """ domain jls.net """ mock_connect.side_effect = self._mock_manager mock_execute.side_effect = self._mock_manager self.dev2 = Device(host="2.2.2.2", user="******", password="******") self.dev2.open() self.assertEqual(self.dev2.connected, True) @patch("jnpr.junos.Device.execute") def test_device_facts(self, mock_execute): with patch("jnpr.junos.utils.fs.FS.cat") as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.return_value = """ domain jls.net """ self.dev.facts_refresh() assert self.dev.facts["version"] == facts["version"] @patch("jnpr.junos.Device.execute") @patch("jnpr.junos.device.warnings") def test_device_facts_error(self, mock_warnings, mock_execute): with patch("jnpr.junos.utils.fs.FS.cat") as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.side_effect = IOError("File cant be handled") self.dev.facts_refresh() self.assertTrue(mock_warnings.warn.called) def test_device_hostname(self): self.assertEqual(self.dev.hostname, "1.1.1.1") def test_device_user(self): self.assertEqual(self.dev.user, "rick") def test_device_get_password(self): self.assertEqual(self.dev.password, None) def test_device_set_password(self): self.dev.password = "******" self.assertEqual(self.dev._auth_password, "secret") def test_device_get_timeout(self): self.assertEqual(self.dev.timeout, 30) def test_device_set_timeout(self): self.dev.timeout = 10 self.assertEqual(self.dev.timeout, 10) def test_device_manages(self): self.assertEqual(self.dev.manages, [], "By default manages will be empty list") @patch("ncclient.manager.connect") @patch("jnpr.junos.Device.execute") def test_device_open_normalize(self, mock_connect, mock_execute): mock_connect.side_effect = self._mock_manager self.dev2 = Device(host="2.2.2.2", user="******", password="******") self.dev2.open(gather_facts=False, normalize=True) self.assertEqual(self.dev2.transform, self.dev2._norm_transform) def test_device_set_facts_exception(self): try: self.dev.facts = "test" except RuntimeError as ex: self.assertEqual(RuntimeError, type(ex)) @patch("jnpr.junos.Device.execute") def test_device_cli(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli("show cli directory").tag, "cli") @patch("jnpr.junos.Device.execute") def test_device_cli_conf_info(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue("ge-0/0/0" in self.dev.cli("show configuration")) @patch("jnpr.junos.Device.execute") def test_device_cli_output(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue("Alarm" in self.dev.cli("show system alarms")) @patch("jnpr.junos.Device.execute") def test_device_cli_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli("show system uptime | display xml rpc").tag, "get-system-uptime-information") def test_device_cli_exception(self): self.dev.rpc.cli = MagicMock(side_effect=AttributeError) val = self.dev.cli("show version") self.assertEqual(val, "invalid command: show version") @patch("jnpr.junos.Device.execute") def test_device_display_xml_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.display_xml_rpc("show system uptime ").tag, "get-system-uptime-information") @patch("jnpr.junos.Device.execute") def test_device_display_xml_rpc_text(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertIn("<get-system-uptime-information>", self.dev.display_xml_rpc("show system uptime ", format="text")) @patch("jnpr.junos.Device.execute") def test_device_display_xml_exception(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.display_xml_rpc("show foo"), "invalid command: show foo| display xml rpc") def test_device_execute(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute("<get-system-core-dumps/>").tag, "directory-list") def test_device_execute_topy(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute("<get-system-core-dumps/>", to_py=self._do_nothing), "Nothing") # This test is for the commented out rpc-error code # def test_device_execute_exception(self): # self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) # self.assertRaises(RpcError, self.dev.execute, # '<load-configuration-error/>') def test_device_execute_unknown_exception(self): class MyException(Exception): pass self.dev._conn.rpc = MagicMock(side_effect=MyException) self.assertRaises(MyException, self.dev.execute, "<get-software-information/>") def test_device_execute_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises(RpcError, self.dev.rpc.get_rpc_error) def test_device_execute_permission_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises(EzErrors.PermissionError, self.dev.rpc.get_permission_denied) def test_device_execute_index_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertTrue(self.dev.rpc.get_index_error()) def test_device_execute_ValueError(self): self.assertRaises(ValueError, self.dev.execute, None) def test_device_execute_unopened(self): self.dev.connected = False self.assertRaises(EzErrors.ConnectClosedError, self.dev.execute, None) def test_device_execute_timeout(self): self.dev._conn.rpc = MagicMock(side_effect=TimeoutExpiredError) self.assertRaises(EzErrors.RpcTimeoutError, self.dev.rpc.get_rpc_timeout) def test_device_execute_closed(self): self.dev._conn.rpc = MagicMock(side_effect=NcErrors.TransportError) self.assertRaises(EzErrors.ConnectClosedError, self.dev.rpc.get_rpc_close) self.assertFalse(self.dev.connected) def test_device_rpcmeta(self): self.assertEqual(self.dev.rpc.get_software_information.func_doc, "get-software-information") def test_device_probe_timeout_zero(self): with patch("jnpr.junos.device.socket"): self.assertFalse(self.dev.probe(0)) def test_device_probe_timeout_gt_zero(self): with patch("jnpr.junos.device.socket"): self.assertTrue(self.dev.probe(1), "probe fn is not working for" " timeout greater than zero") def test_device_probe_timeout_exception(self): with patch("jnpr.junos.device.socket") as mock_socket: with patch("jnpr.junos.device.time.sleep") as mock_time: mock_socket.socket.return_value.close.side_effect = RuntimeError mock_time.return_value = None self.assertFalse(self.dev.probe(0.01)) def test_device_bind_varg(self): self.dev.bind() mock = MagicMock() mock.__name__ = "magic_mock" self.dev.bind(mock) self.assertEqual(self.dev.magic_mock.__name__, "magic_mock") def test_device_bind_kvarg(self): self.dev.bind() mock = MagicMock() mock.return_value = "Test" self.dev.bind(kw=mock) self.assertEqual(self.dev.kw, "Test") def test_device_bind_varg_exception(self): def varg(): self.dev.bind() mock = MagicMock() mock.__name__ = "magic mock" # for *args self.dev.bind(mock) self.dev.bind(mock) self.assertRaises(ValueError, varg) def test_device_bind_kvarg_exception(self): def kve(): self.dev.bind() mock = MagicMock() mock.__name__ = "magic mock" # for **kwargs self.dev.bind(kw=mock) self.dev.bind(kw=mock) self.assertRaises(ValueError, kve) def test_device_template(self): # Try to load the template relative to module base try: template = self.dev.Template("tests/unit/templates/config-example.xml") except: # Try to load the template relative to test base try: template = self.dev.Template("templates/config-example.xml") except: raise self.assertEqual( template.render({"host_name": "1", "domain_name": "2"}), "system {\n host-name 1;\n domain-name 2;\n}" ) def test_device_close(self): def close_conn(): self.dev.connected = False self.dev.close = MagicMock(name="close") self.dev.close.side_effect = close_conn self.dev.close() self.assertEqual(self.dev.connected, False) @patch("ncclient.manager.connect") def test_device_context_manager(self, mock_connect): mock_connect.side_effect = self._mock_manager try: with Device(host="3.3.3.3", user="******", password="******", gather_facts=False) as dev: self.assertTrue(dev.connected) dev._conn = MagicMock(name="_conn") dev._conn.connected = True def close_conn(): dev.connected = False dev.close = MagicMock(name="close") dev.close.side_effect = close_conn raise RpcError except Exception as e: self.assertIsInstance(e, RpcError) self.assertFalse(dev.connected) def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), "rpc-reply", fname) foo = open(fpath).read() if fname == "get-rpc-error.xml": # Raise ncclient exception for error raise RPCError(etree.XML(foo)) elif fname == "get-permission-denied.xml": # Raise ncclient exception for error raise RPCError(etree.XML(foo)) elif ( fname == "get-index-error.xml" or fname == "get-system-core-dumps.xml" or fname == "load-configuration-error.xml" ): rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply()) elif fname == "show-configuration.xml" or fname == "show-system-alarms.xml": rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply())._NCElement__doc else: rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply())._NCElement__doc[0] return rpc_reply 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: if args[0].tag == "command": if args[0].text == "show cli directory": return self._read_file("show-cli-directory.xml") elif args[0].text == "show configuration": return self._read_file("show-configuration.xml") elif args[0].text == "show system alarms": return self._read_file("show-system-alarms.xml") elif args[0].text == "show system uptime | display xml rpc": return self._read_file("show-system-uptime-rpc.xml") else: raise RpcError else: return self._read_file(args[0].tag + ".xml") def _do_nothing(self, *args, **kwargs): return "Nothing"
# In: 10.5.6.54/55269 --> 17.172.232.166/5223;tcp, If: vlan.0, Pkts: 20, Bytes: 5629 # Out: 17.172.232.166/5223 --> 67.253.16.3/25955;tcp, If: fe-0/0/0.0, Pkts: 26, Bytes: 5742 session = {} # sessionfile = "sessions.txt" ip = '10.5.6.254' username = '******' password = '******' dev = Device(host=ip, user=username, password=password) dev.open() sessionoutput = dev.cli('show security flow session brief') # print sessionlist sessionlist = sessionoutput.split("\n") # with open(sessionfile, "r") as sessionlist: for line in sessionlist: temp = [] # print line if "Session ID" in line: temp = line.split(", ") sessionid = int(temp[0].split("Session ID: ")[1])
class myDev(): def __init__(self, hostname=None, port=None, username=None, password=None): self.hostname = hostname self.port = port self.username = username self.password = password self.jnprdev = Device(host=hostname, username=username, password=password, port=port, timeout=5, device_params={'name':'junos'}, hostkey_verify=False) self.rpc = self.jnprdev.rpc def _open(self): try: self.jnprdev.open() except (jnpr.junos.exception.ConnectAuthError, jnpr.junos.exception.ConnectUnknownHostError, jnpr.junos.exception.ConnectRefusedError, jnpr.junos.exception.ProbeError, jnpr.junos.exception.ConnectTimeoutError) as err: raise jException(err) def open_config(self): self._open() self.jnprdev.bind(cu=Config) try: self.jnprdev.cu.lock() except jnpr.junos.exception.LockError as err: raise jException(err, self.hostname) def open_show(self): self._open() def open_fileupload(self): self._open() def load_configuration(self, configuration): try: self.jnprdev.cu.load(configuration, format='set', merge=False) except jnpr.junos.exception.ConfigLoadError as err: raise jException(err, self.hostname) def showcompare(self): return self.jnprdev.cu.diff() def commit(self, comment): try: self.jnprdev.cu.commit(comment=comment, sync=True) except jnpr.junos.exception.CommitError as err: raise jException(err) def rollback(self): # rolling back current changes only self.jnprdev.cu.rollback(rb_id=0) def show_cmd(self, command): self.jnprdev.cli(command, format='text', warning=True) def fileloader(self, package, remotepath): with SCP(self.jnprdev) as scp: try: scp.put(package, remotepath) except Exception as err: raise jException(err, self.hostname) def close(self): if hasattr(self.jnprdev, 'cu'): self.jnprdev.cu.unlock() self.jnprdev.close()
class JunOS_Connection(): 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 hostcommit(self,hostname): set_hostname='set system host-name %s' % hostname self._conf_JunOS.load(set_hostname, format='set') self._conf_JunOS.commit() print "Hostname Changed" def ssh(self): set_Ssh=("set system services ssh") self._conf_JunOS.load(set_Ssh, format='set') self._conf_JunOS.commit() print "SSH Enabled" def telnet(self): set_Telnet=("set system services telnet") self._conf_JunOS.load(set_Telnet, format='set') self._conf_JunOS.commit() print "TELNET Enabled" def ftp(self): set_Ftp=("set system services ftp") self._conf_JunOS.load(set_Ftp, format='set') self._conf_JunOS.commit() print"FTP Enabled" def ntp(self,boot,ntp): ###########Boot Server Command########### if len(boot[0])!=0: boot="set system ntp boot-server %s" % boot self._conf_JunOS.load(boot, format='set') ###########NTP Server Command########### ntp="set system ntp server %s" % ntp self._conf_JunOS.load(ntp, format='set') self._conf_JunOS.commit() def dhcp(self,pool, cdr, router,low, high): router_List=[pool, cdr, router] self.dhcp_router=("set system services dhcp pool %s/%s router %s") % tuple(router_List) self._conf_JunOS.load(self.dhcp_router, format='set') address_Range_List=[pool, cdr, low, high] self.dhcp_add_Range=("set system services dhcp pool %s/%s address-range low %s " "high %s") % tuple(address_Range_List) self._conf_JunOS.load(self.dhcp_add_Range, format='set') self._conf_JunOS.commit() print "DHCP SERVER CREATED" def vlan_Command(self,name, id , interface): set_vlan=[name,id] if len(interface)==0: if len(id)==0: print("Err") else: print "set vlans %s vlan-id %s" % tuple(set_vlan) else: set_Interface=[name,id,interface] print "set vlans %s vlan-id %s interface %s" % tuple(set_Interface) def vr(self,vr_var,int_var,unit_var): ## Create first VR command ## self.set_VR='set routing-instances %s instance-type virtual-router' % vr_var ## Combine int and unit to get correct syntax ## self.int_var = int_var + "." + unit_var ## Make a list for next command ## vr_list = [vr_var, self.int_var] ## Create second VR command ## self.set_int="set routing-instances %s interface %s" % tuple(vr_list) ## Execute commands and commit ## self._conf_JunOS.load(self.set_VR, format='set') self._conf_JunOS.load(self.set_int, format='set') self._conf_JunOS.commit() def ipV4(self,v4, interface, unit, mask): ip = v4 + "/" + mask ip_list = (interface, unit, ip) self.set_ip="set interfaces %s unit %s family inet address %s" % tuple(ip_list) #T.insert(END, '\n' + self.set_ip)##logbox self._conf_JunOS.load(self.set_ip, format='set') self._conf_JunOS.commit() def ipV6(self,v6, interface, unit, mask): ip = v6 + "/" + mask ip_list = (interface, unit, ip) self.set_ip="set interfaces %s unit %s family inet6 address %s" % tuple(ip_list) #T.insert(END, '\n' + self.set_ip)##logbox self._conf_JunOS.load(self.set_ip, format='set') self._conf_JunOS.commit() def OSPF(self, routerid, area, interface, unit): self.set_id="set routing-options router-id %s" % routerid ospflist = (area, interface, unit) self.set_ospf="set protocols ospf area %s interface %s.%s" % tuple(ospflist) self._conf_JunOS.load(self.set_id, format='set') self._conf_JunOS.load(self.set_ospf, format='set') self._conf_JunOS.commit() def ISIS(self,interface, unit): islist=(interface, unit) self.set_family="set interfaces %s unit %s family iso" % tuple(islist) self.set_protocol="set protocols isis interface %s.%s" % tuple(islist) self._conf_JunOS.load(self.set_family, format='set') self._conf_JunOS.load(self.set_protocol, format='set') self._conf_JunOS.commit() def ISO(self, iso): self.set_security="set security forwarding-options family iso mode packet-based" self.set_lo0="set interfaces lo0 unit 0 family iso address %s" % iso self.set_lo_int="set protocols isis interface lo0.0" # self._conf_JunOS.load(self.set_security, format='set') self._conf_JunOS.load(self.set_lo0, format='set') self._conf_JunOS.load(self.set_lo_int, format='set') self._conf_JunOS.commit() def OSPF3(self, routerid, area, interface, unit): self.set_id="set routing-options router-id %s" % routerid ospflist = (area, interface, unit) self.set_lo0="set protocols ospf3 area 0 interface lo0.0 passive" self.set_ospf3="set protocols ospf3 area %s interface %s.%s" % tuple(ospflist) self._conf_JunOS.load(self.set_id, format='set') self._conf_JunOS.load(self.set_lo0, format='set') self._conf_JunOS.load(self.set_ospf3, format='set') self._conf_JunOS.commit() def classes(self, name, action, detail): if len(name)!=0: class_info=[name,action,detail] self.class_set="set system login class %s %s %s" % tuple(class_info) self._conf_JunOS.load(self.class_set, format="set") self._conf_JunOS.commit() def users(self, user, class_Name, pass1): user_info=[user,class_Name,pass1] self.user_set="set system login user %s class % " \ "authentication plain-text-password-value %s" % tuple(user_info) self._conf_JunOS.load(self.user_set, format="set") self._conf_JunOS.commit() def firewall(self,filter, term, from1, from2, then): if len(from1)!=0: from_List=[filter,term,from1,from2] self.fw_From="set firewall filter %s term %s from %s %s" % tuple(from_List) self._conf_JunOS.load(self.fw_From, format="set") if len(then)!=0: then_List=[filter,term,then] self.fw_Then="set firewall filter %s term %s then %s" % tuple(then_List) self._conf_JunOS.load(self.fw_Then, format="set") self._conf_JunOS.commit() def show(self): return self.dev_Connect.cli("show configuration")
import sys import time import datetime from pprint import pprint from jnpr.junos import Device counter = 0 dev = Device(host='delhi-re0.ultralab.juniper.net', user='******', password='******') dev.open() while counter < 1000000: #Laser off pprint( dev.cli( "request pfe execute command \"test xfp 4 laser off\" target fpc0") ) print "Waiting 30 seconds before onlining \n" time.sleep(30) #Laser on pprint( dev.cli( "request pfe execute command \"test xfp 4 laser on\" target fpc0")) print "Waiting 30 seconds before deactivating \n" counter = counter + 1 print "This is round %s.\n" % (counter) dev.close()
from jnpr.junos import Device from pprint import pprint print("Open connection and print facts:") print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") dev = Device(host="10.254.0.35", user="******", passwd="lab123") dev.open() pprint(dev.facts) # -------------------------------------------------------------- print("CLI-cheat. Do not use for normal automation scripting:") print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") print(dev.cli("show interfaces ge* terse", warning=False)) # -------------------------------------------------------------- print("Using XML RPC to get info, then parse XML reply:") print("~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~") lxml = dev.rpc.get_arp_table_information() arp_table = lxml.findall('arp-table-entry') for entry in arp_table: print("MAC: %s, IP: %s" % (entry.findtext('mac-address').strip(), entry.findtext('ip-address').strip())) # -------------------------------------------------------------- print("Using tables and views to get route info:")
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()
class JunOSDriver(NetworkDriver): def __init__(self, hostname, username, password, timeout=60, optional_args=None): self.hostname = hostname self.username = username self.password = password self.timeout = timeout self.config_replace = False self.locked = False if optional_args is None: optional_args = {} self.port = optional_args.get('port', 22) self.config_lock = optional_args.get('config_lock', True) self.device = Device(hostname, user=username, password=password, port=self.port) def open(self): try: self.device.open() except ConnectTimeoutError as cte: raise ConnectionException(cte.message) self.device.timeout = self.timeout self.device.bind(cu=Config) if self.config_lock: self.lock() def close(self): if self.config_lock: self.unlock() self.device.close() def lock(self): if not self.locked: self.device.cu.lock() self.locked = True def unlock(self): if self.locked: self.device.cu.unlock() self.locked = False def _load_candidate(self, filename, config, overwrite): if filename is None: configuration = config else: with open(filename) as f: configuration = f.read() if not self.config_lock: # if not locked during connection time # will try to lock it if not already aquired self.lock() # and the device will be locked till first commit/rollback try: self.device.cu.load(configuration, format='text', overwrite=overwrite) except ConfigLoadError as e: if self.config_replace: raise ReplaceConfigException(e.message) else: raise MergeConfigException(e.message) def load_replace_candidate(self, filename=None, config=None): self.config_replace = True self._load_candidate(filename, config, True) def load_merge_candidate(self, filename=None, config=None): self.config_replace = False self._load_candidate(filename, config, False) def compare_config(self): diff = self.device.cu.diff() if diff is None: return '' else: return diff.strip() def commit_config(self): self.device.cu.commit() if not self.config_lock: self.unlock() def discard_config(self): self.device.cu.rollback(rb_id=0) if not self.config_lock: self.unlock() def rollback(self): self.device.cu.rollback(rb_id=1) self.commit_config() # perhaps both should be moved in napalm_base.helpers at some point @staticmethod def _find_txt(xml_tree, path, default = ''): try: return xml_tree.find(path).text.strip() except Exception: return default @staticmethod def _convert(to, who, default = u''): if who is None: return default try: return to(who) except: return default def get_facts(self): output = self.device.facts uptime = 0 if 'RE0' in output: uptime = output['RE0']['up_time'] interfaces = junos_views.junos_iface_table(self.device) interfaces.get() interface_list = interfaces.keys() return { 'vendor': u'Juniper', 'model': unicode(output['model']), 'serial_number': unicode(output['serialnumber']), 'os_version': unicode(output['version']), 'hostname': unicode(output['hostname']), 'fqdn': unicode(output['fqdn']), 'uptime': string_parsers.convert_uptime_string_seconds(uptime), 'interface_list': interface_list } def get_interfaces(self): # init result dict result = {} interfaces = junos_views.junos_iface_table(self.device) interfaces.get() # convert all the tuples to our pre-defined dict structure for iface in interfaces.keys(): result[iface] = { 'is_up': interfaces[iface]['is_up'], 'is_enabled': interfaces[iface]['is_enabled'], 'description': (interfaces[iface]['description'] or u''), 'last_flapped': float((interfaces[iface]['last_flapped'] or -1)), 'mac_address': unicode((interfaces[iface]['mac_address'] or '')), 'speed': -1 } # result[iface]['last_flapped'] = float(result[iface]['last_flapped']) match = re.search(r'(\d+)(\w*)', interfaces[iface]['speed'] or u'') if match is None: continue speed_value = self._convert(int, match.group(1), -1) if speed_value == -1: continue speed_unit = match.group(2) if speed_unit.lower() == 'gbps': speed_value *= 1000 result[iface]['speed'] = speed_value return result def get_interfaces_counters(self): query = junos_views.junos_iface_counter_table(self.device) query.get() interface_counters = dict() for interface, counters in query.items(): interface_counters[interface] = {k: v if v is not None else -1 for k, v in counters} return interface_counters def get_environment(self): environment = junos_views.junos_enviroment_table(self.device) routing_engine = junos_views.junos_routing_engine_table(self.device) temperature_thresholds = junos_views.junos_temperature_thresholds(self.device) environment.get() routing_engine.get() temperature_thresholds.get() environment_data = dict() for sensor_object, object_data in environment.items(): structured_object_data = {k: v for k, v in object_data} if structured_object_data['class'] == 'Power': # Create a dict for the 'power' key try: environment_data['power'][sensor_object] = dict() except KeyError: environment_data['power'] = dict() environment_data['power'][sensor_object] = dict() # Set these values to -1, because Junos does not provide them environment_data['power'][sensor_object]['capacity'] = -1.0 environment_data['power'][sensor_object]['output'] = -1.0 if structured_object_data['class'] == 'Fans': # Create a dict for the 'fans' key try: environment_data['fans'][sensor_object] = dict() except KeyError: environment_data['fans'] = dict() environment_data['fans'][sensor_object] = dict() if structured_object_data['status'] == 'OK' and structured_object_data['class'] == 'Power': # If status is Failed, Absent or Testing, set status to False. environment_data['power'][sensor_object]['status'] = True elif structured_object_data['status'] != 'OK' and structured_object_data['class'] == 'Power': environment_data['power'][sensor_object]['status'] = False elif structured_object_data['status'] == 'OK' and structured_object_data['class'] == 'Fans': # If status is Failed, Absent or Testing, set status to False. environment_data['fans'][sensor_object]['status'] = True elif structured_object_data['status'] != 'OK' and structured_object_data['class'] == 'Fans': environment_data['fans'][sensor_object]['status'] = False for temperature_object, temperature_data in temperature_thresholds.items(): structured_temperature_data = {k: v for k, v in temperature_data} if structured_object_data['class'] == 'Temp': # Create a dict for the 'temperature' key try: environment_data['temperature'][sensor_object] = dict() except KeyError: environment_data['temperature'] = dict() environment_data['temperature'][sensor_object] = dict() environment_data['temperature'][sensor_object]['temperature'] = float(structured_object_data['temperature']) # Set a default value (False) to the key is_critical and is_alert environment_data['temperature'][sensor_object]['is_alert'] = False environment_data['temperature'][sensor_object]['is_critical'] = False # Check if the working temperature is equal to or higher than alerting threshold if structured_temperature_data['red-alarm'] <= structured_object_data['temperature']: environment_data['temperature'][sensor_object]['is_critical'] = True environment_data['temperature'][sensor_object]['is_alert'] = True elif structured_temperature_data['yellow-alarm'] <= structured_object_data['temperature']: environment_data['temperature'][sensor_object]['is_alert'] = True for routing_engine_object, routing_engine_data in routing_engine.items(): structured_routing_engine_data = {k: v for k, v in routing_engine_data} # Create dicts for 'cpu' and 'memory'. try: environment_data['cpu'][routing_engine_object] = dict() environment_data['memory'] = dict() except KeyError: environment_data['cpu'] = dict() environment_data['cpu'][routing_engine_object] = dict() environment_data['memory'] = dict() # Calculate the CPU usage by using the CPU idle value. environment_data['cpu'][routing_engine_object]['%usage'] = 100.0 - structured_routing_engine_data['cpu-idle'] try: environment_data['memory']['available_ram'] = int(structured_routing_engine_data['memory-dram-size']) except ValueError: environment_data['memory']['available_ram'] = int(''.join(i for i in structured_routing_engine_data['memory-dram-size'] if i.isdigit())) # Junos gives us RAM in %, so calculation has to be made. # Sadly, bacause of this, results are not 100% accurate to the truth. environment_data['memory']['used_ram'] = (environment_data['memory']['available_ram'] / 100 * structured_routing_engine_data['memory-buffer-utilization']) return environment_data @staticmethod def _get_address_family(table): """ Function to derive address family from a junos table name :params table: The name of the routing table :returns: address family """ address_family_mapping = { 'inet': 'ipv4', 'inet6': 'ipv6' } family = table.split('.')[-2] return address_family_mapping[family] def _parse_route_stats(self, neighbor): data = {} if not neighbor['is_up']: pass elif isinstance(neighbor['tables'], list): for idx, table in enumerate(neighbor['tables']): family = self._get_address_family(table) data[family] = {} data[family]['received_prefixes'] = neighbor['received_prefixes'][idx] data[family]['accepted_prefixes'] = neighbor['accepted_prefixes'][idx] data[family]['sent_prefixes'] = neighbor['sent_prefixes'][idx] else: family = self._get_address_family(neighbor['tables']) data[family] = {} data[family]['received_prefixes'] = neighbor['received_prefixes'] data[family]['accepted_prefixes'] = neighbor['accepted_prefixes'] data[family]['sent_prefixes'] = neighbor['sent_prefixes'] return data @staticmethod def _parse_value(value): if isinstance(value, basestring): return unicode(value) elif value is None: return u'' else: return value def get_bgp_neighbors(self): instances = junos_views.junos_route_instance_table(self.device) uptime_table = junos_views.junos_bgp_uptime_table(self.device) bgp_neighbors = junos_views.junos_bgp_table(self.device) keys =['local_as', 'remote_as', 'is_up', 'is_enabled', 'description', 'remote_id'] bgp_neighbor_data = {} for instance, instance_data in instances.get().items(): if instance.startswith('__'): # junos internal instances continue instance_name = "global" if instance == 'master' else instance bgp_neighbor_data[instance_name] = {'peers': {}} for neighbor, data in bgp_neighbors.get(instance=instance).items(): neighbor_data = {k: v for k, v in data} peer_ip = neighbor.split('+')[0] if 'router_id' not in bgp_neighbor_data[instance_name]: # we only need to set this once bgp_neighbor_data[instance_name]['router_id'] = unicode(neighbor_data['local_id']) peer = {key:self._parse_value(value) for key, value in neighbor_data.iteritems() if key in keys} peer['address_family'] = self._parse_route_stats(neighbor_data) bgp_neighbor_data[instance_name]['peers'][peer_ip] = peer for neighbor, uptime in uptime_table.get(instance=instance).items(): bgp_neighbor_data[instance_name]['peers'][neighbor]['uptime'] = uptime[0][1] for key in bgp_neighbor_data.keys(): if not bgp_neighbor_data[key]['peers']: del bgp_neighbor_data[key] return bgp_neighbor_data def get_lldp_neighbors(self): lldp = junos_views.junos_lldp_table(self.device) lldp.get() result = lldp.items() neighbors = dict() for neigh in result: if neigh[0] not in neighbors.keys(): neighbors[neigh[0]] = list() neighbors[neigh[0]].append({x[0]: unicode(x[1]) for x in neigh[1]}) return neighbors def get_lldp_neighbors_detail(self, interface=''): lldp_neighbors = dict() lldp_table = junos_views.junos_lldp_neighbors_detail_table(self.device) lldp_table.get() interfaces = lldp_table.get().keys() old_junos = self._convert(int, self.device.facts.get('version', '0.0').split('.')[0], '0') < 13 lldp_table.GET_RPC = 'get-lldp-interface-neighbors' if old_junos: lldp_table.GET_RPC = 'get-lldp-interface-neighbors-information' for interface in interfaces: if old_junos: lldp_table.get(interface_name=interface) else: lldp_table.get(interface_device=interface) for item in lldp_table: if interface not in lldp_neighbors.keys(): lldp_neighbors[interface] = list() lldp_neighbors[interface].append({ 'parent_interface' : item.parent_interface, 'remote_port' : item.remote_port, 'remote_chassis_id' : item.remote_chassis_id, 'remote_port' : item.remote_port, 'remote_port_description' : item.remote_port_description, 'remote_system_name' : item.remote_system_name, 'remote_system_description' : item.remote_system_description, 'remote_system_capab' : item.remote_system_capab, 'remote_system_enable_capab': item.remote_system_enable_capab }) return lldp_neighbors def cli(self, commands = None): cli_output = dict() if type(commands) is not list: raise TypeError('Please enter a valid list of commands!') for command in commands: try: cli_output[unicode(command)] = unicode(self.device.cli(command)) except Exception as e: cli_output[unicode(command)] = 'Unable to execute command "{cmd}": {err}'.format( cmd = command, err = e ) raise CommandErrorException(str(cli_output)) return cli_output def get_bgp_config(self, group='', neighbor=''): def update_dict(d, u): # for deep dictionary update for k, v in u.iteritems(): if isinstance(d, collections.Mapping): if isinstance(v, collections.Mapping): r = update_dict(d.get(k, {}), v) d[k] = r else: d[k] = u[k] else: d = {k: u[k]} return d def build_prefix_limit(**args): """ This helper will transform the lements of a dictionary into nested dictionaries: Example: { 'inet_unicast_limit': 500, 'inet_unicast_teardown_threshold': 95, 'inet_unicast_teardown_timeout': 5 } becomes: { 'inet': { 'unicast': { 'limit': 500, 'teardown': { 'threshold': 95, 'timeout': 5 } } } } """ prefix_limit = dict() for key, value in args.iteritems(): key_levels = key.split('_') length = len(key_levels)-1 temp_dict = { key_levels[length]: value } for index in reversed(range(length)): level = key_levels[index] temp_dict = {level: temp_dict} update_dict(prefix_limit, temp_dict) return prefix_limit _COMMON_FIELDS_DATATYPE_ = { 'description': unicode, 'local_address': unicode, 'local_as': int, 'remote_as': int, 'import_policy': unicode, 'export_policy': unicode, 'inet_unicast_limit_prefix_limit': int, 'inet_unicast_teardown_threshold_prefix_limit': int, 'inet_unicast_teardown_timeout_prefix_limit': int, 'inet_unicast_novalidate_prefix_limit': int, 'inet_flow_limit_prefix_limit': int, 'inet_flow_teardown_threshold_prefix_limit': int, 'inet_flow_teardown_timeout_prefix_limit': int, 'inet_flow_novalidate_prefix_limit': unicode, 'inet6_unicast_limit_prefix_limit': int, 'inet6_unicast_teardown_threshold_prefix_limit': int, 'inet6_unicast_teardown_timeout_prefix_limit': int, 'inet6_unicast_novalidate_prefix_limit': int, 'inet6_flow_limit_prefix_limit': int, 'inet6_flow_teardown_threshold_prefix_limit': int, 'inet6_flow_teardown_timeout_prefix_limit': int, 'inet6_flow_novalidate_prefix_limit': unicode, } _PEER_FIELDS_DATATYPE_MAP_ = { 'group': unicode, 'authentication_key': unicode, 'route_reflector_client': bool, 'nhs': bool } _PEER_FIELDS_DATATYPE_MAP_.update( _COMMON_FIELDS_DATATYPE_ ) _GROUP_FIELDS_DATATYPE_MAP_ = { 'type': unicode, 'apply_groups': list, 'remove_private_as': bool, 'multipath': bool, 'multihop_ttl': int } _GROUP_FIELDS_DATATYPE_MAP_.update( _COMMON_FIELDS_DATATYPE_ ) _DATATYPE_DEFAULT_ = { unicode: u'', int: 0, bool: False, list: [] } bgp_config = dict() if group: bgp = junos_views.junos_bgp_config_group_table(self.device) bgp.get(group = group) else: bgp = junos_views.junos_bgp_config_table(self.device) bgp.get() neighbor = '' # if no group is set, no neighbor should be set either bgp_items = bgp.items() peers = junos_views.junos_bgp_config_peers_table(self.device) peers.get() # unfortunately cannot add filters for group name of neighbor address peers_items = peers.items() bgp_neighbors = dict() for bgp_group_neighbor in peers_items: bgp_peer_address = bgp_group_neighbor[0] if neighbor and bgp_peer_address != neighbor: continue # if filters applied, jump over all other neighbors bgp_group_details = bgp_group_neighbor[1] bgp_peer_details = { field: _DATATYPE_DEFAULT_.get(datatype) \ for field, datatype in _PEER_FIELDS_DATATYPE_MAP_.iteritems() \ if '_prefix_limit' not in field } for elem in bgp_group_details: if not('_prefix_limit' not in elem[0] and elem[1] is not None): continue datatype = _PEER_FIELDS_DATATYPE_MAP_.get(elem[0]) default = _DATATYPE_DEFAULT_.get(datatype) key = elem[0] value = elem[1] if key in ['export_policy', 'import_policy']: if isinstance(value, list): value = ' '.join(value) bgp_peer_details.update({ key: self._convert(datatype, value, default) }) prefix_limit_fields = dict() for elem in bgp_group_details: if '_prefix_limit' in elem[0] and elem[1] is not None: datatype = _PEER_FIELDS_DATATYPE_MAP_.get(elem[0]) default = _DATATYPE_DEFAULT_.get(datatype) prefix_limit_fields.update({ elem[0].replace('_prefix_limit', ''): self._convert(datatype, elem[1], default) }) bgp_peer_details['prefix_limit'] = build_prefix_limit(**prefix_limit_fields) # and all these things only because PyEZ cannto convert to a specifc datatype when retrieving config... group = bgp_peer_details.pop('group') if group not in bgp_neighbors.keys(): bgp_neighbors[group] = dict() bgp_neighbors[group][bgp_peer_address] = bgp_peer_details if neighbor and bgp_peer_address == neighbor: break # found the desired neighbor for bgp_group in bgp_items: bgp_group_name = bgp_group[0] bgp_group_details = bgp_group[1] bgp_config[bgp_group_name] = { field: _DATATYPE_DEFAULT_.get(datatype) \ for field, datatype in _GROUP_FIELDS_DATATYPE_MAP_.iteritems() \ if '_prefix_limit' not in field } for elem in bgp_group_details: if not('_prefix_limit' not in elem[0] and elem[1] is not None): continue datatype = _GROUP_FIELDS_DATATYPE_MAP_.get(elem[0]) default = _DATATYPE_DEFAULT_.get(datatype) key = elem[0] value = elem[1] if key in ['export_policy', 'import_policy']: if isinstance(value, list): value = ' '.join(value) bgp_config[bgp_group_name].update({ key: self._convert(datatype, value, default) }) prefix_limit_fields = dict() for elem in bgp_group_details: if '_prefix_limit' in elem[0] and elem[1] is not None: datatype = _GROUP_FIELDS_DATATYPE_MAP_.get(elem[0]) default = _DATATYPE_DEFAULT_.get(datatype) prefix_limit_fields.update({ elem[0].replace('_prefix_limit', ''): self._convert(datatype, elem[1], default) }) bgp_config[bgp_group_name]['prefix_limit'] = build_prefix_limit(**prefix_limit_fields) bgp_config[bgp_group_name]['neighbors'] = bgp_neighbors.get(bgp_group_name, {}) return bgp_config def get_bgp_neighbors_detail(self, neighbor_address = ''): bgp_neighbors = dict() bgp_neighbors_table = junos_views.junos_bgp_neighbors_table(self.device) bgp_neighbors_table.get( neighbor_address = neighbor_address ) bgp_neighbors_items = bgp_neighbors_table.items() default_neighbor_details = { 'up' : False, 'local_as' : 0, 'remote_as' : 0, 'local_address' : u'', 'routing_table' : u'', 'local_address_configured' : False, 'local_port' : 0, 'remote_address' : u'', 'remote_port' : 0, 'multihop' : False, 'multipath' : False, 'remove_private_as' : False, 'import_policy' : u'', 'export_policy' : u'', 'input_messages' : 0, 'output_messages' : 0, 'input_updates' : 0, 'output_updates' : 0, 'messages_queued_out' : 0, 'connection_state' : u'', 'previous_connection_state' : u'', 'last_event' : u'', 'suppress_4byte_as' : False, 'local_as_prepend' : False, 'holdtime' : 0, 'configured_holdtime' : 0, 'keepalive' : 0, 'configured_keepalive' : 0, 'active_prefix_count' : 0, 'received_prefix_count' : 0, 'accepted_prefix_count' : 0, 'suppressed_prefix_count' : 0, 'advertise_prefix_count' : 0, 'flap_count' : 0 } _OPTION_KEY_MAP_ = { 'RemovePrivateAS': 'remove_private_as', 'Multipath' : 'multipath', 'Multihop' : 'multihop', 'AddressFamily' : 'local_address_configured' # 'AuthKey' : 'authentication_key_set' # but other vendors do not specify if auth key is set # other options: # Preference, HoldTime, Ttl, LogUpDown, Refresh } for bgp_neighbor in bgp_neighbors_items: remote_as = int(bgp_neighbor[0]) if remote_as not in bgp_neighbors.keys(): bgp_neighbors[remote_as] = list() neighbor_details = default_neighbor_details.copy() neighbor_details.update( {elem[0]: elem[1] for elem in bgp_neighbor[1] if elem[1] is not None} ) options = neighbor_details.pop('options', '') if isinstance(options, str): options_list = options.split() for option in options_list: key = _OPTION_KEY_MAP_.get(option) if key is None: continue neighbor_details[key] = True four_byte_as = neighbor_details.pop('4byte_as', 0) local_address = neighbor_details.pop('local_address', '') local_details = local_address.split('+') neighbor_details['local_address'] = unicode(local_details[0]) if len(local_details) == 2: neighbor_details['local_port']= int(local_details[1]) else: neighbor_details['local_port']=179 neighbor_details['suppress_4byte_as'] = (remote_as != four_byte_as) peer_address = neighbor_details.pop('peer_address', '') remote_details = peer_address.split('+') neighbor_details['remote_address'] = unicode(remote_details[0]) if len(remote_details) == 2: neighbor_details['remote_port'] = int(remote_details[1]) else: neighbor_details['remote_port'] = 179 bgp_neighbors[remote_as].append(neighbor_details) return bgp_neighbors def get_arp_table(self): # could use ArpTable # from jnpr.junos.op.phyport import ArpTable # and simply use it # but # we need: # - filters # - group by VLAN ID # - hostname & TTE fields as well arp_table = list() arp_table_raw = junos_views.junos_arp_table(self.device) arp_table_raw.get() arp_table_items = arp_table_raw.items() for arp_table_entry in arp_table_items: arp_entry = { elem[0]: elem[1] for elem in arp_table_entry[1] } tte = arp_entry.pop('tte') arp_entry['age'] = tte # must compute age based on TTE arp_table.append(arp_entry) return arp_table def get_ntp_peers(self): ntp_table = junos_views.junos_ntp_peers_config_table(self.device) ntp_table.get() ntp_peers = ntp_table.items() if not ntp_peers: return {} return {unicode(peer[0]):{} for peer in ntp_peers} def get_ntp_stats(self): # NTP Peers does not have XML RPC defined # thus we need to retrieve raw text and parse... # :( ntp_stats = list() REGEX = ( '^\s?(\+|\*|x|-)?([a-zA-Z0-9\.+-:]+)' '\s+([a-zA-Z0-9\.]+)\s+([0-9]{1,2})' '\s+(-|u)\s+([0-9h-]+)\s+([0-9]+)' '\s+([0-9]+)\s+([0-9\.]+)\s+([0-9\.-]+)' '\s+([0-9\.]+)\s?$' ) ntp_assoc_output = self.device.cli('show ntp associations no-resolve') ntp_assoc_output_lines = ntp_assoc_output.splitlines() for ntp_assoc_output_line in ntp_assoc_output_lines[3:]: #except last line line_search = re.search(REGEX, ntp_assoc_output_line, re.I) if not line_search: continue # pattern not found line_groups = line_search.groups() try: ntp_stats.append({ 'remote' : unicode(line_groups[1]), 'synchronized' : (line_groups[0] == '*'), 'referenceid' : unicode(line_groups[2]), 'stratum' : int(line_groups[3]), 'type' : unicode(line_groups[4]), 'when' : unicode(line_groups[5]), 'hostpoll' : int(line_groups[6]), 'reachability' : int(line_groups[7]), 'delay' : float(line_groups[8]), 'offset' : float(line_groups[9]), 'jitter' : float(line_groups[10]) }) except Exception: continue # jump to next line return ntp_stats def get_interfaces_ip(self): interfaces_ip = dict() interface_table = junos_views.junos_ip_interfaces_table(self.device) interface_table.get() interface_table_items = interface_table.items() _FAMILY_VMAP_ = { 'inet' : u'ipv4', 'inet6' : u'ipv6' # can add more mappings } for interface_details in interface_table_items: try: ip_address = interface_details[0] address = unicode(ip_address.split('/')[0]) prefix = self._convert(int, ip_address.split('/')[-1], 0) interface = unicode(interface_details[1][0][1]) family_raw = interface_details[1][1][1] family = _FAMILY_VMAP_.get(family_raw) if not family: continue if interface not in interfaces_ip.keys(): interfaces_ip[interface] = dict() if family not in interfaces_ip[interface].keys(): interfaces_ip[interface][family] = dict() if address not in interfaces_ip[interface][family].keys(): interfaces_ip[interface][family][address] = dict() interfaces_ip[interface][family][address][u'prefix_length'] = prefix except Exception: continue return interfaces_ip def get_mac_address_table(self): mac_address_table = list() mac_table = junos_views.junos_mac_address_table(self.device) mac_table.get() mac_table_items = mac_table.items() default_values = { 'mac' : u'', 'interface' : u'', 'vlan' : 0, 'static' : False, 'active' : True, 'moves' : 0, 'last_move' : 0.0 } for mac_table_entry in mac_table_items: mac_entry = default_values.copy() mac_entry.update( {elem[0]: elem[1] for elem in mac_table_entry[1]} ) mac_address_table.append(mac_entry) return mac_address_table def get_route_to(self, destination = '', protocol = ''): routes = {} if not isinstance(destination, str): raise TypeError('Please specify a valid destination!') if not isinstance(protocol, str) or protocol.lower() not in ['static', 'bgp', 'isis']: raise TypeError("Protocol not supported: {protocol}.".format( protocol = protocol )) protocol = protocol.lower() _COMMON_PROTOCOL_FIELDS_ = [ 'destination', 'prefix_length', 'protocol', 'current_active', 'last_active', 'age', 'next_hop', 'outgoing_interface', 'selected_next_hop', 'preference', 'inactive_reason', 'routing_table' ] # identifies the list of fileds common for all protocols _BOOLEAN_FIELDS_ = [ 'current_active', 'selected_next_hop', 'last_active' ] # fields expected to have boolean values _PROTOCOL_SPECIFIC_FIELDS_ = { 'bgp': [ 'local_as', 'remote_as', 'as_path', 'communities', 'local_preference', 'preference2', 'remote_address', 'metric', 'metric2' ], 'isis': [ 'level', 'metric', 'local_as' ] } routes_table = junos_views.junos_protocol_route_table(self.device) try: routes_table.get( destination=destination, protocol=protocol ) except RpcTimeoutError: # on devices with milions of routes # in case the destination is too generic (e.g.: 10/8) # will take very very long to determine all routes and # moreover will return a huge list raise CommandTimeoutException('Too many routes returned! Please try with a longer prefix!') except Exception as e: raise CommandErrorException('Cannot retrieve routes! Reason: {err}'.format(err = e)) routes_items = routes_table.items() for route in routes_items: d = dict() next_hop = route[0] d = {elem[0]: elem[1] for elem in route[1]} destination = d.pop('destination', '') prefix_length = d.pop('prefix_length', 32) destination = '{d}/{p}'.format( d=destination, p=prefix_length ) d.update({key: False for key in _BOOLEAN_FIELDS_ if d.get(key) is None}) as_path = d.get('as_path') if as_path is not None: d['as_path'] = as_path.split(' I ')[0].replace('AS path:', '').replace('I', '').strip() # to be sure that contains only AS Numbers if d.get('inactive_reason') is None: d['inactive_reason'] = u'' communities = d.get('communities') if communities is not None and type(communities) is not list: d['communities'] = [communities] d['next_hop'] = unicode(next_hop) d_keys = d.keys() # fields that are not in _COMMON_PROTOCOL_FIELDS_ are supposed to be protocol specific all_protocol_attributes = {key: d.pop(key) for key in d_keys if key not in _COMMON_PROTOCOL_FIELDS_} protocol_attributes = { key: value for key, value in all_protocol_attributes.iteritems() \ if key in _PROTOCOL_SPECIFIC_FIELDS_.get(protocol) } d['protocol_attributes'] = protocol_attributes if destination not in routes.keys(): routes[destination] = list() routes[destination].append(d) return routes def get_snmp_information(self): snmp_information = dict() _AUTHORIZATION_MODE_MAP_ = { 'read-only': u'ro', 'read-write': u'rw' } snmp_config = junos_views.junos_snmp_config_table(self.device) snmp_config.get() snmp_items = snmp_config.items() if not snmp_items: return snmp_information communities = list() for snmp_config_out in snmp_items: community_name = snmp_config_out[0] community_details = snmp_config_out[1] communities.append({ c[0]: c[1] for c in community_details }) snmp_information = { 'contact': self._convert(unicode, communities[0].get('contact')), 'location': self._convert(unicode, communities[0].get('location')), 'chassis_id': self._convert(unicode, communities[0].get('chassis')), 'community': {} } for snmp_entry in communities: name = self._convert(unicode, snmp_entry.get('name')) authorization = self._convert(unicode, snmp_entry.get('authorization')) snmp_information['community'][name] = { 'mode': _AUTHORIZATION_MODE_MAP_.get(authorization, u''), 'acl': u'' } return snmp_information def get_probes_config(self): probes = dict() probes_table = junos_views.junos_rpm_probes_config_table(self.device) probes_table.get() probes_table_items = probes_table.items() for probe_test in probes_table_items: test_name = unicode(probe_test[0]) test_details = { p[0]: p[1] for p in probe_test[1] } probe_name = self._convert(unicode, test_details.pop('probe_name')) target = self._convert(unicode, test_details.pop('target', '')) test_interval = self._convert(int, test_details.pop('test_interval', '0')) probe_count = self._convert(int, test_details.pop('probe_count', '0')) probe_type = self._convert(unicode, test_details.pop('probe_type', '')) source = self._convert(unicode, test_details.pop('source_address', '')) if probe_name not in probes.keys(): probes[probe_name] = dict() probes[probe_name][test_name] = { 'probe_type' : probe_type, 'target' : target, 'source' : source, 'probe_count' : probe_count, 'test_interval' : test_interval } return probes def get_probes_results(self): probes_results = dict() probes_results_table = junos_views.junos_rpm_probes_results_table(self.device) probes_results_table.get() probes_results_items = probes_results_table.items() for probe_result in probes_results_items: probe_name = unicode(probe_result[0]) test_results = { p[0]: p[1] for p in probe_result[1] } for test_param_name, test_param_value in test_results.iteritems(): if isinstance(test_param_value, float): test_results[test_param_name] = test_param_value * 1e-3 # convert from useconds to mseconds test_name = test_results.pop('test_name', '') source = test_results.get('source', u'') if source is None: test_results['source'] = u'' if probe_name not in probes_results.keys(): probes_results[probe_name] = dict() probes_results[probe_name][test_name] = test_results return probes_results def traceroute(self, destination, source='', ttl=0, timeout=0): traceroute_result = dict() # calling form RPC does not work properly :( # but defined junos_route_instance_table just in case source_str = '' maxttl_str = '' wait_str = '' if source: source_str = 'source {source}'.format(source=source) if ttl: maxttl_str = 'ttl {ttl}'.format(ttl=ttl) if timeout: wait_str = 'wait {timeout}'.format(timeout=timeout) traceroute_command = 'traceroute {destination} {source} {maxttl} {wait}'.format( destination=destination, source=source_str, maxttl=maxttl_str, wait=wait_str ) traceroute_rpc = E('command', traceroute_command) rpc_reply = self.device._conn.rpc(traceroute_rpc)._NCElement__doc # make direct RPC call via NETCONF traceroute_results = rpc_reply.find('.//traceroute-results') traceroute_success = traceroute_results.find('traceroute-success') traceroute_failure = self._find_txt(traceroute_results, 'traceroute-failure', '') error_message = self._find_txt(traceroute_results, 'rpc-error/error-message', '') error = '' if traceroute_failure and error_message: return {'error': '{}: {}'.format(traceroute_failure, error_message)} traceroute_result['success'] = dict() for hop in traceroute_results.findall('hop'): ttl_value = self._convert(int, self._find_txt(hop, 'ttl-value'), 1) if ttl_value not in traceroute_result['success']: traceroute_result['success'][ttl_value] = {'probes': {}} for probe in hop.findall('probe-result'): probe_index = self._convert(int, self._find_txt(probe, 'probe-index'), 0) ip_address = unicode(self._find_txt(probe, 'ip-address', u'*')) host_name = unicode(self._find_txt(probe, 'host-name', u'*')) rtt = self._convert(float, self._find_txt(probe, 'rtt'), 0) * 1e-3 # ms traceroute_result['success'][ttl_value]['probes'][probe_index] = { 'ip_address': ip_address, 'host_name': host_name, 'rtt': rtt } return traceroute_result def get_users(self): users = dict() _JUNOS_CLASS_CISCO_PRIVILEGE_LEVEL_MAP = { 'super-user': 15, 'superuser': 15, 'operator': 5, 'read-only': 1, 'unauthorized': 0 } _DEFAULT_USER_DETAILS = { 'level': 0, 'password': '', 'sshkeys': [] } users_table = junos_views.junos_users_table(self.device) users_table.get() users_items = users_table.items() for user_entry in users_items: username = user_entry[0] user_details = _DEFAULT_USER_DETAILS.copy() user_details.update({ d[0]: d[1] for d in user_entry[1] if d[1] }) user_class = user_details.pop('class', '') level = _JUNOS_CLASS_CISCO_PRIVILEGE_LEVEL_MAP.get(user_class, 0) user_details.update({ 'level': level }) user_details['sshkeys'] = [ user_details.pop(key) for key in ['ssh_rsa', 'ssh_dsa', 'ssh_ecdsa'] if user_details.get(key, '') ] users[username] = user_details return users
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 operation_command(device,command): dev = Device(host=device, user=username, password=password) dev.open() output = dev.cli(command) dev.close return output
class TestCore(unittest.TestCase): @classmethod def setUpClass(self): from jnpr.junos import Device self.dev = Device(host="xxxx", user="******", password="******") self.dev.open() @classmethod def tearDownClass(self): self.dev.close() def test_device_open(self): self.assertEqual(self.dev.connected, True) def test_device_facts(self): assert self.dev.facts["hostname"] == "highlife" def test_device_get_timeout(self): assert self.dev.timeout == 30 def test_device_set_timeout(self): self.dev.timeout = 35 assert self.dev.timeout == 35 def test_device_cli(self): self.assertTrue("qfx5100" in self.dev.cli("show version")) def test_device_rpc(self): res = self.dev.rpc.get_route_information(destination="10.48.21.71") self.assertEqual(res.tag, "route-information") def test_device_rpc_format_text(self): res = self.dev.rpc.get_interface_information({"format": "text"}) self.assertEqual(res.tag, "output") def test_device_rpc_timeout(self): with self.assertRaises(RpcTimeoutError): self.dev.rpc.get_route_information(dev_timeout=0.01) def test_device_rpc_normalize_true(self): rsp = self.dev.rpc.get_interface_information(interface_name="ge-0/0/1", normalize=True) self.assertEqual( rsp.xpath("physical-interface/name")[0].text, "ge-0/0/1") 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()
class TestDevice(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() @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_new_console_return(self): dev = Device(host='1.1.1.1', user='******', password='******', port=23, gather_facts=False) self.assertTrue(isinstance(dev, Console)) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectAuthError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.AuthenticationError self.assertRaises(EzErrors.ConnectAuthError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectRefusedError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError self.assertRaises(EzErrors.ConnectRefusedError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') @patch('jnpr.junos.device.datetime') def test_device_ConnectTimeoutError(self, mock_datetime, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError( "Could not open socket to 1.1.1.1:830") from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectTimeoutError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') @patch('jnpr.junos.device.datetime') def test_device_diff_err_message(self, mock_datetime, mock_manager): NcErrors.SSHError.message = 'why are you trying :)' mock_manager.connect.side_effect = NcErrors.SSHError from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectUnknownHostError(self, mock_manager): import socket mock_manager.connect.side_effect = socket.gaierror self.assertRaises(EzErrors.ConnectUnknownHostError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_other_error(self, mock_manager): mock_manager.connect.side_effect = TypeError self.assertRaises(EzErrors.ConnectError, self.dev.open) def test_device_probe_error(self): mock_probe = MagicMock() mock_probe.return_value = None self.dev.probe = mock_probe def fn(): self.dev.open(auto_probe=1) self.assertRaises(EzErrors.ProbeError, fn) def test_device_property_logfile_isinstance(self): mock = MagicMock() with patch(builtin_string + '.open', mock): if sys.version > '3': builtin_file = 'io.TextIOWrapper' else: builtin_file = builtin_string + '.file' with patch(builtin_file, MagicMock): handle = open('filename', 'r') self.dev.logfile = handle self.assertEqual(self.dev.logfile, handle) def test_device_host_mand_param(self): self.assertRaises(ValueError, Device, user='******', password='******', gather_facts=False) def test_device_property_logfile_close(self): self.dev._logfile = MagicMock() self.dev._logfile.close.return_value = 0 self.dev.logfile = None self.assertFalse(self.dev._logfile) def test_device_property_logfile_exception(self): try: self.dev.logfile = True except Exception as ex: self.assertEqual(type(ex), ValueError) def test_device_master_is_master(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['re1', 'master', 'node', 'fwdd', 'member', 'pfem'] self.assertEqual(localdev.master, True) def test_device_master_is_backup(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['re0', 'backup'] self.assertEqual(localdev.master, False) def test_device_master_is_re0_only(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['2RE'] = False localdev.facts._cache['RE_hw_mi'] = False localdev.facts._cache['current_re'] = ['re0'] self.assertEqual(localdev.master, True) def test_device_master_is_multi_chassis_non_master1(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['2RE'] = True localdev.facts._cache['current_re'] = ['lcc1-re1', 'member1-re1', 'lcc1-backup', 'member1-backup'] self.assertEqual(localdev.master, False) def test_device_master_is_multi_chassis_non_master2(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['2RE'] = True localdev.facts._cache['current_re'] = ['lcc1-re0', 'member1-re0', 'lcc1-master', 'member1-master', 'member1'] self.assertEqual(localdev.master, False) def test_device_master_is_none1(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = None self.assertEqual(localdev.master, None) def test_device_master_is_none2(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['2RE'] = True localdev.facts._cache['current_re'] = ['foo', 'bar'] self.assertEqual(localdev.master, None) @patch('jnpr.junos.device.warnings') def test_device_master_is_old_facts(self, mock_warn): localdev = Device(host='1.1.1.1', user='******', password='******', fact_style='old', gather_facts=False) mock_warn.assert_has_calls([call.warn('fact-style old will be removed ' 'in a future release.', RuntimeWarning)]) self.assertEqual(localdev.master, None) def test_device_master_setter(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) with self.assertRaises(RuntimeError): localdev.master = 'foo' def test_device_re_name_is_re0(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['re0', 'backup'] localdev.facts._cache['hostname_info'] = {'re0': 'tapir', 're1': 'tapir1'} self.assertEqual(localdev.re_name, 're0') def test_device_re_name_is_lcc_re1(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['lcc1-re1', 'member1-re1', 'lcc1-backup', 'member1-backup'] localdev.facts._cache['hostname_info'] = {'re0': 'mj1'} self.assertEqual(localdev.re_name, 'lcc1-re1') def test_device_re_name_is_re0_only(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['foo'] localdev.facts._cache['hostname_info'] = {'re0': 'mj1'} self.assertEqual(localdev.re_name, 're0') def test_device_re_name_is_none1(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = None self.assertEqual(localdev.re_name, None) def test_device_re_name_is_none2(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['re1', 'master', 'node', 'fwdd', 'member', 'pfem'] localdev.facts._cache['hostname_info'] = None self.assertEqual(localdev.re_name, None) @patch('jnpr.junos.device.warnings') def test_device_re_name_is_old_facts(self, mock_warn): localdev = Device(host='1.1.1.1', user='******', password='******', fact_style='old', gather_facts=False) mock_warn.assert_has_calls([call.warn('fact-style old will be removed ' 'in a future release.', RuntimeWarning)]) self.assertEqual(localdev.re_name, None) def test_device_re_name_setter(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) with self.assertRaises(RuntimeError): localdev.re_name = 'foo' def test_device_repr(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.assertEqual(repr(localdev), 'Device(1.1.1.1)') def test_device_local(self): Device.ON_JUNOS = True localdev = Device() self.assertEqual(localdev._hostname, 'localhost') @patch('jnpr.junos.device.os') @patch(builtin_string + '.open') @patch('paramiko.config.SSHConfig.lookup') def test_device__sshconf_lkup(self, mock_paramiko, open_mock, os_mock): os_mock.path.exists.return_value = True self.dev._sshconf_lkup() mock_paramiko.assert_called_once_with('1.1.1.1') @patch('jnpr.junos.device.os') @patch(builtin_string + '.open') @patch('paramiko.config.SSHConfig.lookup') def test_device__sshconf_lkup_def(self, mock_paramiko, open_mock, os_mock): os_mock.path.exists.return_value = True self.dev._ssh_config = '/home/rsherman/.ssh/config' self.dev._sshconf_lkup() mock_paramiko.assert_called_once_with('1.1.1.1') @patch('os.getenv') def test_device__sshconf_lkup_path_not_exists(self, mock_env): mock_env.return_value = '/home/test' self.assertEqual(self.dev._sshconf_lkup(), None) @patch('os.getenv') def test_device__sshconf_lkup_home_not_defined(self, mock_env): mock_env.return_value = None self.assertEqual(self.dev._sshconf_lkup(), None) mock_env.assert_called_with('HOME') @patch('ncclient.manager.connect') @patch('jnpr.junos.Device.execute') def test_device_open(self, mock_connect, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_cat.return_value = """ domain jls.net """ mock_connect.side_effect = self._mock_manager mock_execute.side_effect = self._mock_manager self.dev2 = Device( host='2.2.2.2', user='******', password='******') self.dev2.open() self.assertEqual(self.dev2.connected, True) @patch('jnpr.junos.Device.execute') def test_device_facts(self, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.return_value = """ domain jls.net """ self.dev.facts_refresh() self.dev.facts._cache['current_re'] = ['re0'] assert self.dev.facts['version'] == facts['version'] @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.factcache.warnings') def test_device_facts_error(self, mock_warnings, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.side_effect = IOError('File cant be handled') self.dev.facts_refresh(warnings_on_failure=True) self.assertTrue(mock_warnings.warn.called) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.device.warnings') def test_device_facts_error_exception_on_error(self, mock_warnings, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.side_effect = IOError('File cant be handled') self.assertRaises(IOError, self.dev.facts_refresh, exception_on_failure=True) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.device.warnings') def test_device_old_style_facts_error_exception_on_error(self, mock_warnings, mock_execute): self.dev._fact_style = 'old' with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.side_effect = IOError('File cant be handled') self.assertRaises(IOError, self.dev.facts_refresh, exception_on_failure=True) def test_device_facts_refresh_unknown_fact_style(self): self.dev._fact_style = 'bad' with self.assertRaises(RuntimeError): self.dev.facts_refresh() def test_device_facts_refresh_old_fact_style_with_keys(self): self.dev._fact_style = 'old' with self.assertRaises(RuntimeError): self.dev.facts_refresh(keys='domain') def test_device_hostname(self): self.assertEqual(self.dev.hostname, '1.1.1.1') def test_device_user(self): self.assertEqual(self.dev.user, 'test') def test_device_get_password(self): self.assertEqual(self.dev.password, None) def test_device_set_password(self): self.dev.password = '******' self.assertEqual(self.dev._auth_password, 'secret') def test_device_get_timeout(self): self.assertEqual(self.dev.timeout, 30) def test_device_set_timeout(self): self.dev.timeout = 10 self.assertEqual(self.dev.timeout, 10) def test_device_set_timeout_string(self): self.dev.timeout = '10' self.assertEqual(self.dev.timeout, 10) def test_device_set_timeout_invalid_string_value(self): with self.assertRaises(RuntimeError): self.dev.timeout = 'foo' def test_device_set_timeout_invalid_type(self): with self.assertRaises(RuntimeError): self.dev.timeout = [1,2,3,4] def test_device_manages(self): self.assertEqual(self.dev.manages, [], 'By default manages will be empty list') @patch('ncclient.manager.connect') @patch('jnpr.junos.Device.execute') def test_device_open_normalize(self, mock_connect, mock_execute): mock_connect.side_effect = self._mock_manager self.dev2 = Device(host='2.2.2.2', user='******', password='******') self.dev2.open(gather_facts=False, normalize=True) self.assertEqual(self.dev2.transform, self.dev2._norm_transform) def test_device_set_facts_exception(self): try: self.dev.facts = 'test' except RuntimeError as ex: self.assertEqual(RuntimeError, type(ex)) def test_device_ofacts_exception(self): with self.assertRaises(RuntimeError): ofacts = self.dev.ofacts def test_device_set_ofacts_exception(self): with self.assertRaises(RuntimeError): self.dev.ofacts = False @patch('jnpr.junos.Device.execute') def test_device_cli(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli('show cli directory', warning=False).tag, 'cli') @patch('jnpr.junos.device.json.loads') def test_device_rpc_json_ex(self, mock_json_loads): self.dev.facts = facts self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) ex = ValueError('Extra data ') ex.message = 'Extra data ' # for py3 as we dont have message thr mock_json_loads.side_effect = [ ex, self._mock_manager(etree.fromstring( '<get-route-information format="json"/>'))] self.dev.rpc.get_route_information({'format': 'json'}) self.assertEqual(mock_json_loads.call_count, 2) @patch('jnpr.junos.Device.execute') def test_device_cli_to_rpc_string(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli_to_rpc_string('show system uptime') self.assertEqual("rpc.get_system_uptime_information()", data) @patch('jnpr.junos.Device.execute') def test_device_cli_to_rpc_string_strip_pipes(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli_to_rpc_string( 'show system uptime | match foo | count') self.assertEqual("rpc.get_system_uptime_information()", data) @patch('jnpr.junos.Device.execute') def test_device_cli_to_rpc_string_complex(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli_to_rpc_string( 'show interfaces ge-0/0/0.0 routing-instance all media') self.assertEqual("rpc.get_interface_information(" "routing_instance='all', media=True, " "interface_name='ge-0/0/0.0')", data) @patch('jnpr.junos.Device.execute') def test_device_cli_to_rpc_string_invalid(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli_to_rpc_string('foo') self.assertEqual(None, data) @patch('jnpr.junos.Device.execute') def test_device_cli_format_json(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli('show interface terse', warning=False, format='json') self.assertEqual(type(data), dict) self.assertEqual(data['interface-information'][0] ['physical-interface'][0]['oper-status'][0]['data'], 'up') @patch('jnpr.junos.Device.execute') def test_device_cli_conf_info(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('ge-0/0/0' in self.dev.cli('show configuration', warning=False)) @patch('jnpr.junos.Device.execute') def test_device_cli_output(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Alarm' in self.dev.cli('show system alarms', warning=False)) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.device.warnings') def test_device_cli_output_warning(self, mock_warnings, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli('show interfaces ge-0/0/0.0 routing-instance ' 'all media', format='xml') ip = data.findtext('logical-interface[name="ge-0/0/0.0"]/' 'address-family[address-family-name="inet"]/' 'interface-address/ifa-local') self.assertTrue('192.168.100.1' in ip) self.assertTrue(mock_warnings.warn.called) rpc_string = "rpc.get_interface_information(routing_instance='all', "\ "media=True, interface_name='ge-0/0/0.0')" self.assertIn(rpc_string, mock_warnings.warn.call_args[0][0]) def test_device_cli_blank_output(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual('', self.dev.cli('show configuration interfaces', warning=False)) def test_device_cli_rpc_reply_with_message(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual( '\nprotocol: operation-failed\nerror: device asdf not found\n', self.dev.cli('show interfaces terse asdf', warning=False)) @patch('jnpr.junos.Device.execute') def test_device_cli_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli('show system uptime| display xml rpc', warning=False) .tag, 'get-system-uptime-information') def test_device_cli_exception(self): self.dev.rpc.cli = MagicMock(side_effect=AttributeError) val = self.dev.cli('show version') self.assertEqual(val, 'invalid command: show version') @patch('jnpr.junos.Device.execute') def test_device_cli_rpc_exception(self, mock_execute): mock_execute.side_effect = self._mock_manager val = self.dev.cli('foo') self.assertEqual(val, 'invalid command: foo: RpcError') @patch('jnpr.junos.Device.execute') def test_device_display_xml_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual( self.dev.display_xml_rpc('show system uptime').tag, 'get-system-uptime-information') @patch('jnpr.junos.Device.execute') def test_device_display_xml_rpc_text(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertIn( '<get-system-uptime-information>', self.dev.display_xml_rpc( 'show system uptime', format='text')) @patch('jnpr.junos.Device.execute') def test_device_display_xml_exception(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual( self.dev.display_xml_rpc('show foo'), 'invalid command: show foo| display xml rpc') def test_device_execute(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute('<get-system-core-dumps/>').tag, 'directory-list') def test_device_execute_topy(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute('<get-system-core-dumps/>', to_py=self._do_nothing), 'Nothing') # This test is for the commented out rpc-error code # def test_device_execute_exception(self): # self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) # self.assertRaises(RpcError, self.dev.execute, # '<load-configuration-error/>') @patch('jnpr.junos.device.warnings') def test_device_execute_unknown_exception(self, mock_warnings): class MyException(Exception): pass self.dev._conn.rpc = MagicMock(side_effect=MyException) self.assertRaises(MyException, self.dev.execute, '<get-software-information/>') def test_device_execute_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises(RpcError, self.dev.rpc.get_rpc_error) def test_device_execute_permission_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises( EzErrors.PermissionError, self.dev.rpc.get_permission_denied) def test_device_execute_index_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertTrue(self.dev.rpc.get_index_error()) def test_device_execute_ValueError(self): self.assertRaises(ValueError, self.dev.execute, None) def test_device_execute_unopened(self): self.dev.connected = False self.assertRaises(EzErrors.ConnectClosedError, self.dev.execute, None) def test_device_execute_timeout(self): self.dev._conn.rpc = MagicMock(side_effect=TimeoutExpiredError) self.assertRaises( EzErrors.RpcTimeoutError, self.dev.rpc.get_rpc_timeout) def test_device_execute_closed(self): self.dev._conn.rpc = MagicMock(side_effect=NcErrors.TransportError) self.assertRaises( EzErrors.ConnectClosedError, self.dev.rpc.get_rpc_close) self.assertFalse(self.dev.connected) def test_device_rpcmeta(self): self.assertEqual(self.dev.rpc.get_software_information.__doc__, 'get-software-information') def test_device_probe_timeout_zero(self): with patch('jnpr.junos.device.socket'): self.assertFalse(self.dev.probe(0)) def test_device_probe_timeout_gt_zero(self): with patch('jnpr.junos.device.socket'): self.assertTrue(self.dev.probe(1), 'probe fn is not working for' ' timeout greater than zero') def test_device_probe_timeout_exception(self): with patch('jnpr.junos.device.socket') as mock_socket: with patch('jnpr.junos.device.time.sleep') as mock_time: mock_socket.socket.return_value.close.side_effect \ = RuntimeError mock_time.return_value = None self.assertFalse(self.dev.probe(.01)) def test_device_bind_varg(self): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic_mock' self.dev.bind(mock) self.assertEqual(self.dev.magic_mock.__name__, 'magic_mock') def test_device_bind_kvarg(self): self.dev.bind() mock = MagicMock() mock.return_value = 'Test' self.dev.bind(kw=mock) self.assertEqual(self.dev.kw, 'Test') def test_device_bind_varg_exception(self): def varg(): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic mock' # for *args self.dev.bind(mock) self.dev.bind(mock) self.assertRaises(ValueError, varg) def test_device_bind_kvarg_exception(self): def kve(): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic mock' # for **kwargs self.dev.bind(kw=mock) self.dev.bind(kw=mock) self.assertRaises(ValueError, kve) def test_device_template(self): # Try to load the template relative to module base try: template = self.dev.Template( 'tests/unit/templates/config-example.xml') except: # Try to load the template relative to test base try: template = self.dev.Template('templates/config-example.xml') except: raise self.assertEqual(template.render({'host_name': '1', 'domain_name': '2'}), 'system {\n host-name 1;\n domain-name 2;\n}') def test_device_close(self): def close_conn(): self.dev.connected = False self.dev.close = MagicMock(name='close') self.dev.close.side_effect = close_conn self.dev.close() self.assertEqual(self.dev.connected, False) @patch('ncclient.manager.connect') def test_device_context_manager(self, mock_connect): mock_connect.side_effect = self._mock_manager try: with Device(host='3.3.3.3', user='******', password='******', gather_facts=False) as dev: self.assertTrue(dev.connected) dev._conn = MagicMock(name='_conn') dev._conn.connected = True def close_conn(): dev.connected = False dev.close = MagicMock(name='close') dev.close.side_effect = close_conn raise RpcError except Exception as e: self.assertIsInstance(e, RpcError) self.assertFalse(dev.connected) def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) with open(fpath) as fp: foo = fp.read() if fname == 'get-rpc-error.xml': # Raise ncclient exception for error raise RPCError(etree.XML(foo)) elif fname == 'get-permission-denied.xml': # Raise ncclient exception for error raise RPCError(etree.XML(foo)) elif (fname == 'get-index-error.xml' or fname == 'get-system-core-dumps.xml' or fname == 'load-configuration-error.xml' or fname == 'show-configuration-interfaces.xml' or fname == 'show-interfaces-terse-asdf.xml'): rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply()) elif (fname == 'show-configuration.xml' or fname == 'show-system-alarms.xml'): rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply())._NCElement__doc elif fname == 'show-interface-terse.json': rpc_reply = json.loads(foo) elif fname == 'get-route-information.json': rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply()) else: rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply())._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs and 'normalize' not in kwargs: device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].tag == 'command': if args[0].text == 'show cli directory': return self._read_file('show-cli-directory.xml') if args[0].text == 'show interface terse': return self._read_file('show-interface-terse.json') elif args[0].text == 'show configuration': return self._read_file('show-configuration.xml') elif args[0].text == 'show system alarms': return self._read_file('show-system-alarms.xml') elif args[0].text == 'show system uptime| display xml rpc': return self._read_file('show-system-uptime-rpc.xml') elif args[0].text == 'show configuration interfaces': return self._read_file('show-configuration-interfaces.xml') elif args[0].text == 'show interfaces terse asdf': return self._read_file('show-interfaces-terse-asdf.xml') elif args[0].text == 'show interfaces ge-0/0/0.0 ' \ 'routing-instance all media': return self._read_file( 'show-interfaces-routing-instance-media.xml') elif args[0].text == 'show interfaces ge-0/0/0.0 ' \ 'routing-instance all media| display ' \ 'xml rpc': return self._read_file( 'show-interfaces-routing-instance-media-rpc.xml') else: raise RpcError else: if args[0].attrib.get('format') == 'json': return self._read_file(args[0].tag + '.json') return self._read_file(args[0].tag + '.xml') def _do_nothing(self, *args, **kwargs): return 'Nothing'
class NetconfAction(ActionBase): """ Uses NetConf to execute the given template Can execute template as an op command or apply the template as a configuration template """ dev = None request_type = "apply_template" result_msg = "" def set_endpoint(self, endpoint): try: # create the required iterator from the endpoint_list self.dev = Device(user=endpoint["username"], password=endpoint["password"], host=endpoint["ip"], port=22) self.dev.open(gather_facts=False) except Exception as err: print "Could not open device %s!" % endpoint["ip"] self.result_msg = str(err) self.dev = None return def execute_template(self, template): """ switches based on request_type chosen from template configuration :param template: :return: String results from the endpoint netconf subsystem """ if self.dev is None: return self.result_msg if self.request_type == "apply_template": return self.apply_template(template) elif self.request_type == "execute_cheat_command": return self.execute_cheat_command(template) elif self.request_type == "assert_set_configuration": return self.assert_set_configuration(template) elif self.request_type == "assert_xpath_configuration": return self.assert_xpath_configuration(template) else: return self.execute_op_command(template) def execute_op_command(self, template): # Django is so very helpful in escaping EVERYTHING, undo the madness before passing to pyez s = self.unescape(template) try: results = self.dev.execute(s) except RpcError as e: print e return "Error executing command: %s" % str(e) print etree.tostring(results, pretty_print=True) return etree.tostring(results, pretty_print=True) def execute_cheat_command(self, template): print "Executing cheat command" results = self.dev.cli(template) return self.format_results(results) def assert_set_configuration(self, pattern): print "Checking set command regex" config = self.dev.cli('show configuration | display set') print config config_pattern = re.compile(pattern) results = "" for line in config.split('\n'): if config_pattern.match(line): results += line + "\n" if results != "": return results def assert_xpath_configuration(self, xpath): print "Searching xpath" configuration_xml = self.dev.execute("<get-configuration></get-configuration>") print configuration_xml if configuration_xml.find(xpath): return "Configuration element: %s is present" % xpath return "not found" def apply_template(self, template): print self.dev conf_string = template.strip() print conf_string if re.search(r"^<", conf_string): print "Found a encoded string" conf_string = self.unescape(conf_string) print conf_string # try to determine the format of our config_string config_format = "set" if re.search(r"^\s*<.*>$", conf_string, re.MULTILINE): print "found xml style config" config_format = "xml" elif re.search(r"^\s*(set|delete|replace|rename)\s", conf_string): print "found set style config" config_format = "set" elif re.search(r"^[a-z:]*\s*\w+\s+{", conf_string, re.I) and re.search(r".*}\s*$", conf_string): print "found a text style config" config_format = "text" print "using format: " + config_format cu = Config(self.dev) try: cu.lock() except LockError as le: print "Could not lock database!" print str(le) self.dev.close() return "Failed to lock configuration database! %s" % str(le) try: print "loading config" cu.load(conf_string, format=config_format) except Exception as e: print "Could not load configuration" print str(e) try: cu.unlock() except UnlockError as ue: print str(ue) self.dev.close() return "Failed, could not load the configuration template. %s" % str(e) diff = cu.diff() print diff if diff is not None: try: cu.commit_check() print "Committing config!" cu.commit(comment="Commit via a_frame") except CommitError as ce: print "Could not load config! %s" % str(ce) cu.rollback() try: print "Unlocking database!" cu.unlock() except UnlockError as ue: print "Could not unlock database" print str(ue) print repr(ce) self.dev.close() return "Failed, commit check failed. %s" % str(ce) else: # nothing to commit print "Nothing to commit - no diff found" cu.unlock() self.dev.close() return "Nothing to commit!" try: print "Unlocking database!" cu.unlock() except UnlockError as ue: print "Could not unlock database" print str(ue) self.dev.close() return "Committed, but could not unlock db" print "Closing device handle" self.dev.close() return "Completed with diff: %s" % diff @staticmethod def unescape(s): s = s.replace("<", "<") s = s.replace(">", ">") s = s.replace("&", "&") return s @staticmethod def format_results(results): """ detects string format (xml || json) and formats appropriately :param results: string from urlopen :return: formatted string output """ print results try: if type(results) is str: results = etree.fromstring(results) print "found valid xml, formatting and returning" # use pretty_print if we have an xml document returned return etree.tostring(results, pretty_print=True) except XMLSyntaxError: pass except ValueError: pass except TypeError: pass # is the result valid json? try: json_string = json.loads(results) print "Found JSON results" return json.dumps(json_string, indent=4) except ValueError: pass except TypeError: pass print "no special formatting, returning" return results
def __init__(self, **kvargs): """ NoobDevice object constructor. :param str host: **REQUIRED** host-name or ipaddress of target device :param str user: *OPTIONAL* login user-name, uses root if not provided :param str passwd: *OPTIONAL* in console connection for device at zeroized state password is not required :param int port: *OPTIONAL* port, default is telnet port `23` :param int baud: *OPTIONAL* baud, default baud rate is 9600 :param str mode: *OPTIONAL* mode, mode of connection (telnet/serial/ssh) default is telnet :param int timeout: *OPTIONAL* timeout, default is 0.5 :param int attempts: *OPTIONAL* attempts, default is 10 :param str ssh_config: *OPTIONAL* The path to the SSH configuration file. This can be used to load SSH information from a configuration file. By default ~/.ssh/config is queried it will be used by SCP class. So its assumed ssh is enabled by the time we use SCP functionality. :param bool gather_facts: *OPTIONAL* default is ``False``. If ``False`` then the facts are not gathered on call to :meth:`open` """ # ---------------------------------------- # setup instance connection/open variables # ---------------------------------------- self._tty = None self._facts = {} self.connected = False self._skip_logout = False self.results = dict(changed=False, failed=False, errmsg=None) # hostname is not required in serial mode connection self._hostname = kvargs.get('host') self._auth_user = kvargs.get('user', 'root') self._auth_password = kvargs.get( 'password', '') or kvargs.get( 'passwd', '') self._port = kvargs.get('port', '23') self._baud = kvargs.get('baud', '9600') self._mode = kvargs.get('mode', 'telnet') self._timeout = kvargs.get('timeout', '0.5') # self.timeout needed by PyEZ utils self.timeout = self._timeout self._attempts = kvargs.get('attempts', 10) self.gather_facts = kvargs.get('gather_facts', False) self.rpc = _RpcMetaExec(self) from jnpr.junos import Device if sys.version < '3': self.cli = lambda cmd, format='text', warning=True: \ Device.cli.im_func(self, cmd, format, warning) self._sshconf_path = lambda: Device._sshconf_lkup.im_func(self) self.facts_refresh = lambda exception_on_failure=False: \ Device.facts_refresh.im_func(self, exception_on_failure) else: self.cli = lambda cmd, format='text', warning=True: \ Device.cli(self, cmd, format, warning) self._sshconf_path = lambda: Device._sshconf_lkup(self) self.facts_refresh = lambda exception_on_failure=False: \ Device.facts_refresh(self, exception_on_failure) self._ssh_config = kvargs.get('ssh_config')
from jnpr.junos import Device from jnpr.junos.utils.config import Config from pprint import pprint from getpass import getpass import sys out = open("C:\Users\Amr Ali\PycharmProjects\Juniper-PYZ\out.txt", 'w') x = 11 while x <= 13: dev = Device(host="127.0.0.1", user="******", passwd="root123", mode="telnet", port=str(x)) dev.open() print dev.facts print type(dev.facts) facts = dev.facts["hostname"] + " " + dev.facts["version"] isis = dev.cli("show configuration protocols isis | display set") out.write(facts) out.write(isis) #print dev.rpc.get_isis_adjacency_information() dev.close() x += 1 out.close() print " check data on following path \"C:\Users\Amr Ali\PycharmProjects\Juniper-PYZ\out.txt\""
for i in xrange(40, 0, -1): time.sleep(1) dev_ssh = Device(host=dev_ip_address, user=dev_username, passwd=dev_password, port='22') try: dev_ssh.open() except ConnectError as err: print ("Cannot connect to device: {0}".format(err)) sys.exit(1) except Exception as err: print (err) sys.exit(1) command1 = dev_ssh.cli('show configuration groups', warning=False) check1 = command1.find('fxp0') command2 = dev_ssh.cli('show configuration system root-authentication', warning=False) check2 = command2.find('encrypted-password') command3 = dev_ssh.cli('show configuration system services', warning=False) check3 = command3.find('ssh') command4 = dev.cli('show configuration system login', warning=False) check4 = command4.find('write') command5 = dev.cli('show configuration routing-options static', warning=False) check5 = command5.find('preference') if check1 >= 0 & check2 >= 0 & check3 >= 0 & check4 >= 0 & check5 >= 0:
class TestDevice(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() @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_new_console_return(self): dev = Device(host='1.1.1.1', user='******', password='******', port=23, gather_facts=False) self.assertTrue(isinstance(dev, Console)) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectAuthError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.AuthenticationError self.assertRaises(EzErrors.ConnectAuthError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectRefusedError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError self.assertRaises(EzErrors.ConnectRefusedError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') @patch('jnpr.junos.device.datetime') def test_device_ConnectTimeoutError(self, mock_datetime, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError( "Could not open socket to 1.1.1.1:830") from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectTimeoutError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') @patch('jnpr.junos.device.datetime') def test_device_diff_err_message(self, mock_datetime, mock_manager): NcErrors.SSHError.message = 'why are you trying :)' mock_manager.connect.side_effect = NcErrors.SSHError from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectUnknownHostError(self, mock_manager): import socket mock_manager.connect.side_effect = socket.gaierror self.assertRaises(EzErrors.ConnectUnknownHostError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_other_error(self, mock_manager): mock_manager.connect.side_effect = TypeError self.assertRaises(EzErrors.ConnectError, self.dev.open) def test_device_probe_error(self): mock_probe = MagicMock() mock_probe.return_value = None self.dev.probe = mock_probe def fn(): self.dev.open(auto_probe=1) self.assertRaises(EzErrors.ProbeError, fn) def test_device_property_logfile_isinstance(self): mock = MagicMock() with patch(builtin_string + '.open', mock): if sys.version > '3': builtin_file = 'io.TextIOWrapper' else: builtin_file = builtin_string + '.file' with patch(builtin_file, MagicMock): handle = open('filename', 'r') self.dev.logfile = handle self.assertEqual(self.dev.logfile, handle) def test_device_host_mand_param(self): self.assertRaises(ValueError, Device, user='******', password='******', gather_facts=False) def test_device_property_logfile_close(self): self.dev._logfile = MagicMock() self.dev._logfile.close.return_value = 0 self.dev.logfile = None self.assertFalse(self.dev._logfile) def test_device_property_logfile_exception(self): try: self.dev.logfile = True except Exception as ex: self.assertEqual(type(ex), ValueError) def test_device_master_is_master(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['re1', 'master', 'node', 'fwdd', 'member', 'pfem'] self.assertEqual(localdev.master, True) def test_device_master_is_backup(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['re0', 'backup'] self.assertEqual(localdev.master, False) def test_device_master_is_re0_only(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['2RE'] = False localdev.facts._cache['RE_hw_mi'] = False localdev.facts._cache['current_re'] = ['re0'] self.assertEqual(localdev.master, True) def test_device_master_is_multi_chassis_non_master1(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['2RE'] = True localdev.facts._cache['current_re'] = ['lcc1-re1', 'member1-re1', 'lcc1-backup', 'member1-backup'] self.assertEqual(localdev.master, False) def test_device_master_is_multi_chassis_non_master2(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['2RE'] = True localdev.facts._cache['current_re'] = ['lcc1-re0', 'member1-re0', 'lcc1-master', 'member1-master', 'member1'] self.assertEqual(localdev.master, False) def test_device_master_is_none1(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = None self.assertEqual(localdev.master, None) def test_device_master_is_none2(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['2RE'] = True localdev.facts._cache['current_re'] = ['foo', 'bar'] self.assertEqual(localdev.master, None) @patch('jnpr.junos.device.warnings') def test_device_master_is_old_facts(self, mock_warn): localdev = Device(host='1.1.1.1', user='******', password='******', fact_style='old', gather_facts=False) mock_warn.assert_has_calls([call.warn('fact-style old will be removed ' 'in a future release.', RuntimeWarning)]) self.assertEqual(localdev.master, None) def test_device_master_setter(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) with self.assertRaises(RuntimeError): localdev.master = 'foo' def test_device_re_name_is_re0(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['re0', 'backup'] localdev.facts._cache['hostname_info'] = {'re0': 'tapir', 're1': 'tapir1'} self.assertEqual(localdev.re_name, 're0') def test_device_re_name_is_lcc_re1(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['lcc1-re1', 'member1-re1', 'lcc1-backup', 'member1-backup'] localdev.facts._cache['hostname_info'] = {'re0': 'mj1'} self.assertEqual(localdev.re_name, 'lcc1-re1') def test_device_re_name_is_re0_only(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['foo'] localdev.facts._cache['hostname_info'] = {'re0': 'mj1'} self.assertEqual(localdev.re_name, 're0') def test_device_re_name_is_none1(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = None self.assertEqual(localdev.re_name, None) def test_device_re_name_is_none2(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) localdev.facts._cache['current_re'] = ['re1', 'master', 'node', 'fwdd', 'member', 'pfem'] localdev.facts._cache['hostname_info'] = None self.assertEqual(localdev.re_name, None) @patch('jnpr.junos.device.warnings') def test_device_re_name_is_old_facts(self, mock_warn): localdev = Device(host='1.1.1.1', user='******', password='******', fact_style='old', gather_facts=False) mock_warn.assert_has_calls([call.warn('fact-style old will be removed ' 'in a future release.', RuntimeWarning)]) self.assertEqual(localdev.re_name, None) def test_device_re_name_setter(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) with self.assertRaises(RuntimeError): localdev.re_name = 'foo' def test_device_repr(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.assertEqual(repr(localdev), 'Device(1.1.1.1)') def test_device_local(self): Device.ON_JUNOS = True localdev = Device() self.assertEqual(localdev._hostname, 'localhost') @patch('jnpr.junos.device.os') @patch(builtin_string + '.open') @patch('paramiko.config.SSHConfig.lookup') def test_device__sshconf_lkup(self, mock_paramiko, open_mock, os_mock): os_mock.path.exists.return_value = True self.dev._sshconf_lkup() mock_paramiko.assert_called_once_with('1.1.1.1') @patch('jnpr.junos.device.os') @patch(builtin_string + '.open') @patch('paramiko.config.SSHConfig.lookup') def test_device__sshconf_lkup_def(self, mock_paramiko, open_mock, os_mock): os_mock.path.exists.return_value = True self.dev._ssh_config = '/home/rsherman/.ssh/config' self.dev._sshconf_lkup() mock_paramiko.assert_called_once_with('1.1.1.1') @patch('os.getenv') def test_device__sshconf_lkup_path_not_exists(self, mock_env): mock_env.return_value = '/home/test' self.assertEqual(self.dev._sshconf_lkup(), None) @patch('os.getenv') def test_device__sshconf_lkup_home_not_defined(self, mock_env): mock_env.return_value = None self.assertEqual(self.dev._sshconf_lkup(), None) mock_env.assert_called_with('HOME') @patch('ncclient.manager.connect') @patch('jnpr.junos.Device.execute') def test_device_open(self, mock_connect, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_cat.return_value = """ domain jls.net """ mock_connect.side_effect = self._mock_manager mock_execute.side_effect = self._mock_manager self.dev2 = Device( host='2.2.2.2', user='******', password='******') self.dev2.open() self.assertEqual(self.dev2.connected, True) @patch('jnpr.junos.Device.execute') def test_device_facts(self, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.return_value = """ domain jls.net """ self.dev.facts_refresh() self.dev.facts._cache['current_re'] = ['re0'] assert self.dev.facts['version'] == facts['version'] @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.factcache.warnings') def test_device_facts_error(self, mock_warnings, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.side_effect = IOError('File cant be handled') self.dev.facts_refresh(warnings_on_failure=True) self.assertTrue(mock_warnings.warn.called) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.device.warnings') def test_device_facts_error_exception_on_error(self, mock_warnings, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.side_effect = IOError('File cant be handled') self.assertRaises(IOError, self.dev.facts_refresh, exception_on_failure=True) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.device.warnings') def test_device_old_style_facts_error_exception_on_error(self, mock_warnings, mock_execute): self.dev._fact_style = 'old' with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.side_effect = IOError('File cant be handled') self.assertRaises(IOError, self.dev.facts_refresh, exception_on_failure=True) def test_device_facts_refresh_unknown_fact_style(self): self.dev._fact_style = 'bad' with self.assertRaises(RuntimeError): self.dev.facts_refresh() def test_device_facts_refresh_old_fact_style_with_keys(self): self.dev._fact_style = 'old' with self.assertRaises(RuntimeError): self.dev.facts_refresh(keys='domain') def test_device_hostname(self): self.assertEqual(self.dev.hostname, '1.1.1.1') def test_device_user(self): self.assertEqual(self.dev.user, 'test') def test_device_get_password(self): self.assertEqual(self.dev.password, None) def test_device_set_password(self): self.dev.password = '******' self.assertEqual(self.dev._auth_password, 'secret') def test_device_get_timeout(self): self.assertEqual(self.dev.timeout, 30) def test_device_set_timeout(self): self.dev.timeout = 10 self.assertEqual(self.dev.timeout, 10) def test_device_manages(self): self.assertEqual(self.dev.manages, [], 'By default manages will be empty list') @patch('ncclient.manager.connect') @patch('jnpr.junos.Device.execute') def test_device_open_normalize(self, mock_connect, mock_execute): mock_connect.side_effect = self._mock_manager self.dev2 = Device(host='2.2.2.2', user='******', password='******') self.dev2.open(gather_facts=False, normalize=True) self.assertEqual(self.dev2.transform, self.dev2._norm_transform) def test_device_set_facts_exception(self): try: self.dev.facts = 'test' except RuntimeError as ex: self.assertEqual(RuntimeError, type(ex)) def test_device_ofacts_exception(self): with self.assertRaises(RuntimeError): ofacts = self.dev.ofacts def test_device_set_ofacts_exception(self): with self.assertRaises(RuntimeError): self.dev.ofacts = False @patch('jnpr.junos.Device.execute') def test_device_cli(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli('show cli directory', warning=False).tag, 'cli') @patch('jnpr.junos.device.json.loads') def test_device_rpc_json_ex(self, mock_json_loads): self.dev.facts = facts self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) ex = ValueError('Extra data ') ex.message = 'Extra data ' # for py3 as we dont have message thr mock_json_loads.side_effect = [ ex, self._mock_manager(etree.fromstring( '<get-route-information format="json"/>'))] self.dev.rpc.get_route_information({'format': 'json'}) self.assertEqual(mock_json_loads.call_count, 2) @patch('jnpr.junos.Device.execute') def test_device_cli_to_rpc_string(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli_to_rpc_string('show system uptime') self.assertEqual("rpc.get_system_uptime_information()", data) @patch('jnpr.junos.Device.execute') def test_device_cli_to_rpc_string_strip_pipes(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli_to_rpc_string( 'show system uptime | match foo | count') self.assertEqual("rpc.get_system_uptime_information()", data) @patch('jnpr.junos.Device.execute') def test_device_cli_to_rpc_string_complex(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli_to_rpc_string( 'show interfaces ge-0/0/0.0 routing-instance all media') self.assertEqual("rpc.get_interface_information(" "routing_instance='all', media=True, " "interface_name='ge-0/0/0.0')", data) @patch('jnpr.junos.Device.execute') def test_device_cli_to_rpc_string_invalid(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli_to_rpc_string('foo') self.assertEqual(None, data) @patch('jnpr.junos.Device.execute') def test_device_cli_format_json(self, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli('show interface terse', warning=False, format='json') self.assertEqual(type(data), dict) self.assertEqual(data['interface-information'][0] ['physical-interface'][0]['oper-status'][0]['data'], 'up') @patch('jnpr.junos.Device.execute') def test_device_cli_conf_info(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('ge-0/0/0' in self.dev.cli('show configuration', warning=False)) @patch('jnpr.junos.Device.execute') def test_device_cli_output(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Alarm' in self.dev.cli('show system alarms', warning=False)) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.device.warnings') def test_device_cli_output_warning(self, mock_warnings, mock_execute): mock_execute.side_effect = self._mock_manager data = self.dev.cli('show interfaces ge-0/0/0.0 routing-instance ' 'all media', format='xml') ip = data.findtext('logical-interface[name="ge-0/0/0.0"]/' 'address-family[address-family-name="inet"]/' 'interface-address/ifa-local') self.assertTrue('192.168.100.1' in ip) self.assertTrue(mock_warnings.warn.called) rpc_string = "rpc.get_interface_information(routing_instance='all', "\ "media=True, interface_name='ge-0/0/0.0')" self.assertIn(rpc_string, mock_warnings.warn.call_args[0][0]) def test_device_cli_blank_output(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual('', self.dev.cli('show configuration interfaces', warning=False)) def test_device_cli_rpc_reply_with_message(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual( '\nprotocol: operation-failed\nerror: device asdf not found\n', self.dev.cli('show interfaces terse asdf', warning=False)) @patch('jnpr.junos.Device.execute') def test_device_cli_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli('show system uptime| display xml rpc', warning=False) .tag, 'get-system-uptime-information') def test_device_cli_exception(self): self.dev.rpc.cli = MagicMock(side_effect=AttributeError) val = self.dev.cli('show version') self.assertEqual(val, 'invalid command: show version') @patch('jnpr.junos.Device.execute') def test_device_cli_rpc_exception(self, mock_execute): mock_execute.side_effect = self._mock_manager val = self.dev.cli('foo') self.assertEqual(val, 'invalid command: foo: RpcError') @patch('jnpr.junos.Device.execute') def test_device_display_xml_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual( self.dev.display_xml_rpc('show system uptime').tag, 'get-system-uptime-information') @patch('jnpr.junos.Device.execute') def test_device_display_xml_rpc_text(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertIn( '<get-system-uptime-information>', self.dev.display_xml_rpc( 'show system uptime', format='text')) @patch('jnpr.junos.Device.execute') def test_device_display_xml_exception(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual( self.dev.display_xml_rpc('show foo'), 'invalid command: show foo| display xml rpc') def test_device_execute(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute('<get-system-core-dumps/>').tag, 'directory-list') def test_device_execute_topy(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute('<get-system-core-dumps/>', to_py=self._do_nothing), 'Nothing') # This test is for the commented out rpc-error code # def test_device_execute_exception(self): # self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) # self.assertRaises(RpcError, self.dev.execute, # '<load-configuration-error/>') @patch('jnpr.junos.device.warnings') def test_device_execute_unknown_exception(self, mock_warnings): class MyException(Exception): pass self.dev._conn.rpc = MagicMock(side_effect=MyException) self.assertRaises(MyException, self.dev.execute, '<get-software-information/>') def test_device_execute_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises(RpcError, self.dev.rpc.get_rpc_error) def test_device_execute_permission_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises( EzErrors.PermissionError, self.dev.rpc.get_permission_denied) def test_device_execute_index_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertTrue(self.dev.rpc.get_index_error()) def test_device_execute_ValueError(self): self.assertRaises(ValueError, self.dev.execute, None) def test_device_execute_unopened(self): self.dev.connected = False self.assertRaises(EzErrors.ConnectClosedError, self.dev.execute, None) def test_device_execute_timeout(self): self.dev._conn.rpc = MagicMock(side_effect=TimeoutExpiredError) self.assertRaises( EzErrors.RpcTimeoutError, self.dev.rpc.get_rpc_timeout) def test_device_execute_closed(self): self.dev._conn.rpc = MagicMock(side_effect=NcErrors.TransportError) self.assertRaises( EzErrors.ConnectClosedError, self.dev.rpc.get_rpc_close) self.assertFalse(self.dev.connected) def test_device_rpcmeta(self): self.assertEqual(self.dev.rpc.get_software_information.__doc__, 'get-software-information') def test_device_probe_timeout_zero(self): with patch('jnpr.junos.device.socket'): self.assertFalse(self.dev.probe(0)) def test_device_probe_timeout_gt_zero(self): with patch('jnpr.junos.device.socket'): self.assertTrue(self.dev.probe(1), 'probe fn is not working for' ' timeout greater than zero') def test_device_probe_timeout_exception(self): with patch('jnpr.junos.device.socket') as mock_socket: with patch('jnpr.junos.device.time.sleep') as mock_time: mock_socket.socket.return_value.close.side_effect \ = RuntimeError mock_time.return_value = None self.assertFalse(self.dev.probe(.01)) def test_device_bind_varg(self): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic_mock' self.dev.bind(mock) self.assertEqual(self.dev.magic_mock.__name__, 'magic_mock') def test_device_bind_kvarg(self): self.dev.bind() mock = MagicMock() mock.return_value = 'Test' self.dev.bind(kw=mock) self.assertEqual(self.dev.kw, 'Test') def test_device_bind_varg_exception(self): def varg(): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic mock' # for *args self.dev.bind(mock) self.dev.bind(mock) self.assertRaises(ValueError, varg) def test_device_bind_kvarg_exception(self): def kve(): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic mock' # for **kwargs self.dev.bind(kw=mock) self.dev.bind(kw=mock) self.assertRaises(ValueError, kve) def test_device_template(self): # Try to load the template relative to module base try: template = self.dev.Template( 'tests/unit/templates/config-example.xml') except: # Try to load the template relative to test base try: template = self.dev.Template('templates/config-example.xml') except: raise self.assertEqual(template.render({'host_name': '1', 'domain_name': '2'}), 'system {\n host-name 1;\n domain-name 2;\n}') def test_device_close(self): def close_conn(): self.dev.connected = False self.dev.close = MagicMock(name='close') self.dev.close.side_effect = close_conn self.dev.close() self.assertEqual(self.dev.connected, False) @patch('ncclient.manager.connect') def test_device_context_manager(self, mock_connect): mock_connect.side_effect = self._mock_manager try: with Device(host='3.3.3.3', user='******', password='******', gather_facts=False) as dev: self.assertTrue(dev.connected) dev._conn = MagicMock(name='_conn') dev._conn.connected = True def close_conn(): dev.connected = False dev.close = MagicMock(name='close') dev.close.side_effect = close_conn raise RpcError except Exception as e: self.assertIsInstance(e, RpcError) self.assertFalse(dev.connected) def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) with open(fpath) as fp: foo = fp.read() if fname == 'get-rpc-error.xml': # Raise ncclient exception for error raise RPCError(etree.XML(foo)) elif fname == 'get-permission-denied.xml': # Raise ncclient exception for error raise RPCError(etree.XML(foo)) elif (fname == 'get-index-error.xml' or fname == 'get-system-core-dumps.xml' or fname == 'load-configuration-error.xml' or fname == 'show-configuration-interfaces.xml' or fname == 'show-interfaces-terse-asdf.xml'): rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply()) elif (fname == 'show-configuration.xml' or fname == 'show-system-alarms.xml'): rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply())._NCElement__doc elif fname == 'show-interface-terse.json': rpc_reply = json.loads(foo) elif fname == 'get-route-information.json': rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply()) else: rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply())._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs and 'normalize' not in kwargs: device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].tag == 'command': if args[0].text == 'show cli directory': return self._read_file('show-cli-directory.xml') if args[0].text == 'show interface terse': return self._read_file('show-interface-terse.json') elif args[0].text == 'show configuration': return self._read_file('show-configuration.xml') elif args[0].text == 'show system alarms': return self._read_file('show-system-alarms.xml') elif args[0].text == 'show system uptime| display xml rpc': return self._read_file('show-system-uptime-rpc.xml') elif args[0].text == 'show configuration interfaces': return self._read_file('show-configuration-interfaces.xml') elif args[0].text == 'show interfaces terse asdf': return self._read_file('show-interfaces-terse-asdf.xml') elif args[0].text == 'show interfaces ge-0/0/0.0 ' \ 'routing-instance all media': return self._read_file( 'show-interfaces-routing-instance-media.xml') elif args[0].text == 'show interfaces ge-0/0/0.0 ' \ 'routing-instance all media| display ' \ 'xml rpc': return self._read_file( 'show-interfaces-routing-instance-media-rpc.xml') else: raise RpcError else: if args[0].attrib.get('format') == 'json': return self._read_file(args[0].tag + '.json') return self._read_file(args[0].tag + '.xml') def _do_nothing(self, *args, **kwargs): return 'Nothing'
def handle_create(self): assert self.properties[self.ZEROIZE] == 'zeroize', "You must set 'zeroize=zeroize' ({0})".format(self.properties[self.ZEROIZE]) # # ! UNREACHABLE results = {} logfile = self.properties[self.LOGFILE] if logfile is not None: logging.basicConfig(filename=logfile, level=logging.INFO, format='%(asctime)s:%(name)s:%(message)s') logging.getLogger().name = 'NETCONIFY:' + self.properties[self.HOST] def log_notify(self, event, message): logging.info("%s:%s" % (event, message)) use_notifier = log_notify else: def silent_notify(self, event, message): pass use_notifier = silent_notify if self.properties[self.CONSOLE] is 0: # via NETCONF assert HAS_PYEZ, "junos-eznc >= 1.1.x is required for this module" dev = Device(self.properties[self.HOST], user=self.properties[self.USER], password=self.properties[self.PASSWORD], port=self.properties[self.PORT]) try: use_notifier(None, 'LOGIN', 'host={0}'.format(self.properties[self.HOST])) dev.open() use_notifier(None, 'LOGIN', 'OK') except Exception as err: logging.info("connecting to host: {0}:{1}".format(self.properties[self.HOST], str(err))) return # --- UNREACHABLE --- use_notifier(None, 'ZEROIZE', 'invoking command') dev.cli('request system zeroize') results['changed'] = True # no close, we're done after this point. else: try: from netconify.cmdo import netconifyCmdo from netconify.constants import version if not float(re.match('\d+.\d+', version).group()) >= 1.0: logging.info("junos-netconify >= 1.0.x is required for this module") return except ImportError: logging.info("junos-netconify >= 1.0.x is required for this module") return nc_args = [] nc_args.append(self.properties[self.CONSOLE]) nc_args.append('--zeroize') if self.properties[self.USER] is not None: nc_args.append('--user='******'--passwd=' + self.properties[self.PASSWORD]) try: nc = netconifyCmdo(notify=use_notifier) nc.run(nc_args) except Exception as err: logging.info("connecting to host: {0}".format(str(err))) return results['changed'] = True # indicate done in the logfile and return results use_notifier(None, 'DONE', 'OK')
#key = psum.pop(0) #peerIPtable[key] = psum #print peerIPtable allpeer = {} peersum = dev.rpc.get_bgp_summary_information(normalize=True) allpeer = peersum.findtext("bgp-information/bgp-peer/description") while line in peersum: print peersum ncounter = 0 while ncounter < counter: print peertable[ncounter] with open("AnyCast-Master-Table.txt", "r") as anyfile: anycastroutes = dev.cli( 'show route advertising-protocol bgp 172.16.1.2') for line in anyfile: line = line.strip().lower() if line in anycastroutes: print 'Anycast match route ' + line else: print 'Missing Anycast route ' + line ncounter = ncounter + 1 #with open('no_peer.txt', 'r') as file1: # with open(peer_sum, 'r') as file2: # same = set(file1).intersection(file2) #same.discard('\n')
class NetconfAction(ActionBase): """ Uses NetConf to execute the given template Can execute template as an op command or apply the template as a configuration template """ dev = None request_type = "apply_template" result_msg = "" def set_endpoint(self, endpoint): try: # create the required iterator from the endpoint_list self.dev = Device(user=endpoint["username"], password=endpoint["password"], host=endpoint["ip"]) self.dev.open(gather_facts=False) except Exception as err: print "Could not open device!" self.result_msg = str(err) self.dev = None return def execute_template(self, template): """ switches based on request_type chosen from template configuration :param template: :return: String results from the endpoint netconf subsystem """ if self.dev is None: return self.result_msg if self.request_type == "apply_template": return self.apply_template(template) elif self.request_type == "execute_cheat_command": return self.execute_cheat_command(template) elif self.request_type == "assert_set_configuration": return self.assert_set_configuration(template) elif self.request_type == "assert_xpath_configuration": return self.assert_xpath_configuration(template) else: return self.execute_op_command(template) def execute_op_command(self, template): try: results = self.dev.execute(template) except RpcError as e: print e return "Error executing command: %s" % str(e) print etree.tostring(results, pretty_print=True) return etree.tostring(results, pretty_print=True) def execute_cheat_command(self, template): print "Executing cheat command" results = self.dev.cli(template) return results def assert_set_configuration(self, pattern): print "Checking set command regex" config = self.dev.cli('show configuration | display set') print config config_pattern = re.compile(pattern) results = "" for line in config.split('\n'): if config_pattern.match(line): results += line + "\n" if results != "": return results def assert_xpath_configuration(self, xpath): print "Searching xpath" configuration_xml = self.dev.execute("<get-configuration></get-configuration>") print configuration_xml if configuration_xml.find(xpath): return "Configuration element: %s is present" % xpath return "not found" def apply_template(self, template): print self.dev conf_string = template.strip() # try to determine the format of our config_string config_format = "set" if re.search(r"^\s*<.*>$", conf_string, re.MULTILINE): config_format = "xml" elif re.search(r"^\s*(set|delete|replace|rename)\s", conf_string): config_format = "set" elif re.search(r"^[a-z:]*\s*\w+\s+{", conf_string, re.I) and re.search(r".*}\s*$", conf_string): config_format = "text" print "using format: " + config_format cu = Config(self.dev) try: cu.lock() except LockError as le: print "Could not lock database!" print str(le) self.dev.close() return "Failed to lock configuration database! %s" % str(le) try: print "loading config" cu.load(conf_string, format=config_format) except Exception as e: print "Could not load configuration" print str(e) try: cu.unlock() except UnlockError as ue: print str(ue) self.dev.close() return "Failed, could not load the configuration template. %s" % str(e) diff = cu.diff() print diff if diff is not None: try: cu.commit_check() print "Committing config!" cu.commit(comment="Commit via a_frame") except CommitError as ce: print "Could not load config! %s" % str(ce) cu.rollback() try: print "Unlocking database!" cu.unlock() except UnlockError as ue: print "Could not unlock database" print str(ue) print repr(ce) self.dev.close() return "Failed, commit check failed. %s" % str(ce) else: # nothing to commit print "Nothing to commit - no diff found" return "Nothing to commit!" try: print "Unlocking database!" cu.unlock() except UnlockError as ue: print "Could not unlock database" print str(ue) self.dev.close() return "Committed, but could not unlock db" print "Closing device handle" self.dev.close() return "Completed with diff: %s" % diff
description "MPLS interface"; unit 0 { family mpls; } } } """ cu.load(data, format='text') print "\nconfig# show | compare" cu.pdiff() if cu.commit_check(): print "\nCommiting..\n" cu.commit(comment="Configuring ge-1/0/1 interfaces", detail=True) else: cu.rollback() print "cli> show configuration interfaces", dev.cli( "show configuration interfaces", warning=False) print "Rolling back the configuration" cu.rollback(rb_id=1) cu.commit(detail=True) print "cli> show configuration interfaces", dev.cli( "show configuration interfaces", warning=False) dev.close()
myparser = Parser() ex = Device(host=ex_switch,user=ex_user,password=ex_password) ex.open() config = etree.tostring(ex.rpc.get_configuration()) srx = Device(host=srx_firewall,user=srx_user,password=srx_password) srx.open() users = etree.tostring(srx.rpc.get_userfw_local_auth_table_all()) #Delete all existing users for (_, _, user_entry) in myparser(users, generator=['local-authentication-info']): existing_ip_address = (user_entry['ip-address']).get_cdata() user_del_command = "request security user-identification local-authentication-table del ip-address " + str(existing_ip_address) srx.cli(command=user_del_command,format='text', warning=False) #Read static users based on configuration in EX-Series DHCP server for (_, _, static_entry) in myparser(config, generator=['static-binding']): mac = (static_entry['name']).get_cdata() host_name = (static_entry['host-name']).get_cdata() ip_address = (static_entry['fixed-address']['name']).get_cdata() user_add_command = "request security user-identification local-authentication-table add ip-address " + str(ip_address) + " user-name " + str(host_name) srx.cli(command=user_add_command,format='text', warning=False) ex.close() srx.close()
class TestDevice(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() @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectAuthError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.AuthenticationError self.assertRaises(EzErrors.ConnectAuthError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectRefusedError(self, mock_manager): mock_manager.connect.side_effect = NcErrors.SSHError self.assertRaises(EzErrors.ConnectRefusedError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') @patch('jnpr.junos.device.datetime') def test_device_ConnectTimeoutError(self, mock_datetime, mock_manager): NcErrors.SSHError.message = 'cannot open' mock_manager.connect.side_effect = NcErrors.SSHError from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectTimeoutError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') @patch('jnpr.junos.device.datetime') def test_device_diff_err_message(self, mock_datetime, mock_manager): NcErrors.SSHError.message = 'why are you trying :)' mock_manager.connect.side_effect = NcErrors.SSHError from datetime import timedelta, datetime currenttime = datetime.now() mock_datetime.datetime.now.side_effect = [currenttime, currenttime + timedelta(minutes=4)] self.assertRaises(EzErrors.ConnectError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_ConnectUnknownHostError(self, mock_manager): import socket mock_manager.connect.side_effect = socket.gaierror self.assertRaises(EzErrors.ConnectUnknownHostError, self.dev.open) @patch('jnpr.junos.device.netconf_ssh') def test_device_other_error(self, mock_manager): mock_manager.connect.side_effect = TypeError self.assertRaises(EzErrors.ConnectError, self.dev.open) def test_device_property_logfile_isinstance(self): mock = MagicMock() with patch('__builtin__.open', mock): with patch('__builtin__.file', MagicMock): handle = open('filename', 'r') self.dev.logfile = handle self.assertEqual(self.dev.logfile, handle) def test_device_host_mand_param(self): self.assertRaises(ValueError, Device, user='******', password='******', gather_facts=False) def test_device_property_logfile_close(self): self.dev._logfile = MagicMock() self.dev._logfile.close.return_value = 0 self.dev.logfile = None self.assertFalse(self.dev._logfile) def test_device_property_logfile_exception(self): try: self.dev.logfile = True except Exception as ex: self.assertEqual(type(ex), ValueError) def test_device_repr(self): localdev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.assertEqual(repr(localdev), 'Device(1.1.1.1)') @patch('jnpr.junos.device.os') @patch('__builtin__.open') @patch('paramiko.config.SSHConfig.lookup') def test_device__sshconf_lkup(self, os_mock, open_mock, mock_paramiko): os_mock.path.exists.return_value = True self.dev._sshconf_lkup() mock_paramiko.assert_called_any() @patch('os.getenv') def test_device__sshconf_lkup_path_not_exists(self, mock_env): mock_env.return_value = '/home/test' self.assertEqual(self.dev._sshconf_lkup(), None) @patch('os.getenv') def test_device__sshconf_lkup_home_not_defined(self, mock_env): mock_env.return_value = None self.assertEqual(self.dev._sshconf_lkup(), None) mock_env.assert_called_with('HOME') @patch('ncclient.manager.connect') @patch('jnpr.junos.Device.execute') def test_device_open(self, mock_connect, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_cat.return_value = """ domain jls.net """ mock_connect.side_effect = self._mock_manager mock_execute.side_effect = self._mock_manager self.dev2 = Device(host='2.2.2.2', user='******', password='******') self.dev2.open() self.assertEqual(self.dev2.connected, True) @patch('jnpr.junos.Device.execute') def test_device_facts(self, mock_execute): with patch('jnpr.junos.utils.fs.FS.cat') as mock_cat: mock_execute.side_effect = self._mock_manager mock_cat.return_value = """ domain jls.net """ self.dev.facts_refresh() assert self.dev.facts['version'] == facts['version'] def test_device_hostname(self): self.assertEqual(self.dev.hostname, '1.1.1.1') def test_device_user(self): self.assertEqual(self.dev.user, 'rick') def test_device_get_password(self): self.assertEqual(self.dev.password, None) def test_device_set_password(self): self.dev.password = '******' self.assertEqual(self.dev._password, 'secret') def test_device_get_timeout(self): self.assertEqual(self.dev.timeout, 30) def test_device_set_timeout(self): self.dev.timeout = 10 self.assertEqual(self.dev.timeout, 10) def test_device_manages(self): self.assertEqual(self.dev.manages, [], 'By default manages will be empty list') def test_device_set_facts_exception(self): try: self.dev.facts = 'test' except RuntimeError as ex: self.assertEqual(RuntimeError, type(ex)) @patch('jnpr.junos.Device.execute') def test_device_cli(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli('show cli directory').tag, 'cli') @patch('jnpr.junos.Device.execute') def test_device_cli_conf_info(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('ge-0/0/0' in self.dev.cli('show configuration')) @patch('jnpr.junos.Device.execute') def test_device_cli_output(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Alarm' in self.dev.cli('show system alarms')) @patch('jnpr.junos.Device.execute') def test_device_cli_rpc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertEqual(self.dev.cli('show system uptime | display xml rpc')\ .tag, 'get-system-uptime-information') def test_device_cli_exception(self): self.dev.rpc.cli = MagicMock(side_effect=AttributeError) val = self.dev.cli('show version') self.assertEqual(val, 'invalid command: show version') def test_device_execute(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute('<get-system-core-dumps/>').tag, 'directory-list') def test_device_execute_topy(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.dev.execute('<get-system-core-dumps/>', to_py=self._do_nothing), 'Nothing') def test_device_execute_exception(self): class MyException(Exception): rpc_err = """ <rpc-error xmlns="urn:ietf:params:xml:ns:netconf:base:1.0" xmlns:junos="http://xml.juniper.net/junos/12.1X46/junos" xmlns:nc="urn:ietf:params:xml:ns:netconf:base:1.0"> <error-severity>error</error-severity> <error-info> <bad-element>get-bgp-summary-information</bad-element> </error-info> <error-message>permission denied</error-message> </rpc-error> """ xml = etree.XML(rpc_err) self.dev._conn.rpc = MagicMock(side_effect=MyException) self.assertRaises(RpcError, self.dev.execute, '<get-software-information/>') def test_device_execute_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertRaises(RpcError, self.dev.rpc.get_rpc_error) def test_device_execute_index_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) self.assertTrue(self.dev.rpc.get_index_error()) def test_device_execute_ValueError(self): self.assertRaises(ValueError, self.dev.execute, None) def test_device_rpcmeta(self): self.assertEqual(self.dev.rpc.get_software_information.func_doc, 'get-software-information') def test_device_probe_timeout_zero(self): with patch('jnpr.junos.device.socket'): self.assertFalse(self.dev.probe(0)) def test_device_probe_timeout_gt_zero(self): with patch('jnpr.junos.device.socket'): self.assertTrue(self.dev.probe(1), 'probe fn is not working for' ' timeout greater than zero') def test_device_probe_timeout_exception(self): with patch('jnpr.junos.device.socket') as mock_socket: with patch('jnpr.junos.device.time.sleep') as mock_time: mock_socket.socket.return_value.close.side_effect \ = RuntimeError mock_time.return_value = None self.assertFalse(self.dev.probe(.01)) def test_device_bind_varg(self): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic_mock' self.dev.bind(mock) self.assertEqual(self.dev.magic_mock.__name__, 'magic_mock') def test_device_bind_kvarg(self): self.dev.bind() mock = MagicMock() mock.return_value = 'Test' self.dev.bind(kw=mock) self.assertEqual(self.dev.kw, 'Test') def test_device_bind_varg_exception(self): def varg(): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic mock' #for *args self.dev.bind(mock) self.dev.bind(mock) self.assertRaises(ValueError, varg) def test_device_bind_kvarg_exception(self): def kve(): self.dev.bind() mock = MagicMock() mock.__name__ = 'magic mock' #for **kwargs self.dev.bind(kw=mock) self.dev.bind(kw=mock) self.assertRaises(ValueError, kve) def test_device_template(self): # Try to load the template relative to module base try: template = self.dev.Template('tests/unit/templates/config-example') except: # Try to load the template relative to test base try: template = self.dev.Template('templates/config-example') except: raise self.assertEqual(template.render({'host_name': '1', 'domain_name': '2'}), 'system {\n host-name 1;\n domain-name 2;\n}') def test_device_close(self): def close_conn(): self.dev.connected = False self.dev.close = MagicMock(name='close') self.dev.close.side_effect = close_conn self.dev.close() self.assertEqual(self.dev.connected, False) def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() if (fname == 'get-rpc-error.xml' or fname == 'get-index-error.xml' or fname == 'get-system-core-dumps.xml'): rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply()) elif (fname == 'show-configuration.xml' or fname == 'show-system-alarms.xml'): rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply())._NCElement__doc else: rpc_reply = NCElement(foo, self.dev._conn._device_handler .transform_reply())._NCElement__doc[0] return rpc_reply 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: if args[0].tag == 'command': if args[0].text == 'show cli directory': return self._read_file('show-cli-directory.xml') elif args[0].text == 'show configuration': return self._read_file('show-configuration.xml') elif args[0].text == 'show system alarms': return self._read_file('show-system-alarms.xml') elif args[0].text == 'show system uptime | display xml rpc': return self._read_file('show-system-uptime-rpc.xml') else: raise RpcError else: return self._read_file(args[0].tag + '.xml') def _do_nothing(self, *args, **kwargs): return 'Nothing'
from jnpr.junos import Device import sys from getpass import getpass dev = Device('host', user='******', password='******') #dev = Device('10.209.16.236') try: dev.open() except Exception as err: print "Unable to connect to host:", err sys.exit(1) print dev.facts dev.facts_refresh() print dev.facts print dev.cli("show version | display xml rpc") dev.close()
from pprint import pprint as pp from lxml import etree # for the example ... from exampleutils import * from jnpr.junos import Device as Junos login = dict(user='******', host='vsrx_cyan', password='******') jdev = Junos(**login) jdev.open() # you can run any cli command using the :cli: method, for example print "showing command: 'show version'" print jdev.cli("show version") # showing command: 'show version' # Hostname: jnpr-dc-fw # Model: junosv-firefly # JUNOS Software Release [12.1X44-D10.4] # you can also obtain the XML RPC for the associated command by # doing this: print "showing as XML RPC command:" xml_cmd = jdev.cli("show version | display xml rpc") # this is an actual XML element, so we can dump it for debug: etree.dump(xml_cmd)
import jnpr.junos import os import sys from pprint import pprint from jnpr.junos import Device r0 = Device(host='172.16.1.250', user='******', password='******').open() response = r0.cli('show configuration | display set') print response
from jnpr.junos import Device dev = Device(host='xxxx', user='******', password='******', gather_facts=False) dev.open() print dev.cli("show version", warning=False) dev.close()
class JunosDevice(BaseDevice): def __init__(self, host, username, password, *args, **kwargs): super(JunosDevice, self).__init__(host, username, password, *args, vendor='juniper', device_type=JNPR_DEVICE_TYPE, **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.connected = False self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativdSW(self.native) def open(self): if not self.connected: self.native.open() self.connected = True def close(self): if self.connected: self.native.close() self.connected = False def show(self, command, raw_text=True): if not raw_text: raise ValueError('Juniper only supports raw text output. \ Append " | display xml" to your commands for a structured string.') if not command.startswith('show'): raise CommandError(command, 'Juniper "show" commands must begin with "show".') return self.native.cli(command, warning=False) def show_list(self, commands, raw_text=True): responses = [] for command in commands: responses.append(self.show(command, raw_text=raw_text)) return responses def backup_running_config(self, filename): with open(filename, 'w') as f: f.write(self.running_config) def config(self, command, format='set'): try: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandError(command, e.message) def config_list(self, commands, format='set'): try: for command in commands: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandListError(commands, command, e.message) def _uptime_components(self, uptime_full_string): match_days = re.search(r'(\d+) days?', uptime_full_string) match_hours = re.search(r'(\d+) hours?', uptime_full_string) match_minutes = re.search(r'(\d+) minutes?', uptime_full_string) match_seconds = re.search(r'(\d+) seconds?', uptime_full_string) days = int(match_days.group(1)) if match_days else 0 hours = int(match_hours.group(1)) if match_hours else 0 minutes = int(match_minutes.group(1)) if match_minutes else 0 seconds = int(match_seconds.group(1)) if match_seconds else 0 return days, hours, minutes, seconds def _uptime_to_string(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components(uptime_full_string) return '%02d:%02d:%02d:%02d' % (days, hours, minutes, seconds) def _uptime_to_seconds(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components(uptime_full_string) seconds += days * 24 * 60 * 60 seconds += hours * 60 * 60 seconds += minutes * 60 return seconds def _get_interfaces(self): eth_ifaces = EthPortTable(self.native) eth_ifaces.get() loop_ifaces = LoopbackTable(self.native) loop_ifaces.get() ifaces = eth_ifaces.keys() ifaces.extend(loop_ifaces.keys()) return ifaces def checkpoint(self, filename): self.save(filename) def rollback(self, filename): self.native.timeout = 60 temp_file = NamedTemporaryFile() with SCP(self.native) as scp: scp.get(filename, local_path=temp_file.name) self.cu.load(path=temp_file.name, format='text', overwrite=True) self.cu.commit() temp_file.close() self.native.timeout = 30 @property def facts(self): if hasattr(self, '_facts'): return self._facts native_facts = self.native.facts facts = {} facts['hostname'] = native_facts['hostname'] facts['fqdn'] = native_facts['fqdn'] facts['model'] = native_facts['model'] native_uptime_string = native_facts['RE0']['up_time'] facts['uptime'] = self._uptime_to_seconds(native_uptime_string) facts['uptime_string'] = self._uptime_to_string(native_uptime_string) facts['serial_number'] = native_facts['serialnumber'] facts['interfaces'] = self._get_interfaces() for fact_key in native_facts: if fact_key.startswith('version') and fact_key != 'version_info': facts['os_version'] = native_facts[fact_key] break facts['vendor'] = self.vendor self._facts = facts return self._facts def _file_copy_local_file_exists(self, filepath): return os.path.isfile(filepath) def _file_copy_local_md5(self, filepath, blocksize=2**20): if self._file_copy_local_file_exists(filepath): m = hashlib.md5() with open(filepath, "rb") as f: buf = f.read(blocksize) while buf: m.update(buf) buf = f.read(blocksize) return m.hexdigest() def _file_copy_remote_md5(self, filename): return self.fs.checksum(filename) def file_copy_remote_exists(self, src, dest=None): if dest is None: dest = os.path.basename(src) local_hash = self._file_copy_local_md5(src) remote_hash = self._file_copy_remote_md5(dest) if local_hash is not None: if local_hash == remote_hash: return True return False def file_copy(self, src, dest=None): if dest is None: dest = os.path.basename(src) with SCP(self.native) as scp: scp.put(src, remote_path=dest) def get_boot_options(self): return self.facts['os_version'] def set_boot_options(self, sys): raise NotImplementedError def reboot(self, timer=0, confirm=False): if confirm: self.sw.reboot(in_min=timer) else: print('Need to confirm reboot with confirm=True') @property def running_config(self): return self.show('show config') def save(self, filename=None): if filename is None: self.cu.commit() return temp_file = NamedTemporaryFile() temp_file.write(self.show('show config')) temp_file.flush() with SCP(self.native) as scp: scp.put(temp_file.name, remote_path=filename) temp_file.close() return True @property def startup_config(self): return self.show('show config')
class Netconf(object): def __init__(self): if not HAS_PYEZ: raise NetworkError( msg= 'junos-eznc >= 1.2.2 is required but does not appear to be installed. ' 'It can be installed using `pip install junos-eznc`') if not HAS_JXMLEASE: raise NetworkError( msg='jxmlease is required but does not appear to be installed. ' 'It can be installed using `pip install jxmlease`') self.device = None self.config = None self._locked = False self._connected = False self.default_output = 'xml' def raise_exc(self, msg): if self.device: if self._locked: self.config.unlock() self.disconnect() raise NetworkError(msg) def connect(self, params, **kwargs): host = params['host'] kwargs = dict() kwargs['port'] = params.get('port') or 830 kwargs['user'] = params['username'] if params['password']: kwargs['passwd'] = params['password'] if params['ssh_keyfile']: kwargs['ssh_private_key_file'] = params['ssh_keyfile'] kwargs['gather_facts'] = False try: self.device = Device(host, **kwargs) self.device.open() except ConnectError: exc = get_exception() self.raise_exc('unable to connect to %s: %s' % (host, str(exc))) self.config = Config(self.device) self._connected = True def disconnect(self): try: self.device.close() except AttributeError: pass self._connected = False ### Command methods ### def run_commands(self, commands): responses = list() for cmd in commands: meth = getattr(self, cmd.args.get('command_type')) responses.append(meth(str(cmd), output=cmd.output)) for index, cmd in enumerate(commands): if cmd.output == 'xml': responses[index] = etree.tostring(responses[index]) elif cmd.args.get('command_type') == 'rpc': responses[index] = str(responses[index].text).strip() return responses def cli(self, commands, output='xml'): '''Send commands to the device.''' try: return self.device.cli(commands, format=output, warning=False) except (ValueError, RpcError): exc = get_exception() self.raise_exc('Unable to get cli output: %s' % str(exc)) def rpc(self, command, output='xml'): name, kwargs = rpc_args(command) meth = getattr(self.device.rpc, name) reply = meth({'format': output}, **kwargs) return reply ### Config methods ### def get_config(self, config_format="text"): if config_format not in SUPPORTED_CONFIG_FORMATS: self.raise_exc(msg='invalid config format. Valid options are ' '%s' % ', '.join(SUPPORTED_CONFIG_FORMATS)) ele = self.rpc('get_configuration', output=config_format) if config_format == 'text': return str(ele.text).strip() else: return ele def load_config(self, config, commit=False, replace=False, confirm=None, comment=None, config_format='text'): if replace: merge = False overwrite = True else: merge = True overwrite = False if overwrite and config_format == 'set': self.raise_exc( 'replace cannot be True when config_format is `set`') self.lock_config() try: candidate = '\n'.join(config) self.config.load(candidate, format=config_format, merge=merge, overwrite=overwrite) except ConfigLoadError: exc = get_exception() self.raise_exc('Unable to load config: %s' % str(exc)) diff = self.config.diff() self.check_config() if all((commit, diff)): self.commit_config(comment=comment, confirm=confirm) self.unlock_config() return diff def save_config(self): raise NotImplementedError ### end of Config ### def get_facts(self, refresh=True): if refresh: self.device.facts_refresh() return self.device.facts def unlock_config(self): try: self.config.unlock() self._locked = False except UnlockError: exc = get_exception() raise NetworkError('unable to unlock config: %s' % str(exc)) def lock_config(self): try: self.config.lock() self._locked = True except LockError: exc = get_exception() raise NetworkError('unable to lock config: %s' % str(exc)) def check_config(self): if not self.config.commit_check(): self.raise_exc(msg='Commit check failed') def commit_config(self, comment=None, confirm=None): try: kwargs = dict(comment=comment) if confirm and confirm > 0: kwargs['confirm'] = confirm return self.config.commit(**kwargs) except CommitError: exc = get_exception() raise NetworkError('unable to commit config: %s' % str(exc)) def confirm_commit(self, checkonly=False): try: resp = self.rpc('get_commit_information') needs_confirm = 'commit confirmed, rollback' in resp[0][4].text if checkonly: return needs_confirm return self.commit_config() except IndexError: # if there is no comment tag, the system is not in a commit # confirmed state so just return pass def rollback_config(self, identifier, commit=True, comment=None): self.lock_config() try: self.config.rollback(identifier) except ValueError: exc = get_exception() self.raise_exc('Unable to rollback config: $s' % str(exc)) diff = self.config.diff() if commit: self.commit_config(comment=comment) self.unlock_config() return diff
from sys import exit from lxml import etree from jnpr.junos import Device from jnpr.junos.utils.config import Config VerizonDevice = raw_input( 'Enter Hostname or IP address of Device under test: ') dev = Device(host=VerizonDevice, user='******', password='******').open() class style: BOLD = '\033[1m' END = '\033[0m' bgppeer = dev.cli('show bgp summary') print bgppeer peertable = {} counter = 0 with open("Peer-Device-Master-Table.txt", "r") as peerfile: for line in peerfile: line = line.strip().lower() if line in bgppeer: peertable[counter] = line counter = counter + 1 print peertable
class Netconf(object): def __init__(self): if not HAS_PYEZ: raise NetworkError( msg='junos-eznc >= 1.2.2 is required but does not appear to be installed. ' 'It can be installed using `pip install junos-eznc`' ) if not HAS_JXMLEASE: raise NetworkError( msg='jxmlease is required but does not appear to be installed. ' 'It can be installed using `pip install jxmlease`' ) self.device = None self.config = None self._locked = False self._connected = False self.default_output = 'xml' def raise_exc(self, msg): if self.device: if self._locked: self.config.unlock() self.disconnect() raise NetworkError(msg) def connect(self, params, **kwargs): host = params['host'] kwargs = dict() kwargs['port'] = params.get('port') or 830 kwargs['user'] = params['username'] if params['password']: kwargs['passwd'] = params['password'] if params['ssh_keyfile']: kwargs['ssh_private_key_file'] = params['ssh_keyfile'] kwargs['gather_facts'] = False try: self.device = Device(host, **kwargs) self.device.open() except ConnectError: exc = get_exception() self.raise_exc('unable to connect to %s: %s' % (host, str(exc))) self.config = Config(self.device) self._connected = True def disconnect(self): try: self.device.close() except AttributeError: pass self._connected = False ### Command methods ### def run_commands(self, commands): responses = list() for cmd in commands: meth = getattr(self, cmd.args.get('command_type')) responses.append(meth(str(cmd), output=cmd.output)) for index, cmd in enumerate(commands): if cmd.output == 'xml': responses[index] = xml_to_json(responses[index]) elif cmd.args.get('command_type') == 'rpc': responses[index] = str(responses[index].text).strip() elif 'RpcError' in responses[index]: raise NetworkError(responses[index]) return responses def cli(self, commands, output='xml'): '''Send commands to the device.''' try: return self.device.cli(commands, format=output, warning=False) except (ValueError, RpcError): exc = get_exception() self.raise_exc('Unable to get cli output: %s' % str(exc)) def rpc(self, command, output='xml'): name, kwargs = rpc_args(command) meth = getattr(self.device.rpc, name) reply = meth({'format': output}, **kwargs) return reply ### Config methods ### def get_config(self, config_format="text"): if config_format not in SUPPORTED_CONFIG_FORMATS: self.raise_exc(msg='invalid config format. Valid options are ' '%s' % ', '.join(SUPPORTED_CONFIG_FORMATS)) ele = self.rpc('get_configuration', output=config_format) if config_format == 'text': return unicode(ele.text).strip() else: return ele def load_config(self, config, commit=False, replace=False, confirm=None, comment=None, config_format='text', overwrite=False): if all([replace, overwrite]): self.raise_exc('setting both replace and overwrite to True is invalid') if replace: merge = False overwrite = False elif overwrite: merge = True overwrite = False else: merge = True overwrite = False if overwrite and config_format == 'set': self.raise_exc('replace cannot be True when config_format is `set`') self.lock_config() try: candidate = '\n'.join(config) self.config.load(candidate, format=config_format, merge=merge, overwrite=overwrite) except ConfigLoadError: exc = get_exception() self.raise_exc('Unable to load config: %s' % str(exc)) diff = self.config.diff() self.check_config() if all((commit, diff)): self.commit_config(comment=comment, confirm=confirm) self.unlock_config() return diff def save_config(self): raise NotImplementedError ### end of Config ### def get_facts(self, refresh=True): if refresh: self.device.facts_refresh() return self.device.facts def unlock_config(self): try: self.config.unlock() self._locked = False except UnlockError: exc = get_exception() raise NetworkError('unable to unlock config: %s' % str(exc)) def lock_config(self): try: self.config.lock() self._locked = True except LockError: exc = get_exception() raise NetworkError('unable to lock config: %s' % str(exc)) def check_config(self): if not self.config.commit_check(): self.raise_exc(msg='Commit check failed') def commit_config(self, comment=None, confirm=None): try: kwargs = dict(comment=comment) if confirm and confirm > 0: kwargs['confirm'] = confirm return self.config.commit(**kwargs) except CommitError: exc = get_exception() raise NetworkError('unable to commit config: %s' % str(exc)) def confirm_commit(self, checkonly=False): try: resp = self.rpc('get_commit_information') needs_confirm = 'commit confirmed, rollback' in resp[0][4].text if checkonly: return needs_confirm return self.commit_config() except IndexError: # if there is no comment tag, the system is not in a commit # confirmed state so just return pass def rollback_config(self, identifier, commit=True, comment=None): self.lock_config() try: self.config.rollback(identifier) except ValueError: exc = get_exception() self.raise_exc('Unable to rollback config: $s' % str(exc)) diff = self.config.diff() if commit: self.commit_config(comment=comment) self.unlock_config() return diff
from jnpr.junos import Device from jnpr.junos.utils.config import Config from jnpr.junos.utils.sw import SW import sys dev = Device('host', user='******', password='******') dev.open() print "===========Setting the configuration===========" cu = Config(dev) #rsp = cu.load( path="config-example.conf" ) config_set = """set system extensions providers juniper license-type juniper deployment-scope commercial""" cu.load(config_set, format="set", merge=True) cu.commit(comment="===========Set the configuration successfully===========") print dev.cli("show configuration system extensions providers", warning=False) cu.rollback(rb_id=1) cu.commit(detail=True) print dev.cli("show configuration system extensions providers", warning=False)