def run(self): self.logfile = open(os.getcwd() + '/' + 'linkfailure_log', 'a') while True: while self.failed() == False: time.sleep(1) # select a router r_number = random.randint(1,len(self.rtr)) - 1 # select a random interface i_number = random.randint(1, len(self.rtr[r_number]['interfaces'])) - 1 #set interfaces ge-1/0/3 disable cmd = 'set interfaces ' + self.rtr[r_number]['interfaces'][i_number]['name'] + ' disable' dev = Device(host=self.rtr[r_number]['ip'], user='******', password='******') dev.open() dev.timeout = 60 cu = Config(dev) cu.lock() cu.load(cmd, format='set', merge=True) cu.commit() cu.unlock() dev.close() link__data = { 'status': 'failed', 'timestamp': datetime.datetime.fromtimestamp(time.time()).strftime('%a:%H:%M:%S'), 'router_id': self.rtr[r_number]['router_id'], 'router_name': self.rtr[r_number]['name'], 'interface_address': self.rtr[r_number]['interfaces'][i_number]['address'], 'interface_name': self.rtr[r_number]['interfaces'][i_number]['name'] } jd = json.dumps(link__data) self.redis.publish('link_event', jd) self.logfile.write("Link failed: " + datetime.datetime.fromtimestamp(time.time()).strftime('%a:%H:%M:%S') + " " + self.rtr[r_number]['name'] + " " + self.rtr[r_number]['ip'] + " " + self.rtr[r_number]['interfaces'][i_number]['name'] + "\n") self.logfile.flush() # now repair the link while self.repaired() == False: time.sleep(1) cmd = 'delete interfaces ' + self.rtr[r_number]['interfaces'][i_number]['name'] + ' disable' dev = Device(host=self.rtr[r_number]['ip'], user='******', password='******') dev.open() dev.timeout = 60 cu = Config(dev) cu.lock() cu.load(cmd, format='set', merge=True) cu.commit() cu.unlock() dev.close() link__data = { 'status': 'healed', 'timestamp': datetime.datetime.fromtimestamp(time.time()).strftime('%a:%H:%M:%S'), 'router_id': self.rtr[r_number]['router_id'], 'router_name': self.rtr[r_number]['name'], 'interface_address': self.rtr[r_number]['interfaces'][i_number]['address'], 'interface_name': self.rtr[r_number]['interfaces'][i_number]['name'] } jd = json.dumps(link__data) self.redis.publish('link_event', jd) self.logfile.write("Link healed: " + datetime.datetime.fromtimestamp(time.time()).strftime('%a:%H:%M:%S') + " " + self.rtr[r_number]['name'] + " " + self.rtr[r_number]['ip'] + " " + self.rtr[r_number]['interfaces'][i_number]['name'] + "\n") self.logfile.flush()
class JuniperObject(object): def __init__(self, jnp_dev): self.conn = jnp_dev self.config = None self.ports = {} self.routes = {} def __get_ports(self): self.ports = EthPortTable(self.conn) self.ports.get() def __get_routes(self): self.routes = RouteTable(self.conn) self.routes.get() def config_mode(self): self.config = Config(self.conn) self.config.lock() def send_command(self, command, cmd_format, cmd_merge): self.config.load(command, format=cmd_format, merge=cmd_merge) def file_command(self, file_path, file_format, file_merge): self.config.load(path=file_path, format=file_format, merge=file_merge) def get_diff(self): return self.config.diff() def commit(self, comment=None): self.config.commit(comment=comment) def rollback(self): self.config.rollback(0) def unlock(self): self.config.unlock() def show_all_interfaces(self): self.__get_ports() print "Juniper SRX Interface Statistics" for my_key in self.ports.keys(): print "---------------------------------" print my_key + ":" print "Operational Status: " + self.ports[my_key]['oper'] print "Packets In: " + self.ports[my_key]['rx_packets'] print "Packets Out: " + self.ports[my_key]['tx_packets'] def show_all_routes(self): self.__get_routes() print "Juniper SRX Routing Table" for my_key in self.routes.keys(): print "---------------------------------" print my_key + ":" print " Next Hop: {}".format(self.routes[my_key]['nexthop']) print " Age: {}".format(self.routes[my_key]['age']) print " via: {}".format(self.routes[my_key]['via']) print " Protocol: {}".format(self.routes[my_key]['protocol'])
def process_device(ip, **kwargs): dev = Device(host=ip, **kwargs) cu = Config(dev) print "Searching for active sessions on Device:", ip, "matching the following criteria" + '\n\n\t' + "Destination IP-Address:" + '\t' + destip + '\n\t' + "Destination-Port:" + '\t' + dport + '\n\t' + "Application:" + '\t\t' + application + '\n' try: dev.open() cluster_status = ClusterStatus(dev) cluster_status.get() session_table = SessionTable(dev) session_table.get() found = 'f' cluster = 'a' cu.lock() for c in cluster_status: if cluster_status.keys(): print "SRX Cluster has redundancy-group", c.redundancy_group_id if not cluster_status.keys(): print "Clustering is not Enabled" for s in session_table: if session_table.keys() and s.in_destination_address == destip and s.in_destination_port == dport and s.in_session_protocol == application: found = 't' print "Found Session on", ip, s.re_name + '\n\n\t' + "Source-Address:" + '\t' + s.in_source_address +'\n\t' + "Session-Id:" + '\t' + s.session_identifier + '\n\n' + "Creating Address-entry on Device:", ip + '\n\n' + "Clearing active session" + '\n\t' + "Session-Id:" + '\t' + s.session_identifier + '\n\t' + "Cluster-Node:" + '\t' + s.re_name + '\n' block_src = {'Address': s.in_source_address} jinja_data = open("jinjafile.conf", "wb") jinja_data.write(JinjaTemplate.render(**block_src)) jinja_data.close() rsp = cu.load( template_path="jinjafile.conf", merge=True ) clearflow = dev.rpc.clear_flow_session(destination_prefix=s.in_destination_address, source_prefix=s.in_source_address, destination_port=s.in_destination_port, protocol=s.in_session_protocol) cu.commit() cu.unlock() if found == 'f': print "No Active Sessions were found with the following criteria:" + '\n\n\t' + "Destination IP-Address:" + '\t' + destip + '\n\t' + "Destination Port:" + '\t' + dport +'\n\t' + "Application:" + '\t\t' + application + '\n' except RpcError: msg = "{0} was Skipped due to RPC Error. Device is not a Juniper SRX Series".format(ip.rstrip()) print msg dev.close() except Exception as err: msg = "{0} was skipped due to unhandled exception.\n{1}".format(ip.rstrip(), err) print msg traceback.print_exc(file=sys.stdout) dev.close()
def updateDeviceConfiguration(self): ''' Device Connection should be open by now, no need to connect again ''' logger.debug('updateDeviceConfiguration for %s' % (self.deviceLogStr)) l3ClosMediation = L3ClosMediation(conf = self._conf) config = l3ClosMediation.createLeafConfigFor2Stage(self.device) # l3ClosMediation used seperate db sessions to create device config # expire device from current session for lazy load with committed data self._session.expire(self.device) configurationUnit = Config(self.deviceConnectionHandle) try: configurationUnit.lock() logger.debug('Lock config for %s' % (self.deviceLogStr)) except LockError as exc: logger.error('updateDeviceConfiguration failed for %s, LockError: %s, %s, %s' % (self.deviceLogStr, exc, exc.errs, exc.rpc_error)) raise DeviceError(exc) try: # make sure no changes are taken from CLI candidate config left over configurationUnit.rollback() logger.debug('Rollback any other config for %s' % (self.deviceLogStr)) configurationUnit.load(config, format='text') logger.debug('Load generated config as candidate, for %s' % (self.deviceLogStr)) #print configurationUnit.diff() #print configurationUnit.commit_check() configurationUnit.commit() logger.info('Committed twoStage config for %s' % (self.deviceLogStr)) except CommitError as exc: #TODO: eznc Error handling is not giving helpful error message logger.error('updateDeviceConfiguration failed for %s, CommitError: %s, %s, %s' % (self.deviceLogStr, exc, exc.errs, exc.rpc_error)) configurationUnit.rollback() raise DeviceError(exc) except Exception as exc: logger.error('updateDeviceConfiguration failed for %s, %s' % (self.deviceLogStr, exc)) logger.debug('StackTrace: %s' % (traceback.format_exc())) configurationUnit.rollback() raise DeviceError(exc) finally: configurationUnit.unlock() logger.debug('Unlock config for %s' % (self.deviceLogStr))
def updateDeviceConfiguration(self): ''' Device Connection should be open by now, no need to connect again ''' logger.debug('updateDeviceConfiguration for %s' % (self.deviceLogStr)) config = self.getDeviceConfig() configurationUnit = Config(self.deviceConnectionHandle) try: configurationUnit.lock() logger.debug('Lock config for %s' % (self.deviceLogStr)) except LockError as exc: logger.error('updateDeviceConfiguration failed for %s, LockError: %s, %s, %s' % (self.deviceLogStr, exc, exc.errs, exc.rpc_error)) raise DeviceRpcFailed('updateDeviceConfiguration failed for %s' % (self.deviceLogStr), exc) try: # make sure no changes are taken from CLI candidate config left over configurationUnit.rollback() logger.debug('Rollback any other config for %s' % (self.deviceLogStr)) configurationUnit.load(config, format='text') logger.debug('Load generated config as candidate, for %s' % (self.deviceLogStr)) #print configurationUnit.diff() #print configurationUnit.commit_check() configurationUnit.commit() logger.info('Committed twoStage config for %s' % (self.deviceLogStr)) except CommitError as exc: #TODO: eznc Error handling is not giving helpful error message logger.error('updateDeviceConfiguration failed for %s, CommitError: %s, %s, %s' % (self.deviceLogStr, exc, exc.errs, exc.rpc_error)) configurationUnit.rollback() raise DeviceRpcFailed('updateDeviceConfiguration failed for %s' % (self.deviceLogStr), exc) except Exception as exc: logger.error('updateDeviceConfiguration failed for %s, %s' % (self.deviceLogStr, exc)) logger.debug('StackTrace: %s' % (traceback.format_exc())) configurationUnit.rollback() raise DeviceRpcFailed('updateDeviceConfiguration failed for %s' % (self.deviceLogStr), exc) finally: configurationUnit.unlock() logger.debug('Unlock config for %s' % (self.deviceLogStr))
def main(): ''' Main function ''' a_device = remote_conn(HOST, USER, PWD) if not a_device: sys.exit('Fix the above errors. Exiting...') print a_device.facts cfg = Config(a_device) cfg.lock() print 'Set hostname using set format' set_hostname(cfg, 'pytest-gmaz', 'set') print 'Show differences' print cfg.diff() print 'Rollback' cfg.rollback(0) print 'Check if rollback is ok' print cfg.diff() print 'Set hostname using cfg file' set_hostname(cfg, 'hostname.conf', 'text') print 'Show differences' print cfg.diff() print 'Commit' cfg.commit(comment='Text hostname commit by gmazioli') print 'Set hostname using external XML' set_hostname(cfg, 'hostname.xml', 'xml') print 'Show differences' print cfg.diff() print 'Commit' cfg.commit(comment='XML hostname commit by gmazioli') print 'Reverting changes and doing the final commit' set_hostname(cfg, 'pynet-jnpr-srx1', 'set') cfg.commit(comment='System commit by gmazioli') cfg.unlock()
def main(): ''' I will test the case with applying config for 1 minute ''' pwd = getpass() ip_addr = raw_input('''Enter Juniper SRX IP"(184.105.247.76)": ''') ip_addr = ip_addr.strip() juniper_srx = { "host": ip_addr, "user": "******", "password": pwd } try: a_device = Device(**juniper_srx) a_device.open() cfg = Config(a_device) cfg.lock() cfg.load(path="exercice4_config.xml" , format="xml", merge=True) print "#"*80 print "Displaying the differences between the running config and the candidate config:" print "#"*80 cfg.pdiff() print "+"*80 print "Applying config" print "+"*80 cfg.commit(comment="Applying config from exercice4_config.xml") print "-"*80 print "reverting config back" cfg.rollback(1) cfg.pdiff() cfg.commit() print "-"*80 print "\n"*2 print except: print print "Authentication Error" print
# Establish the NETCONF connection device_conn.open() # Call the gather_routes function to get the routing tale of the device old_routing_table = gather_routes() # Print the routing table print("Routing table before the change") pprint(old_routing_table) print('-' * 40) # Exercise 4b # Increase the timeout device_conn.timeout = 60 # Pass NETCONRF connection into Config Object cnfg = Config(device_conn) # Lock configuration exclusively to us cnfg.lock() # Load configuration from external file in curly brace notation cnfg.load(path='routing.conf', format='text', merge=True) # Commit the configuration cnfg.commit() # Exercise 4c new_routing_table = gather_routes() # Print the routing table after the change so we can compare print("Routing table after the change") pprint(new_routing_table) # Print the differences in the routing table new_routing_table = dict(new_routing_table) print('-' * 40) print("The new entries in the routing table are: ")
#!/usr/bin/python from jnpr.junos import Device from jnpr.junos.utils.config import Config dev = Device() dev.open() config_set = """ set interfaces xe-0/0/9 disable set interfaces xe-0/0/10 disable set interfaces xe-0/0/11 disable """ cu = Config(dev) cu.lock() cu.load(config_set, format="set", merge=True) cu.commit() cu.unlock() dev.close()
for host in devices: print("\n - - - - - -\n Proceeding with device : " + host) #dev=Device(host=host, user=login, password=pwd, gather_facts=False) dev = Device(host=host, user=login, password=pwd) try: dev.open() except jnpr.junos.exception.ConnectAuthError as error: print('\n Could not authenticate') exit() #pprint(dev.facts) cfg = Config(dev) # Execute Rollback to prevent commit change from old config session # We prefer to raise a LockError is config is not clean #cfg.rollback() try: cfg.lock() #ask for configure exclusive except jnpr.junos.exception.LockError as error: print('\nCould not set configure exclusive lock :') print(error.message) exit() try: cfg.load(path="junos.conf", format='set') except jnpr.junos.exception.ConfigLoadError as error: print('\nthere were some errors/warnings while loading the config :') print(error.message) print(cfg.pdiff()) commit = raw_input("Commit? (y/N)") if commit in ["y", "Y", "Yes", "yes"]: try: cfg.commit(comment=comment) cfg.unlock()
from jnpr.junos import Device from jnpr.junos.utils.config import Config from pprint import pprint junos_hosts = ['192.168.56.15'] for ip in junos_hosts: dev = Device(host=ip, user='******', password='******') dev.open() config = Config(dev) config.lock() config.rollback(rb_id=1) config.pdiff() config.commit() config.unlock() dev.close()
class TestConfig(unittest.TestCase): @patch('ncclient.manager.connect') def setUp(self, mock_connect): mock_connect.side_effect = self._mock_manager self.dev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.dev.open() self.conf = Config(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm_true(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=True) self.conf.rpc.commit_configuration\ .assert_called_with(confirmed=True) def test_config_commit_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') def test_config_commit_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(synchronize=True) def test_config_commit_force_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(force_sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(**{'synchronize': True, 'force-synchronize': True}) def test_config_commit_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(timeout=60) self.conf.rpc.commit_configuration\ .assert_called_with(dev_timeout=60) def test_config_commit_full(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(full=True) self.conf.rpc.commit_configuration\ .assert_called_with(full=True) def test_config_commit_detail(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<mockdetail/>' self.assertEqual('<mockdetail/>', self.conf.commit(detail=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}) def test_config_commit_combination(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<moredetail/>' self.assertEqual( '<moredetail/>', self.conf.commit( detail=True, force_sync=True, full=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}, **{'synchronize': True, 'full': True, 'force-synchronize': True}) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_xml_exception(self, mock_jxml): class MyException(Exception): xml = etree.fromstring('<test/>') self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(CommitError, self.conf.commit) def test_config_commit_exception(self): class MyException(Exception): pass self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(MyException, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with( {'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_diff_exception_severity_warning(self): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>mgd: statement must contain additional statements</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) self.conf.rpc.get_configuration = MagicMock( side_effect=RpcError(rsp=rsp)) self.assertEqual(self.conf.diff(), "Unable to parse diff from response!") def test_config_diff_exception_severity_warning_still_raise(self): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>statement not found</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) self.conf.rpc.get_configuration = MagicMock( side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, self.conf.diff) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format_set(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') def test_config_load_len_with_format_xml(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') xmldata = """<snmp> <community> <name>iBGP</name> </community> </snmp>""" self.assertEqual(self.conf.load(xmldata, format='xml'), 'rpc_contents') def test_config_load_len_with_format_text(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') textdata = """policy-options { prefix-list TEST1-NETS { 100.0.0.0/24; } policy-statement TEST1-NETS { term TEST1 { from { prefix-list TEST1-NETS; } then accept; } term REJECT { then reject; } } }""" self.assertEqual(self.conf.load(textdata), 'rpc_contents') def test_config_load_with_format_json(self): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load('test.json', format='json') self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') @patch(builtin_string + '.open') def test_config_load_with_format_json_from_file_ext(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path='test.json') self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') @patch(builtin_string + '.open') def test_config_load_update(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path='test.conf', update=True) self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_update_merge_overwrite(self): self.assertRaises(ValueError, self.conf.load, path='test.jnpr', update=True, merge=True, overwrite=True) @patch(builtin_string + '.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch(builtin_string + '.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch(builtin_string + '.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch(builtin_string + '.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') @patch(builtin_string + '.open') def test_config_load_try_load_rpcerror(self, mock_open): ex = ConfigLoadError( rsp=etree.fromstring(( """<load-configuration-results> <rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error> </load-configuration-results>"""))) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(ConfigLoadError, self.conf.load, path='config.conf') @patch(builtin_string + '.open') def test_config_load_try_load_rpctimeouterror(self, mock_open): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.load, path='config.conf') @patch(builtin_string + '.open') def test_config_try_load_exception(self, mock_open): class OtherException(Exception): pass self.conf.rpc.load_config = MagicMock(side_effect=OtherException()) self.assertRaises(OtherException, self.conf.load, path='config.conf') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_template_path(self, mock_etree): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock(return_value='<test/>') self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1) @patch('jnpr.junos.Device.execute') def test_rescue_action_save(self, mock_exec): self.dev.request_save_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('save')) @patch('jnpr.junos.Device.execute') def test_rescue_action_get_exception(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock(side_effect=Exception) self.assertTrue(self.conf.rescue('get') is None) @patch('jnpr.junos.Device.execute') def test_rescue_action_get(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock() self.dev.rpc.get_rescue_information.return_value = 1 self.assertEqual(self.conf.rescue('get', format='xml'), 1) @patch('jnpr.junos.Device.execute') def test_rescue_action_delete(self, mock_exec): self.dev.rpc.request_delete_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('delete')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload(self, mock_exec): self.dev.rpc.load_configuration = MagicMock() self.dev.rpc.load_configuration.return_value = True self.assertTrue(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload_exception(self, mock_exec): self.dev.rpc.load_configuration = MagicMock(side_effect=Exception) self.assertFalse(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_unsupported_action(self, mock_exec): self.assertRaises(ValueError, self.conf.rescue, 'abc') def test_config_load_lset_from_rexp_xml(self): self.conf.rpc.load_config = MagicMock() conf = """<snmp><name>iBGP</name></snmp>""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_lset_from_rexp_json(self): self.conf.rpc.load_config = MagicMock() conf = """{ "configuration" : { "system" : { "services" : { "telnet" : [null] } } } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') def test_config_load_lset_from_rexp_set(self): self.conf.rpc.load_config = MagicMock() conf = """set system domain-name englab.nitin.net""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_delete(self): self.conf.rpc.load_config = MagicMock() conf = """delete snmp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_conf(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_lset_from_rexp_conf_replace_tag(self): self.conf.rpc.load_config = MagicMock() conf = """replace: snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'replace') def test_config_load_lset_from_rexp_error(self): self.conf.rpc.load_config = MagicMock() conf = """test>""" self.assertRaises(RuntimeError, self.conf.load, conf) def test_load_merge_true(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf, merge=True) self.assertFalse('action' in self.conf.rpc.load_config.call_args[1]) def test_commit_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit) def test_commit_check_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit_check) def test_commit_configuration_multi_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) try: self.dev.rpc.commit_configuration() except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) if ncclient.__version__ > (0, 4, 5): self.assertEqual(ex.message, "error: interface-range 'axp' is not defined\n" "error: interface-ranges expansion failed") self.assertEqual(ex.errs, [{'source': None, 'message': "interface-range 'axp' is not defined", 'bad_element': None, 'severity': 'error', 'edit_path': None}, {'source': None, 'message': 'interface-ranges expansion failed', 'bad_element': None, 'severity': 'error', 'edit_path': None}]) else: self.assertEqual(ex.message, "interface-range 'axp' is not defined") @patch('jnpr.junos.utils.config.Config.lock') @patch('jnpr.junos.utils.config.Config.unlock') def test_config_mode_exclusive(self, mock_unlock, mock_lock): with Config(self.dev, mode='exclusive') as conf: conf.rpc.load_config = MagicMock() conf.load('conf', format='set') self.assertTrue(mock_lock.called and mock_unlock.called) @patch('jnpr.junos.Device.execute') def test_config_mode_batch(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch('jnpr.junos.Device.execute') def test_config_mode_private(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='private') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(private=True) @patch('jnpr.junos.Device.execute') def test_config_mode_dynamic(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='dynamic') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(dynamic=True) @patch('jnpr.junos.Device.execute') def test_config_mode_close_configuration_ex(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() ex = RpcError(rsp='ok') ex.message = 'Configuration database is not open' self.dev.rpc.close_configuration = MagicMock(side_effect=ex) try: with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) self.assertTrue(self.dev.rpc.close_configuration.called) @patch('jnpr.junos.Device.execute') def test_config_mode_undefined(self, mock_exec): try: with Config(self.dev, mode='unknown') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, ValueError)) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.utils.config.warnings') def test_config_mode_batch_open_configuration_ex(self, mock_warnings, mock_exec): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.utils.config.warnings') def test_config_mode_private_open_configuration_ex(self, mock_warnings, mock_exec): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode='private') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(private=True) def test__enter__private_exception_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.open_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, Config.__enter__, Config(self.dev, mode='private')) def test__enter__private_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='private')) def test__enter__dyanamic_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='dynamic')) def test__enter__batch_exception_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.open_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, Config.__enter__, Config(self.dev, mode='batch')) def test__enter__batch_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='batch')) def _read_file(self, fname): fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() # specific to multi rpc error if fname == 'commit-configuration.xml': raw = etree.XML(foo) obj = RPCReply(raw) obj.parse() if ncclient.__version__ > (0, 4, 5): raise RPCError(etree.XML(foo), errs=obj._errors) else: raise RPCError(etree.XML(foo)) def _mock_manager(self, *args, **kwargs): if kwargs: device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: return self._read_file(args[0].tag + '.xml')
def rm_config(dev): cfg = Config(dev) cfg.lock() cfg.load(path=rmconfigfile, format="text", merge=True) cfg.commit() cfg.unlock()
from jnpr.junos.utils.config import Config dev = Device(host="10.117.97.39", user="******") conf = Config(dev) config = """ system { name-server { 8.8.5.5; 8.8.3.3; } } """ dev.open() conf.lock() conf.load(config, format="text") if ( conf.commit_check() & (conf.diff() is not None) ): print ("Configuration is valid and applied") conf.pdiff() conf.commit() elif ( conf.commit_check() & (conf.diff() is None) ): print ("Configuration is already thier, nothing to be added!") else: print ("Configuration is NOT valid and rollback issued") conf.rollback() conf.unlock() dev.close()
def push_conf_func(config): """ This code will first access the remote router via SSH and then use Juniper Pyez to push config """ # print("Trying to access router now......") try: a_device = Device(host="66.129.235.11", user="******", password="******", port="39000") a_device.open() cfg = Config(a_device) print("SSH access to Remote Router successful..") except Exception as e: print(e) print("Error while attempting ssh connection to server") quit() # sys.exit('Error while attempting ssh connection to server') #check router diff before pushing new config if cfg.diff() is None: print("Locking remote router now...") cfg.lock() else: print( "There are some pending diffs to be pushed on remote router. Please review and push. See Below----" ) print(cfg.pdiff()) print("Bye. See you again!!") a_device.close() sys.exit() f1 = open('conf-to-push.conf', 'w') f1.write(config) f1.close() print("\n") print("Below config is now being loaded to remote router") print('~' * 60) print(config) print('~' * 60) print("\n") try: cfg.load(path='conf-to-push.conf', format='set', merge=True) except ConfigLoadError as e: print(e) a_device.close() sys.exit("Error while loading config") print("Please review the diffs carefully") print('~' * 60) pprint(cfg.pdiff()) print('~' * 60) try: diff_push_input = input( "Are these diffs good to be pushed to running config? - Say 'yes or 'no': " ).strip().lower() if (diff_push_input == 'yes'): try: if cfg.commit_check() is True: cfg.commit() print("\nYour config is committed now.\n") else: print(cfg.commit_check()) except Exception as e: print(e) print("Exception while doing commit check") else: print( "\nAlright.. Config is being rolled back now to last pushed config\n" ) cfg.rollback(0) a_device.close() exit(1) except Exception as e: print(e) print("Error in processing commit code") print("Unlocking Remote router now....BYE!!\n") cfg.unlock() a_device.close() exit(1)
class JUNOS(BasePlugin): configuration = None quantity_of_times_to_try_lock = 3 seconds_to_wait_to_try_lock = 10 # Variables defined at networkapi/database alternative_variable_base_path_list = ['path_to_tftpboot'] detailed_log_level_var = 'detailed_junos_log_level' detailed_log_level_used = None alternative_static_base_path_list = ['/mnt/scripts/tftpboot/'] ignore_warning_list = ['statement not found'] def __init__(self, **kwargs): super(JUNOS, self).__init__(connect_port=830, **kwargs) if 'quantity_of_times_to_try_lock' in kwargs: self.quantity_of_times_to_try_lock = kwargs.get('quantity_of_times_to_try_lock') if 'seconds_to_wait_to_try_lock' in kwargs: self.seconds_to_wait_to_try_lock = kwargs.get('seconds_to_wait_to_try_lock') # Logger objects to be disabled. Remove or add objects to array below: loggers = [device_logger, ssh_logger, session_logger, rpc_logger] detailed_log_level_used = self.set_detailed_junos_log_level(loggers) log.info("Detailed Junos log level: {}".format(detailed_log_level_used)) def connect(self): """ Connects to equipment via ssh using PyEz and create connection with invoked shell object. :returns: True on success or raise an exception on any fail (will NOT return a false result, due project decision). """ if self.equipment_access is None: try: # Collect the credentials (user and password) for equipment self.equipment_access = EquipamentoAcesso.search(None, self.equipment, 'ssh').uniqueResult() except Exception as e: message = "Unknown error while accessing equipment {} in database.".format( self.equipment.nome) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message) log.info("Trying to connect on host {} ... ".format(self.equipment_access.fqdn)) try: self.remote_conn = Device( host=self.equipment_access.fqdn, user=self.equipment_access.user, passwd=self.equipment_access.password, port=self.connect_port) self.remote_conn.open() self.configuration = Config(self.remote_conn) if self.remote_conn.connected: log.info("The connection on host {} was opened successfully!".format(self.equipment_access.fqdn)) return True except ConnectError as e: message = "Authentication failed trying to connect host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.ConnectionException(message) except Exception as e: message = "Unknown error while connecting to host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message) def close(self): """ Disconnect to equipment via ssh using PyEz. :returns: True on success or raise an exception on any fail (will NOT return a false result, due project decision). """ log.info("Trying to close connection on host {} ... ".format(self.equipment_access.fqdn)) try: if self.remote_conn is not None: self.remote_conn.close() log.info("The connection was closed successfully on host {}!".format(self.equipment_access.fqdn)) return True else: log.warning("To connection couldn't be closed because object is None") except ConnectClosedError as e: message = "Cannot close connection on juniper host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message) except Exception as e: message = "Unknown error while closing connection on host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message) def copyScriptFileToConfig(self, filename, use_vrf='', destination=''): """ Receives the file path (usually in /mnt/scripts/tftpboot/networkapi/generated_config/interface/) where contains the command to be executed in the equipment :param str filename: must contain the full path and file name :param str use_vrf: not used :param str destination: not used :returns: Returns a success message, otherwise, raise an exception. That means will NOT return a false result. """ log.info("Trying to load file configuration for host {} ...".format(self.equipment_access.fqdn)) # 'filename' was defined in super class, but in plugin junos the 'file_path' will be used instead file_path = filename file_path = self.check_configuration_file_exists(file_path) try: command_file = open(file_path, "r") command = command_file.read() log.info("Load configuration from file {} successfully!".format(file_path)) return self.exec_command(command) except IOError as e: self.close() message = "Configuration file not found." # Message to client log.error("{} {}: {}".format(message, file_path, e)) # Message to log raise exceptions.APIException(message) # Caution using generic exception here (like Exception). May cause unexpected exception overlaps def exec_command(self, command, success_regex='', invalid_regex=None, error_regex=None): """ Execute a junos command 'set' in the equipment. :param str command: junos command 'set' :param str success_regex: not used :param str invalid_regex: not used :param str error_regex: not used :returns: Returns a success message, otherwise, raise an exception. That means will NOT return a false result. """ log.info("Trying to execute a configuration on host {} ... ".format(self.equipment_access.fqdn)) try: self.__try_lock() self.configuration.rollback() self.configuration.load(command, format='set', ignore_warning=self.ignore_warning_list) self.configuration.commit_check() self.configuration.commit() self.configuration.unlock() result_message = "Configuration junos was executed successfully on {}".format(self.equipment_access.fqdn) log.info(result_message) return result_message except LockError as e: self.close() message = "Couldn't lock host {}.".format(self.equipment_access.fqdn) log.error("{}: {}".format(message, e)) raise exceptions.APIException(message) except UnlockError as e: message = "Couldn't unlock host {}.".format(self.equipment_access.fqdn) log.error("{} (rollback and close will be tried for safety): {}".format(message, e)) self.configuration.rollback() self.close() raise exceptions.APIException(message) except ConfigLoadError as e: message = "Couldn't load configuration on host {}. Please check template syntax.".format( self.equipment_access.fqdn) log.error("{} (rollback, unlock and close will be tried for safety): {}".format(message, e)) self.configuration.rollback() self.configuration.unlock() self.close() raise exceptions.APIException(message) except CommitError as e: message = "Couldn't commit configuration on host {}.".format(self.equipment_access.fqdn) log.error("{} (rollback, unlock and close will be tried for safety): {}".format(message, e)) self.configuration.rollback() self.configuration.unlock() self.close() raise exceptions.APIException(message) except RpcError as e: message = "A remote procedure call exception occurred on host {} ".format(self.equipment_access.fqdn) log.error("{} (close will be tried for safety): {}".format(message, e)) self.close() raise exceptions.APIException(message) # Caution to use generic exception here, may cause overlaps in specific exceptions in try_lock() # except Exception, e: def ensure_privilege_level(self, privilege_level=None): """ Ensure privilege level verifying if the current user is super-user. :returns: Returns True if success, otherwise, raise an exception (it will NOT return a false result) """ log.info("Trying to ensure privilege level for user {} on host {} ... ".format( self.equipment_access.user, self.equipment_access.fqdn)) try: # timeout: duration of time in seconds must wait for the expected result ss = StartShell(self.remote_conn, timeout=2) ss.open() output = ss.run('cli -c "show cli authorization"') # output is a tuple [bool, string], example: # (False, u'cli -c "show cli authorization"\r\r\nCurrent user: \'root \' class \'super-user\ ....) # This string will be parsed to get the user class: # get the target part and split it by \n result = output[1].split('\n') # get the target part; split by '; and get the target part current_user_class = result[1].split("'")[3] if current_user_class != 'super-user': message = "Couldn't validate user privileges on host {}.".format(self.equipment_access.fqdn) log.error("{}. User {} class is '{}' and need to be 'super-user'" "(close connection will be executed for safety)" .format(message, self.equipment_access.user, current_user_class)) self.close() raise exceptions.APIException(message) else: log.info("The privilege for user {} ('super-user') was satisfied on host {}!".format( self.equipment_access.user, self.equipment_access.fqdn)) return True except Exception as e: message = "Unknown error while verifying user privilege on host {} ".format(self.equipment_access.fqdn) log.error("(close connection will be executed for safety): {}".format(message, e)) self.close() raise exceptions.APIException(message) def __try_lock(self): """ Try to lock equipment. :returns: Returns True if success, otherwise, raise an exception. That means will NOT return a false result. """ log.info("Trying to lock host {} ...".format(self.equipment_access.fqdn)) for x in range(self.quantity_of_times_to_try_lock): try: self.configuration.lock() log.info("Host {} was locked successfully!".format(self.equipment_access.fqdn)) return True except LockError as e: count = x + 1 log.warning( "Host {} could not be locked. Automatic try in {} seconds ({}/{}): {}".format( self.equipment_access.fqdn, self.seconds_to_wait_to_try_lock, count, self.quantity_of_times_to_try_lock, e)) time.sleep(self.seconds_to_wait_to_try_lock) except Exception as e: log.error("Unknown error while trying to lock c the equipment on host {}: {}".format( self.equipment_access.fqdn, e)) message = "Errors occurred in all attempts to lock {}. Anybody has locked?".format(self.equipment_access.fqdn) log.error(message) raise exceptions.APIException(message) def check_configuration_file_exists(self, file_path): """ This function try to find and build (if necessary) the configuration file path. The priorities are: (1) build the full path from system variable base and relative file path ('file_path'); or (2) build the full path from static variable base and relative file path ('file_path'); or (3) return the relative path it self ('file_path') :param str file_path: Relative path, examples: 'networkapi/plugins/Juniper/JUNOS/samples/sample_command.txt' or 'networkapi/generated_config/interface/int-d_24823_config_ROR9BX3ATQG93TALJAMO2G' :return: Return a valid configuration file path string. Ex.: 'networkapi/plugins/Juniper/JUNOS/samples/sample_command.txt' or '/mnt/scripts/tftpboot/networkapi/generated_config/interface/int-d_24823_config_ROR9BX3ATQG93TALJAMO2G' """ log.info("Checking configuration file exist: {}".format(file_path)) # Check in system variables for variable in self.alternative_variable_base_path_list: try: base_path = get_value(variable) if base_path != "": result_path = base_path + file_path if os.path.isfile(result_path): log.info("Configuration file {} was found by system variable {}!".format(result_path, variable)) return result_path except (DatabaseError, VariableDoesNotExistException): # DatabaseError means that variable table do not exist pass except Exception as e: log.warning("Unknown error while calling networkapi.system.facade.get_value({}): {} {} ".format( variable, e.__class__, e)) # Check possible static variables for static_path in self.alternative_static_base_path_list: result_path = static_path + file_path if os.path.isfile(result_path): log.info("Configuration file {} was found by static variable {}!".format(result_path, static_path)) return result_path # Check if relative path is valid (for dev tests) if os.path.isfile(file_path): log.info("Configuration file {} was found by relative path".format(file_path)) return file_path message = "An error occurred while finding configuration file." log.error("{} Could not find in: relative path ('{}'), system variables ({}) or static paths ({})".format( message, file_path, self.alternative_variable_base_path_list, self.alternative_static_base_path_list)) raise exceptions.APIException(message) def set_detailed_junos_log_level(self, loggers): """ Used to disable logs from detailed and specific libs used in Junos plugin, for example: If 'ERROR' is defined, higher log messages will be disabled, like 'WARNING', 'INFO' and 'DEBUG'. :param str loggers: Array of logger objects :return: A valid level error ('ERROR', 'INFO', etc.), otherwise None """ default_log_level = 'ERROR' log_level = None # Trying to get the variable from networkapi. try: log_level = get_value(self.detailed_log_level_var) except DatabaseError as e: log.warning("Database error while getting '{}' variable: {}".format( self.detailed_log_level_var, e)) except VariableDoesNotExistException as e: log.warning("Variable '{}' does not exist: {}".format( self.detailed_log_level_var, e)) except Exception as e: log.warning("Unknown error while getting '{}' variable: {} ".format( self.detailed_log_level_var, e)) # If could not get the value earlier, a default value will be used if log_level is None or log_level == "": log.warning("Could not get '{}' variable from networkapi. ".format( self.detailed_log_level_var, default_log_level)) log_level = default_log_level # Trying to set the level to each log object. for logger in loggers: try: logger.setLevel(log_level) except Exception as e: log.error("Invalid log level '{}'. The default {} will be used: {}".format( log_level, default_log_level, e)) log_level = default_log_level # to be used at next iteration too logger.setLevel(log_level) return log_level
from pprint import pprint from getpass import getpass from jnpr.junos import Device from jnpr.junos.utils.config import Config from jnpr_devices import srx2 device1 = Device(**srx2) device1.open() #Entering Edit mode and locking device" #--------------------------------------- CFG = Config(device1) CFG.lock() from Exercise2 import gather_routes print("\n") print("4a.ROUTE TABLE Before changes") print("-" * 30) k = gather_routes() pprint(k) print("\n") print("4b.stage a configuration from a file") print("-" * 30) CFG.load(path="merge_exercise4.conf", format='text', merge=True) print(CFG.diff()) CFG.commit() print("\n")
def push_config(conf_string, ip, user, pw): dev = get_device_reference(ip, user, pw) # try to determine the format of our config_string config_format = 'set' if re.search(r'^\s*<.*>$', conf_string, re.MULTILINE): config_format = 'xml' elif re.search(r'^\s*(set|delete|replace|rename)\s', conf_string): config_format = 'set' elif re.search(r'^[a-z:]*\s*\w+\s+{', conf_string, re.I) and re.search( r'.*}\s*$', conf_string): config_format = 'text' logger.debug("using format: " + config_format) cu = Config(dev) try: cu.lock() except LockError as le: logger.debug("Could not lock database!") logger.debug(str(le)) dev.close() return False try: cu.load(conf_string, format=config_format) except Exception as e: logger.debug("Could not load configuration") logger.debug(str(e)) dev.close() return False diff = cu.diff() logger.debug(diff) if diff is not None: try: cu.commit_check() logger.debug("Committing config!") cu.commit(comment="Commit via wistar") except CommitError as ce: logger.debug("Could not load config!") cu.rollback() logger.debug(repr(ce)) return False else: # nothing to commit logger.debug("Nothing to commit - no diff found") return True try: logger.debug("Unlocking database!") cu.unlock() except UnlockError as ue: logger.debug("Could not unlock database") logger.debug(str(ue)) return False logger.debug("Closing device handle") dev.close() return True
print_rib(rib_table, "BEFORE") # Inventory Routes before the change ROUTES_BEFORE = list() for k in rib_table.keys(): ROUTES_BEFORE.append(k) # Adding the static routes cfg_static_routes = Config(srx2_device) cfg_static_routes.lock() cfg_static_routes.load(path="static_routes.conf", format="text", merge=True) cfg_static_routes.commit() # Checking the RIB after the change rib_table = gather_routes(srx2_device) print_rib(rib_table, "AFTER") # Inventory Routes after the change
def getdevice(ip_address, username, password): """ Retrieve and return device class. """ device = Device(host=ip_address, user=username, password=password) device.open() return device if __name__ == '__main__': ip_addr = raw_input('Enter IP address: ') user = raw_input('Enter the username: '******'-' * 30 print 'Rollback' myconfig.rollback(0) print "Test using config method" print "-" * 30 myconfig.load(path="test_hostname.conf", format="text", merge=True) print "Print difference" print myconfig.diff()
def toggleAdmin(): switchPort = SwitchPortEntry.get( ) # Get switchport from entrybox in mainWindow if connection is None: monitorInterfaceCheckbox.deselect() TextBoxData.insert(END, "\nPlease logon.\n") else: if switchPort == (''): TextBoxData.insert(END, "\nPlease enter a interface.\n") monitorARPCheckbox.deselect() else: filter = '<interface-information><physical-interface><name/><admin-status/><oper-status/></physical-interface></interface-information>' # limits the ammount of information gathered result = connection.rpc.get_interface_information( interface_name=switchPort, filter_xml=filter) # interfaceInfo = etree.tostring(result, encoding='unicode') splitString = interfaceInfo.splitlines() interfaceUpDown = ('{3}'.format(*splitString)) TextBoxData.insert( END, "\nInterface " + switchPort + " is " + interfaceUpDown) ## Configlets config_disable = ''' interfaces { ''' + switchPort + ''' { disable; } } ''' config_enable = ''' interfaces { ''' + switchPort + ''' { delete: disable; } } ''' ## coniglet used based on port status if interfaceUpDown == "up": TextBoxData.insert(END, ", Disabling interface... \n") commiting() cu = Config(connection) cu.lock() cu.load(config_disable) diff = cu.diff() cu.commit() TextBoxData.insert(END, "Commit complete.\n") cu.unlock() TextBoxData.insert(END, '%s' % (diff)) TextBoxData.see("end") elif interfaceUpDown == "down": TextBoxData.insert(END, ", Enabling interface... \n") commiting() cu = Config(connection) cu.lock() cu.load(config_enable) diff = cu.diff() cu.commit() TextBoxData.insert(END, "Commit complete. \n") cu.unlock() TextBoxData.insert(END, '%s' % (diff)) TextBoxData.see("end") else: TextBoxData.insert(END, "\nERROR\n") TextBoxData.see("end")
from jnpr.junos.utils.config import Config password = os.getenv("JNPR_PASSWORD") if password is None: password = getpass("Enter vMX password: "******"vmx2.lasthop.io", user="******", password=password) my_device.open() # Create device Config object my_device_cfg = Config(my_device) # Lock device configuration my_device_cfg.lock() # Try to acquire Lock again print() try: my_device_cfg.lock() print("Lock acquired!") except LockError: print("Device is already locked.") # Stage a config to change the device hostname my_device_cfg.load("set system host-name test-name", format="set", merge=True) # Check the diff of the staged vs running config print() print("Check diff of staged-config vs running-config")
class TestConfig(unittest.TestCase): def setUp(self): self.dev = Device(host='1.1.1.1') self.conf = Config(self.dev) def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm_true(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=True) self.conf.rpc.commit_configuration\ .assert_called_with(confirmed=True) def test_config_commit_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') def test_config_commit_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(synchronize=True) def test_config_commit_force_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(force_sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(**{'synchronize': True, 'force-synchronize': True}) def test_config_commit_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(timeout=60) self.conf.rpc.commit_configuration\ .assert_called_with(dev_timeout=60) def test_config_commit_full(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(full=True) self.conf.rpc.commit_configuration\ .assert_called_with(full=True) def test_config_commit_detail(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<mockdetail/>' self.assertEqual('<mockdetail/>', self.conf.commit(detail=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}) def test_config_commit_combination(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<moredetail/>' self.assertEqual('<moredetail/>', self.conf.commit(detail=True, force_sync=True, full=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}, **{'synchronize': True, 'full': True, 'force-synchronize': True}) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(AttributeError, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with( {'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format_set(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') def test_config_load_len_with_format_xml(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') xmldata = """<snmp> <community> <name>iBGP</name> </community> </snmp>""" self.assertEqual(self.conf.load(xmldata, format='xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch('__builtin__.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch('__builtin__.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') @patch('__builtin__.open') def test_config_load_try_load_rpcerror(self, mock_open): ex = ConfigLoadError( rsp=etree.fromstring(( """<load-configuration-results> <rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error> </load-configuration-results>"""))) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(ConfigLoadError, self.conf.load, path='config.conf') @patch('__builtin__.open') def test_config_try_load_exception(self, mock_open): class OtherException(Exception): pass self.conf.rpc.load_config = MagicMock(side_effect=OtherException()) self.assertRaises(OtherException, self.conf.load, path='config.conf') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_template_path(self, mock_etree): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock(return_value='<test/>') self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1) @patch('jnpr.junos.Device.execute') def test_rescue_action_save(self, mock_exec): self.dev.request_save_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('save')) @patch('jnpr.junos.Device.execute') def test_rescue_action_get_exception(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock(side_effect=Exception) self.assertTrue(self.conf.rescue('get') is None) @patch('jnpr.junos.Device.execute') def test_rescue_action_get(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock() self.dev.rpc.get_rescue_information.return_value = 1 self.assertEqual(self.conf.rescue('get', format='xml'), 1) @patch('jnpr.junos.Device.execute') def test_rescue_action_delete(self, mock_exec): self.dev.rpc.request_delete_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('delete')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload(self, mock_exec): self.dev.rpc.load_configuration = MagicMock() self.dev.rpc.load_configuration.return_value = True self.assertTrue(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload_exception(self, mock_exec): self.dev.rpc.load_configuration = MagicMock(side_effect=Exception) self.assertFalse(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_unsupported_action(self, mock_exec): self.assertRaises(ValueError, self.conf.rescue, 'abc') def test_config_load_lset_from_rexp_xml(self): self.conf.rpc.load_config = MagicMock() conf = """<snmp><name>iBGP</name></snmp>""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_lset_from_rexp_set(self): self.conf.rpc.load_config = MagicMock() conf = """set system domain-name englab.nitin.net""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_delete(self): self.conf.rpc.load_config = MagicMock() conf = """delete snmp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_conf(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_lset_from_rexp_conf_replace_tag(self): self.conf.rpc.load_config = MagicMock() conf = """replace: snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'replace') def test_config_load_lset_from_rexp_error(self): self.conf.rpc.load_config = MagicMock() conf = """nitin>""" self.assertRaises(RuntimeError, self.conf.load, conf) def test_load_merge_true(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf, merge=True) self.assertFalse('action' in self.conf.rpc.load_config.call_args[1]) def test_commit_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit)
def provision_services(): name = request.form.get('name') ip_address = request.form.get('ip_address') campus_user = request.form.get('campus_user') service2 = request.form.get('service2') service3 = request.form.get('service3') service4 = request.form.get('service4') service5 = request.form.get('service5') campus = request.form.get('campus') internet_user = request.form.get('internet_user') legacy = request.form.get('legacy') provisioned_services = '' provisioned_services += Markup('''\ <html> <head> <meta name="viewport" content="width=device-width, initial-scale=1" /> </head> <body><center> Provisioned - <br>''') if campus_user: dev = Device(host='172.25.45.68', user='******', passwd='jnpr123') cu = Config(dev) print name, ip_address try: dev.open() dev.timeout = 300 cu.lock() jinja_input = {'Address': ip_address, 'var1': name} jinja_data = open("jinjafile.conf", "wb") jinja_data.write(JinjaTemplate_Campus.render(**jinja_input)) jinja_data.close() rsp = cu.load( template_path="jinjafile.conf", merge=True ) cu.commit() cu.unlock() except RpcError: msg = "{0} was Skipped due to RPC Error. Device is not a Juniper SRX Series" print msg dev.close() except Exception as err: msg = "{0} was skipped due to unhandled exception.\n{1}" print msg traceback.print_exc(file=sys.stdout) dev.close() provisioned_services += Markup('''Campus User: '''+name+''' with IP Address:'''+ip_address+'''<br>''') if internet_user: dev = Device(host='172.25.45.68', user='******', passwd='jnpr123') cu = Config(dev) print name, ip_address try: dev.open() dev.timeout = 300 cu.lock() jinja_input = {'Address': ip_address, 'var1': name} jinja_data = open("jinjafile.conf", "wb") jinja_data.write(JinjaTemplate_Internet.render(**jinja_input)) jinja_data.close() rsp = cu.load( template_path="jinjafile.conf", merge=True ) cu.commit() cu.unlock() except RpcError: msg = "{0} was Skipped due to RPC Error. Device is not a Juniper SRX Series" print msg dev.close() except Exception as err: msg = "{0} was skipped due to unhandled exception.\n{1}" print msg traceback.print_exc(file=sys.stdout) dev.close() provisioned_services += Markup('''Internet User'''+name+''' with IP Address: '''+ip_address+'''<br>''') if legacy: provisioned_services += Markup('''Legacy<br>''') if service2: provisioned_services += Markup('''Service 2<br>''') if service3: provisioned_services += Markup('''Service 3<br>''') if service4: provisioned_services += Markup('''Service 4<br>''') if service5: provisioned_services += Markup('''Service 5<br>''') if campus: provisioned_services += Markup('''Campus<br>''') provisioned_services += Markup('''<button type="button" name="button" class="btn btn-primary btn-lg" onClick="location.href='../'" enabled><strong>Return to Main Page</strong></button><br>''') provisioned_services += Markup('''</body></html>''') print provisioned_services return render_template('success.html', info=provisioned_services)
class TestConfig(unittest.TestCase): def setUp(self): self.dev = Device(host='1.1.1.1') self.conf = Config(self.dev) def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit(confirm=True)) def test_config_commit_confirm_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(AttributeError, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with({'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='') self.conf.pdiff() self.conf.diff.assert_any_call() def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch('__builtin__.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch('__builtin__.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_template_path(self): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.conf.dev.Template.assert_called_with('test.xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock() self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, rollback=51) self.assertRaises(ValueError, self.conf.diff, rollback=-1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1)
class TestConfig(unittest.TestCase): @patch("ncclient.manager.connect") def setUp(self, mock_connect): mock_connect.side_effect = self._mock_manager self.dev = Device(host="1.1.1.1", user="******", password="******", gather_facts=False) self.dev.open() self.conf = Config(self.dev) @patch("ncclient.operations.session.CloseSession.request") def tearDown(self, mock_session): self.dev.close() def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm_true(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=True) self.conf.rpc.commit_configuration.assert_called_with(confirmed=True) def test_config_commit_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration.assert_called_with( **{ "confirm-timeout": "10", "confirmed": True }) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment="Test") self.conf.rpc.commit_configuration.assert_called_with(log="Test") def test_config_commit_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(sync=True) self.conf.rpc.commit_configuration.assert_called_with(synchronize=True) def test_config_commit_force_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(force_sync=True) self.conf.rpc.commit_configuration.assert_called_with( **{ "synchronize": True, "force-synchronize": True }) def test_config_commit_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(timeout=60) self.conf.rpc.commit_configuration.assert_called_with(dev_timeout=60) def test_config_commit_full(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(full=True) self.conf.rpc.commit_configuration.assert_called_with(full=True) def test_config_commit_detail(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = "<mockdetail/>" self.assertEqual("<mockdetail/>", self.conf.commit(detail=True)) self.conf.rpc.commit_configuration.assert_called_with( {"detail": "detail"}) def test_config_commit_combination(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = "<moredetail/>" self.assertEqual( "<moredetail/>", self.conf.commit(detail=True, force_sync=True, full=True)) self.conf.rpc.commit_configuration.assert_called_with( {"detail": "detail"}, **{ "synchronize": True, "full": True, "force-synchronize": True }) @patch("jnpr.junos.utils.config.JXML.remove_namespaces") def test_config_commit_xml_exception(self, mock_jxml): class MyException(Exception): xml = etree.fromstring("<test/>") self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) self.assertRaises(CommitError, self.conf.commit) def test_config_commit_exception(self): class MyException(Exception): pass self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) self.assertRaises(MyException, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp="ok") self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find("company") ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) # @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self): class MyException(Exception): xml = etree.fromstring(""" <rpc-reply> <rpc-error> <error-type>protocol</error-type> <error-tag>operation-failed</error-tag> <error-severity>error</error-severity> <error-message>permission denied</error-message> <error-info> <bad-element>system</bad-element> </error-info> </rpc-error> </rpc-reply> """) self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.assertDictEqual( self.conf.commit_check(), { "source": None, "message": "permission denied", "bad_element": "system", "severity": "error", "edit_path": None, }, ) def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp="ok") self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find("company") ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.assert_called_with( { "compare": "rollback", "rollback": "0", "format": "text" }, ignore_warning=False, ) def test_config_diff_exception_severity_warning(self): rpc_xml = """ <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>mgd: statement must contain additional statements</error-message> </rpc-error> """ rsp = etree.XML(rpc_xml) self.conf.rpc.get_configuration = MagicMock(side_effect=RpcError( rsp=rsp)) self.assertEqual(self.conf.diff(), "Unable to parse diff from response!") def test_config_diff_exception_severity_warning_still_raise(self): rpc_xml = """ <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>statement not found</error-message> </rpc-error> """ rsp = etree.XML(rpc_xml) self.conf.rpc.get_configuration = MagicMock(side_effect=RpcError( rsp=rsp)) self.assertRaises(RpcError, self.conf.diff) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value="Stuff") self.conf.pdiff() self.conf.diff.assert_called_once_with(0) def test_config_diff_rpc_timeout(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.get_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.diff) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, "test.xml") def test_config_load_len_with_format_set(self): self.conf.rpc.load_config = MagicMock(return_value="rpc_contents") self.assertEqual(self.conf.load("test.xml", format="set"), "rpc_contents") def test_config_load_len_with_format_xml(self): self.conf.rpc.load_config = MagicMock(return_value="rpc_contents") xmldata = """<snmp> <community> <name>iBGP</name> </community> </snmp>""" self.assertEqual(self.conf.load(xmldata, format="xml"), "rpc_contents") def test_config_load_len_with_format_text(self): self.conf.rpc.load_config = MagicMock(return_value="rpc_contents") textdata = """policy-options { prefix-list TEST1-NETS { 100.0.0.0/24; } policy-statement TEST1-NETS { term TEST1 { from { prefix-list TEST1-NETS; } then accept; } term REJECT { then reject; } } }""" self.assertEqual(self.conf.load(textdata), "rpc_contents") def test_config_load_with_format_json(self): self.conf.rpc.load_config = MagicMock( return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load("test.json", format="json") self.assertEqual(op.tag, "load-configuration-results") self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "json") @patch(builtin_string + ".open") def test_config_load_with_format_json_from_file_ext(self, mock_open): self.conf.rpc.load_config = MagicMock( return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path="test.json") self.assertEqual(op.tag, "load-configuration-results") self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "json") @patch(builtin_string + ".open") def test_config_load_update(self, mock_open): self.conf.rpc.load_config = MagicMock( return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path="test.conf", update=True) self.assertEqual(op.tag, "load-configuration-results") self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "text") def test_config_load_update_merge_overwrite(self): self.assertRaises( ValueError, self.conf.load, path="test.jnpr", update=True, merge=True, overwrite=True, ) @patch(builtin_string + ".open") def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = MagicMock(return_value="rpc_contents") self.assertRaises(ValueError, self.conf.load, path="test.jnpr") def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = MagicMock(return_value="rpc_contents") self.assertRaises(ValueError, self.conf.load, "test.xml", format="set", overwrite=True) @patch(builtin_string + ".open") @patch("jnpr.junos.utils.config.etree.XML") def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = "rpc_contents" self.conf.rpc.load_config = MagicMock( return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path="test.xml"), "rpc_contents") @patch(builtin_string + ".open") def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path="test.conf") self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "text") @patch(builtin_string + ".open") def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path="test.set") self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") @patch(builtin_string + ".open") def test_config_load_try_load_rpcerror(self, mock_open): ex = ConfigLoadError( rsp=etree.fromstring(("""<load-configuration-results> <rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error> </load-configuration-results>"""))) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(ConfigLoadError, self.conf.load, path="config.conf") @patch(builtin_string + ".open") def test_config_load_try_load_rpctimeouterror(self, mock_open): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.load, path="config.conf") @patch(builtin_string + ".open") def test_config_try_load_exception(self, mock_open): class OtherException(Exception): pass self.conf.rpc.load_config = MagicMock(side_effect=OtherException()) self.assertRaises(OtherException, self.conf.load, path="config.conf") @patch("jnpr.junos.utils.config.etree.XML") def test_config_load_template_path(self, mock_etree): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path="test.xml") self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "xml") def test_config_load_template(self): class Temp: filename = "abc.xml" render = MagicMock(return_value="<test/>") self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "xml") def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch("jnpr.junos.utils.config.JXML.rpc_error") def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp="ok") self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch("jnpr.junos.utils.config.JXML.rpc_error") def test_config_lock_ConnectClosedError(self, mock_jxml): ex = ConnectClosedError(dev=self) self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(ConnectClosedError, self.conf.lock) @patch("jnpr.junos.utils.config.JXML.remove_namespaces") def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = "test" self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch("jnpr.junos.utils.config.JXML.rpc_error") def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp="ok") self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch("jnpr.junos.utils.config.JXML.rpc_error") def test_config_unlock_ConnectClosedError(self, mock_jxml): ex = ConnectClosedError(dev=self) self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(ConnectClosedError, self.conf.unlock) @patch("jnpr.junos.utils.config.JXML.remove_namespaces") def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = "test" self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1) @patch("jnpr.junos.Device.execute") def test_rescue_action_save(self, mock_exec): self.dev.request_save_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue("save")) @patch("jnpr.junos.Device.execute") def test_rescue_action_get_exception(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock(side_effect=Exception) self.assertTrue(self.conf.rescue("get") is None) @patch("jnpr.junos.Device.execute") def test_rescue_action_get(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock() self.dev.rpc.get_rescue_information.return_value = 1 self.assertEqual(self.conf.rescue("get", format="xml"), 1) @patch("jnpr.junos.Device.execute") def test_rescue_action_delete(self, mock_exec): self.dev.rpc.request_delete_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue("delete")) @patch("jnpr.junos.Device.execute") def test_rescue_action_reload(self, mock_exec): self.dev.rpc.load_configuration = MagicMock() self.dev.rpc.load_configuration.return_value = True self.assertTrue(self.conf.rescue("reload")) @patch("jnpr.junos.Device.execute") def test_rescue_action_reload_exception(self, mock_exec): self.dev.rpc.load_configuration = MagicMock(side_effect=Exception) self.assertFalse(self.conf.rescue("reload")) @patch("jnpr.junos.Device.execute") def test_rescue_action_unsupported_action(self, mock_exec): self.assertRaises(ValueError, self.conf.rescue, "abc") def test_config_load_lset_from_rexp_xml(self): self.conf.rpc.load_config = MagicMock() conf = """<snmp><name>iBGP</name></snmp>""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "xml") def test_config_load_lset_from_rexp_json(self): self.conf.rpc.load_config = MagicMock() conf = """{ "configuration" : { "system" : { "services" : { "telnet" : [null] } } } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "json") def test_config_load_lset_from_rexp_set(self): self.conf.rpc.load_config = MagicMock() conf = """set system domain-name englab.nitin.net""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_set_delete(self): self.conf.rpc.load_config = MagicMock() conf = """delete snmp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_set_rename(self): self.conf.rpc.load_config = MagicMock() conf = """rename firewall family inet filter f1 to filter f2""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_insert(self): self.conf.rpc.load_config = MagicMock() conf = """insert policy-options policy-statement hop term 10 after 9""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_set_activate(self): self.conf.rpc.load_config = MagicMock() conf = """activate system services ftp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_set_deactivate(self): self.conf.rpc.load_config = MagicMock() conf = """deactivate system services ftp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_set_annotate(self): self.conf.rpc.load_config = MagicMock() conf = """annotate system \"Annotation test\"""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_set_copy(self): self.conf.rpc.load_config = MagicMock() conf = """copy firewall family inet filter f1 to filter f2""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_set_protect(self): self.conf.rpc.load_config = MagicMock() conf = """protect system services""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_set_unprotect(self): self.conf.rpc.load_config = MagicMock() conf = """unprotect system services""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "set") def test_config_load_lset_from_rexp_conf(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "text") def test_config_load_lset_from_rexp_conf_replace_tag(self): self.conf.rpc.load_config = MagicMock() conf = """replace: snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]["format"], "text") self.assertEqual(self.conf.rpc.load_config.call_args[1]["action"], "replace") def test_config_load_lset_from_rexp_error(self): self.conf.rpc.load_config = MagicMock() conf = """test>""" self.assertRaises(RuntimeError, self.conf.load, conf) def test_load_merge_true(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf, merge=True) self.assertFalse("action" in self.conf.rpc.load_config.call_args[1]) def test_commit_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit) def test_commit_check_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit_check) def test_commit_configuration_multi_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) try: self.dev.rpc.commit_configuration() except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) self.assertEqual( ex.message, "error: interface-range 'axp' is not defined\n" "error: interface-ranges expansion failed", ) self.assertEqual( ex.errs, [ { "source": None, "message": "interface-range 'axp' is not defined", "bad_element": None, "severity": "error", "edit_path": None, }, { "source": None, "message": "interface-ranges expansion failed", "bad_element": None, "severity": "error", "edit_path": None, }, ], ) @patch("jnpr.junos.utils.config.Config.lock") @patch("jnpr.junos.utils.config.Config.unlock") def test_config_mode_exclusive(self, mock_unlock, mock_lock): with Config(self.dev, mode="exclusive") as conf: conf.rpc.load_config = MagicMock() conf.load("conf", format="set") self.assertTrue(mock_lock.called and mock_unlock.called) @patch("jnpr.junos.Device.execute") def test_config_mode_batch(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode="batch") as conf: conf.load("conf", format="set") self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch("jnpr.junos.Device.execute") def test_config_mode_private(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode="private") as conf: conf.load("conf", format="set") self.dev.rpc.open_configuration.assert_called_with(private=True) @patch("jnpr.junos.Device.execute") def test_config_mode_dynamic(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode="dynamic") as conf: conf.load("conf", format="set") self.dev.rpc.open_configuration.assert_called_with(dynamic=True) @patch("jnpr.junos.Device.execute") def test_config_mode_ephemeral_default(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode="ephemeral") as conf: conf.load("conf", format="set") self.dev.rpc.open_configuration.assert_called_with(ephemeral=True) @patch("jnpr.junos.Device.execute") def test_config_mode_ephemeral_instance(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode="ephemeral", ephemeral_instance="xyz") as conf: conf.load("conf", format="set") self.dev.rpc.open_configuration.assert_called_with( ephemeral_instance="xyz") def test_config_unsupported_kwargs(self): self.dev.rpc.open_configuration = MagicMock() try: with Config(self.dev, mode="ephemeral", xyz="xyz") as conf: conf.load("conf", format="set") except Exception as ex: self.assertEqual(str(ex), "Unsupported argument provided to Config class") @patch("jnpr.junos.Device.execute") def test_config_mode_close_configuration_ex(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() ex = RpcError(rsp="ok") ex.message = "Configuration database is not open" self.dev.rpc.close_configuration = MagicMock(side_effect=ex) try: with Config(self.dev, mode="batch") as conf: conf.load("conf", format="set") except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) self.assertTrue(self.dev.rpc.close_configuration.called) def test_config_mode_undefined(self): try: with Config(self.dev, mode="unknown") as conf: conf.load("conf", format="set") except Exception as ex: self.assertTrue(isinstance(ex, ValueError)) @patch("jnpr.junos.Device.execute") @patch("jnpr.junos.utils.config.warnings") def test_config_mode_batch_open_configuration_ex(self, mock_warnings, mock_exec): rpc_xml = """ <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> """ rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode="batch") as conf: conf.load("conf", format="set") self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch("jnpr.junos.Device.execute") @patch("jnpr.junos.utils.config.warnings") def test_config_mode_private_open_configuration_ex(self, mock_warnings, mock_exec): rpc_xml = """ <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> """ rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode="private") as conf: conf.load("conf", format="set") self.dev.rpc.open_configuration.assert_called_with(private=True) def test__enter__private_exception_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.open_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, Config.__enter__, Config(self.dev, mode="private")) def test__enter__private_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = MagicMock(side_effect=RpcError( rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode="private")) def test__enter__dyanamic_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = MagicMock(side_effect=RpcError( rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode="dynamic")) def test__enter__batch_exception_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.open_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, Config.__enter__, Config(self.dev, mode="batch")) def test__enter__batch_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = MagicMock(side_effect=RpcError( rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode="batch")) def test_config_load_url(self): self.conf.rpc.load_config = MagicMock() self.conf.load(url="/var/home/user/golden.conf") self.assertEqual(self.conf.rpc.load_config.call_args[1]["url"], "/var/home/user/golden.conf") @patch("jnpr.junos.Device.execute") def test_load_config_patch(self, mock_exec): conf = """[edit system] - host-name pakzds904; + host-name pakzds904_set; """ self.conf.load(conf, format="text", patch=True) self.assertEqual(mock_exec.call_args[0][0].tag, "load-configuration") self.assertEqual(mock_exec.call_args[0][0].attrib, { "format": "text", "action": "patch" }) @patch("jnpr.junos.Device.execute") def test_load_config_text(self, mock_exec): textdata = """policy-options { prefix-list TEST1-NETS { 100.0.0.0/24; } policy-statement TEST1-NETS { term TEST1 { from { prefix-list TEST1-NETS; } then accept; } term REJECT { then reject; } } }""" self.conf.load(textdata, overwrite=True) self.assertEqual(mock_exec.call_args[0][0].tag, "load-configuration") self.assertEqual(mock_exec.call_args[0][0].getchildren()[0].tag, "configuration-text") self.assertEqual(mock_exec.call_args[0][0].attrib, { "format": "text", "action": "override" }) def _read_file(self, fname): fpath = os.path.join(os.path.dirname(__file__), "rpc-reply", fname) foo = open(fpath).read() # specific to multi rpc error if fname == "commit-configuration.xml": raw = etree.XML(foo) obj = RPCReply(raw) obj.parse() raise RPCError(etree.XML(foo), errs=obj._errors) def _mock_manager(self, *args, **kwargs): if kwargs: device_params = kwargs["device_params"] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: return self._read_file(args[0].tag + ".xml")
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'] self.device = Device(host, user=user, passwd=passwd, port=port, gather_facts=False).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
from jnpr.junos import Device from jnpr.junos.exception import LockError from jnpr.junos.utils.config import Config from jnpr_devices import srx2 device_object = Device(**srx2) device_object.open() device_config_object = Config(device_object) #Now we'll lock the config in an unprotected manner device_config_object.lock() #And try again to lock it, but with some sanity check try: device_config_object.lock() print("Successfully locked the device config for editing") except LockError: print("The device was already locked; failed to get a new lock") #Set the hostname with a one-liner device_config_object.load("set system host-name some-fake-hostname", format="set", merge=True) #Now verify that we actually sent some config (but didn't apply it) print("The following config is waiting to apply on the device")
user = args.user password = args.password dev = None try: print("\nOpen connection ... dev.open()") dev = Device(host=device, user=user, password=password, gather_facts=False) open_result = dev.open() print(open_result.connected) # True/False conf = Config(dev) data = 'set interfaces gr-0/0/0 description "Some description 3 for gr-0/0/0"' print("\nLock configuration ... conf.lock();") lock_response = conf.lock() print(lock_response) print("\nRollback configuration ... conf.rollback()") rollback_response = conf.rollback() # True/False print(rollback_response) print("\nLoad configuration ... conf.load(data") load_result = conf.load(data, format='set') print(etree.tostring(load_result, encoding='unicode', pretty_print=True)) # XML print("Commit check configuration ... conf.commit_check()") commit_check_result = conf.commit_check() print(commit_check_result) # True/False
class TestConfig(unittest.TestCase): def setUp(self): self.dev = Device(host='1.1.1.1') self.conf = Config(self.dev) def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm_true(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=True) self.conf.rpc.commit_configuration\ .assert_called_with(confirmed=True) def test_config_commit_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') def test_config_commit_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(synchronize=True) def test_config_commit_force_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(force_sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(**{'synchronize': True, 'force-synchronize': True}) def test_config_commit_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(timeout=60) self.conf.rpc.commit_configuration\ .assert_called_with(dev_timeout=60) def test_config_commit_full(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(full=True) self.conf.rpc.commit_configuration\ .assert_called_with(full=True) def test_config_commit_detail(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<mockdetail/>' self.assertEqual('<mockdetail/>', self.conf.commit(detail=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}) def test_config_commit_combination(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<moredetail/>' self.assertEqual('<moredetail/>', self.conf.commit(detail=True, force_sync=True, full=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}, **{'synchronize': True, 'full': True, 'force-synchronize': True}) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_xml_exception(self, mock_jxml): class MyException(Exception): xml = etree.fromstring('<test/>') self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(CommitError, self.conf.commit) def test_config_commit_exception(self): class MyException(Exception): pass self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(MyException, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with( {'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format_set(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') def test_config_load_len_with_format_xml(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') xmldata = """<snmp> <community> <name>iBGP</name> </community> </snmp>""" self.assertEqual(self.conf.load(xmldata, format='xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch('__builtin__.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch('__builtin__.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') @patch('__builtin__.open') def test_config_load_try_load_rpcerror(self, mock_open): ex = ConfigLoadError( rsp=etree.fromstring(( """<load-configuration-results> <rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error> </load-configuration-results>"""))) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(ConfigLoadError, self.conf.load, path='config.conf') @patch('__builtin__.open') def test_config_try_load_exception(self, mock_open): class OtherException(Exception): pass self.conf.rpc.load_config = MagicMock(side_effect=OtherException()) self.assertRaises(OtherException, self.conf.load, path='config.conf') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_template_path(self, mock_etree): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock(return_value='<test/>') self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1) @patch('jnpr.junos.Device.execute') def test_rescue_action_save(self, mock_exec): self.dev.request_save_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('save')) @patch('jnpr.junos.Device.execute') def test_rescue_action_get_exception(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock(side_effect=Exception) self.assertTrue(self.conf.rescue('get') is None) @patch('jnpr.junos.Device.execute') def test_rescue_action_get(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock() self.dev.rpc.get_rescue_information.return_value = 1 self.assertEqual(self.conf.rescue('get', format='xml'), 1) @patch('jnpr.junos.Device.execute') def test_rescue_action_delete(self, mock_exec): self.dev.rpc.request_delete_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('delete')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload(self, mock_exec): self.dev.rpc.load_configuration = MagicMock() self.dev.rpc.load_configuration.return_value = True self.assertTrue(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload_exception(self, mock_exec): self.dev.rpc.load_configuration = MagicMock(side_effect=Exception) self.assertFalse(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_unsupported_action(self, mock_exec): self.assertRaises(ValueError, self.conf.rescue, 'abc') def test_config_load_lset_from_rexp_xml(self): self.conf.rpc.load_config = MagicMock() conf = """<snmp><name>iBGP</name></snmp>""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_lset_from_rexp_set(self): self.conf.rpc.load_config = MagicMock() conf = """set system domain-name englab.nitin.net""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_delete(self): self.conf.rpc.load_config = MagicMock() conf = """delete snmp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_conf(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_lset_from_rexp_conf_replace_tag(self): self.conf.rpc.load_config = MagicMock() conf = """replace: snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'replace') def test_config_load_lset_from_rexp_error(self): self.conf.rpc.load_config = MagicMock() conf = """nitin>""" self.assertRaises(RuntimeError, self.conf.load, conf) def test_load_merge_true(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf, merge=True) self.assertFalse('action' in self.conf.rpc.load_config.call_args[1]) def test_commit_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit)
def 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
def juniper_config_commit(dev, file_location): """ This function is used to configure a Juniper network device. dev = Juniper device connection file_location = Location of configuration changes to push. Changes should be in the set format. """ try: cfg = Config(dev) print("\n" + "!!!!! Locking the configuration !!!!!") cfg.lock() print('\n' + '!!!!! Pushing changes to device ' + str(dev.hostname) + ' !!!!!' + '\n' + '\n') cfg.load(path=file_location, format="set") with open(file_location) as config_to_commit: print( '###############################################################################' + '\n' + '\n') for line in config_to_commit: print(line) print( '\n' + '\n' + '###############################################################################' ) commit_check = input( "\n" + "Are you sure you want to commit changes to the device" + "\n" + "n/Y:") if commit_check.lower().strip() == 'y': cfg.commit(comment="Commit configuration", confirm=2) confirm_check = input( "\n" + "Please confirm commit. Device config will rollback in 2 minutes unless confirmed." + "\n" + "n/Y:") if confirm_check.lower().strip() == 'y': cfg.commit() print('\n' + "!!!!! Commit Confirmed !!!!!") else: cfg.unlock() sys.exit('!!!!! Warning !!!!!!' + '\n' + 'Device config will rollback in 2 minutes.') else: cfg.rollback(0) print('\n' + 'Changes have been rolled back') print('\n' + "!!!!! Unlocking the configuration !!!!!" + '\n') cfg.unlock() dev.close() sys.exit(1) print('\n' + "!!!!! Unlocking the configuration !!!!!" + '\n') cfg.unlock() except CommitError as error: print('\n' + "!!!!!!!!!! Config Error !!!!!!!!!!") print('\n' + str(error)) print('\n' + "!!!!!!!!!! Attempting to rollback config !!!!!!!!!!") cfg.rollback(0) cfg.unlock() dev.close() sys.exit(1) return except LockError as error: print('\n' + "Error: Unable to lock configuration") dev.close() sys.exit(1) return except UnlockError: print('\n' + "Error: Unable to unlock configuration") dev.close() sys.exit(1) return except Exception as err: print(err) dev.close() sys.exit(1) return return
def fnWriteToDevice(sConfig): logging.deug("fnWriteToDevice") hDev = Device() hDev.open() sCu = Config(hDev) # Lock the configuration, load configuration changes, and commit logging.info("Locking the configuration") try: sCu.lock() logging.debug("Configuration Locked") except LockError: logging.debug("Error: Unable to lock configuration") hDev.close() return logging.info("Loading configuration changes") try: if "delete" in sConfig: sCU.load(sConfig, format="set") else: sCu.load(sConfig, format="set", merge=True) logging.debug("Configuration Loaded") except ConfigLoadError as err: logging.debug(err) logging.debug("UNABLE TO LOAD CONFIGURATION CHANGES:") logging.debug("UNLOCKING THE CONFIGURATION") hDev = Device() hDev.open() sCu = Config(hDev) # Lock the configuration, load configuration changes, and commit logging.info("Locking the configuration") try: sCu.lock() logging.debug("Configuration Locked") except LockError: logging.debug("Error: Unable to lock configuration") hDev.close() return logging.info("Loading configuration changes") try: if "delete" in sConfig: sCU.load(sConfig, format="set") else: sCu.load(sConfig, format="set", merge=True) logging.debug("Configuration Loaded") except ConfigLoadError as err: logging.debug(err) logging.debug("UNABLE TO LOAD CONFIGURATION CHANGES:") logging.debug("UNLOCKING THE CONFIGURATION") try: sCu.unlock() logging.debug("Configuration Unlocked from Load Failure") except UnlockError: logging.debug( "Error: Unable to unlock configuration from Load Failure") sDev.close() return logging.info("Committing the configuration") try: dev.cu.commit() logging.debug("Commiting Configuration") logging.debug(sConfiguration) except CommitError: logging.debug("Error: Unable to commit configuration") logging.debug("Unlocking the configuration") try: sCu.unlock() logging.debug("Configuration Unlocked from Commit Failure") except UnlockError: logging.debug( "Error: Unable to unlock configuration from Commiti Failure") sDev.close() return logging.debug("Unlocking the configuration") try: dev.cu.unlock() except UnlockError: logging.debug("Error: Unable to unlock configuration") dev.close() return
class NetconfJuniperSess(SessBase): """netconfセッション用クラス """ def __init__(self, server, user_login, pass_login, logger_name, netconf_port=830, rpc_timeout=20): self.server = server self.user_login = user_login self.pass_login = pass_login self.logger = logging.getLogger(logger_name) self.netconf_port = netconf_port self.rpc_timeout = rpc_timeout self.closed = True self.acl_name = 'SNMP-ACCESS' self.last_acl = list() def open(self): """サーバに接続 """ self.dev = Device( host=self.server.ipaddr, user=self.user_login, password=self.pass_login, ) self.dev.open(gather_facts=False) if self.dev.connected: # デフォルト30秒を更新 setattr(self.dev, 'timeout', self.rpc_timeout) self.cu = Config(self.dev) self.closed = False self.write_log(self.logger, 'info', "%s (%s): 接続しました." % (self.server.ipaddr, self.server.model, )) else: raise RuntimeError("%s: %s: unable to connect." % (self.__class__.__name__, self.server.ipaddr)) def get_snmp_acl(self, **kw): """ SNMPアクセスリストを取得 >>> for pl in PrefListTable(self.dev).get(): ... if pl.name == 'SNMP-ACCESS': ... pp.pprint(json.loads(pl.entries.to_json())) ... { u'10.0.0.1/32': { u'prefix': u'10.0.0.1/32'}, u'172.25.8.0/24': { u'prefix': u'172.25.8.0/24'}, u'172.31.30.0/24': { u'prefix': u'172.31.30.0/24'}, u'192.168.11.0/24': { u'prefix': u'192.168.11.0/24'}} """ set_last_acl = kw.get('set_last_acl', True) acl = list() for pl in PrefListTable(self.dev).get(): if pl.name == self.acl_name: # prefix-list name がマッチしたらエントリを取得 acl = map(IPv4Network, pl.entries.keys()) break # 取得できなかった場合はカラのリストを返す if set_last_acl: self.last_acl = acl return acl def update_snmp_acl(self, acl_diff_dict, **kw): """ SNMPアクセスリストを更新 """ if not os.access(template_path, os.R_OK): self.close(error_msg="テンプレートファイルを開けません.: %s" % (template_path, )) raise IOError('failed!') if kw.get('prompt', False): # 確認プロンプトを表示 reply = raw_input("変更しますか? ") if not re.match('\s*(y|yes|)\s*$', reply.rstrip(), re.I): self.write_log(self.logger, 'info', "%s: 更新をキャンセルします." % (self.server.ipaddr, )) self.close() return False new_acl = list(set(self.last_acl) - set(acl_diff_dict['del'])) + acl_diff_dict['add'] template_vars = dict([ ('acl_dict', dict([ (self.acl_name, [ n.with_prefixlen for n in new_acl ]), ])), ]) # 新しいACLを機器にロードする self.cu.lock() self.cu.load(template_path=template_path, template_vars=template_vars) return self.get_snmp_acl(set_last_acl=False) def save_exit_config(self, **kw): """ コミット or ロールバック """ if kw.get('prompt', False): # 確認プロンプトを表示 if not re.match('\s*(y|yes|)\s*$', raw_input("保存しますか? ").rstrip(), re.I): self.write_log(self.logger, 'info', "%s: ロールバックします." % (self.server.ipaddr, )) self.cu.rollback() current_acl = self.get_snmp_acl(set_last_acl=False) failed = set(current_acl) != set(self.last_acl) if failed: self.close(error_msg="正常にロールバックできませんでした.: %s%s" % ( self.last_acl, current_acl, )) raise RuntimeError('failed!') self.close() return # コミット self.cu.commit() self.cu.unlock() self.write_log(self.logger, 'debug', "%s: コミットしました." % (self.server.ipaddr, )) def close(self, error_msg=None): """ セッション終了 """ if self.closed: return self.dev.close() if error_msg: self.write_log(self.logger, 'error', "%s: %s" % (self.server.ipaddr, error_msg)) else: self.write_log(self.logger, 'debug', "%s: セッションを閉じました." % (self.server.ipaddr, )) self.closed = True
def provision(host, **kwargs): # host = kwargs['host'] username = kwargs["username"] password = kwargs["password"] port = kwargs["port"] compareconfig = kwargs["compareconfig"] configuration = kwargs["configuration"] waitconfirm = kwargs[b"waitconfirm"] print colored("-------------------------------------------------------------------------------\n", "yellow") print colored("Start committing configuration to: ", "cyan") + colored("%s" % host["address"], "yellow") logging.info("Start committing configuration to %s" % host["address"]) dev = Device( host=host["address"], username=username, password=password, port=port, timeout=5, device_params={"name": "junos"}, hostkey_verify=False, ) try: logging.info("Connecting to %s" % host) # logging.debug("Connecting to %s" % host) dev.open() except jnpr.junos.exception.ConnectAuthError as err: logging.info("Wrong username or password while connecting to %s." % host["address"]) print colored("Wrong username or password while connecting to %s.", "red") % host["address"] host["status"] = CONNECTION_FAILED return except jnpr.junos.exception.ConnectUnknownHostError as err: logging.info("Wrong hostname: %s." % host["address"]) print "Host: " + colored("%s" % host["address"], "red") + " not found. Wrong FQDN?" host["status"] = CONNECTION_FAILED return except jnpr.junos.exception.ConnectRefusedError as err: logging.info("NETCONF session to %s failed." % host["address"]) print "Host: " + colored("NETCONF session to %s failed", "red") % host["address"] host["status"] = CONNECTION_FAILED return except jnpr.junos.exception.ConnectTimeoutError as err: logging.info("Time-out error. Could not open socket to: %s." % host["address"]) print "Time-out error. Could not open socket to : " + colored("%s" % host["address"], "red") host["status"] = CONNECTION_FAILED return # Create an instance of Config cu = Config(dev) logging.debug("Acquiring lock to %s." % host) # lock the device try: cu.lock() except jnpr.junos.exception.LockError as err: logging.info("Error: unable to lock configuration in %s." % host["address"]) print colored("Error: unable to lock configuration in %s", "red") % host["address"] host["status"] = UNABLE_TO_LOCK dev.close() return # parse configuration file and load commands. Handle exceptions accordingly for line in configuration: if line[0] != "#": logging.debug("Loading command: %s in %s " % (line.rstrip("\n"), host["address"])) try: cu.load(line, format="set", merge=False) except jnpr.junos.exception.ConfigLoadError as err: logging.info( "Failed loading command '%s' with severity %s in %s." % (line.rstrip("\n"), err.errs["severity"], host["address"]) ) print colored("Loading command failed with severity: %s", "red") % err.errs["severity"] host["status"] = COMMIT_FAILED_WARNING if err.errs["severity"] == "error": cu.rollback() logging.info("Commit failed. Rolling back in %s and exiting the script" % host["address"]) logging.debug("Commit failed with %s rolling back in %s" % (err, host["address"])) print colored("Exiting, configuration rolled-back", "red") host["status"] = COMMIT_FAILED_ERROR cu.unlock() dev.close() sys.exit(1) # print "show|compare" results to stdout if requested if compareconfig != "true": print colored("\n'show | compare' output:", "blue") print cu.diff() if waitconfirm == b"true": if kwargs["first_host"] == b"true": ack = raw_input("Proceed with commiting? [y/n]: ") else: ack = "yes" else: ack = "yes" if ack == "y" or ack == "yes": try: cu.commit(comment="This is netconf jprovision script") logging.info("Committing to %s succeded." % host["address"]) logging.debug("Committing to %s succeded." % host["address"]) print colored("Succeeded", "green") if not str(host["status"]): host["status"] = SUCCESSFUL except jnpr.junos.exception.CommitError as err: cu.rollback() logging.info("Commit failed rolling back in %s" % host["address"]) logging.debug("Commit failed with %s rolling back in %s" % (err, host["address"])) print colored("Configuration rolled-back due to commit error", "red") host["status"] = COMMIT_FAILED_ERROR elif ack == "n" or ack == "no": logging.info("User aborted commiting") sys.stdout.write("User aborted, rolling back and exiting.\n") cu.rollback() host["status"] = COMMIT_ABORTED sys.exit(0) cu.unlock() dev.close() logging.info("Finished.")
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
password = get_user_info() # Create object with ip_address, user and password lines = open(filename).readlines() for line in lines: hostname = line.strip() log("Juniper Device name:%s,configuration file:%s" %(hostname,args.commands)) ip = resolve_host(hostname) if ip: juniper_device = Device(host=ip,user=os.getenv("USER"),password=password,port='22') # open the device defined instance juniper_device.open() # open configuration method config = Config(juniper_device) # open configuration lock method allowing only one configuration try: config.lock() except LockError: print "Error: Unable to lock configuration" juniper_device.close() sys.exit(0) # rollback any configuration that might be in candidate configuration config.rollback(0) try: config.load(path=args.commands, format=args.configuration_choice, merge="True") # Merge = "False" would implies a replace action. A # replace action, however, requires that the configuration file have a # 'replace:' statement in it print configuration diff from devices # perspective. To load a jinja template: # cu.load(template_path=conf_file, template_vars=config, merge=True) except ValueError as err:
class TestConfig(unittest.TestCase): @patch('ncclient.manager.connect') def setUp(self, mock_connect): mock_connect.side_effect = self._mock_manager self.dev = Device(host='1.1.1.1', user='******', password='******', gather_facts=False) self.dev.open() self.conf = Config(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm_true(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=True) self.conf.rpc.commit_configuration\ .assert_called_with(confirmed=True) def test_config_commit_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') def test_config_commit_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(synchronize=True) def test_config_commit_force_sync(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(force_sync=True) self.conf.rpc.commit_configuration\ .assert_called_with(**{'synchronize': True, 'force-synchronize': True}) def test_config_commit_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(timeout=60) self.conf.rpc.commit_configuration\ .assert_called_with(dev_timeout=60) def test_config_commit_full(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(full=True) self.conf.rpc.commit_configuration\ .assert_called_with(full=True) def test_config_commit_detail(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<mockdetail/>' self.assertEqual('<mockdetail/>', self.conf.commit(detail=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}) def test_config_commit_combination(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.rpc.commit_configuration.return_value = '<moredetail/>' self.assertEqual( '<moredetail/>', self.conf.commit(detail=True, force_sync=True, full=True)) self.conf.rpc.commit_configuration\ .assert_called_with({'detail': 'detail'}, **{'synchronize': True, 'full': True, 'force-synchronize': True}) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_xml_exception(self, mock_jxml): class MyException(Exception): xml = etree.fromstring('<test/>') self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(CommitError, self.conf.commit) def test_config_commit_exception(self): class MyException(Exception): pass self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(MyException, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with( {'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_diff_exception_severity_warning(self): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>mgd: statement must contain additional statements</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) self.conf.rpc.get_configuration = MagicMock(side_effect=RpcError( rsp=rsp)) self.assertEqual(self.conf.diff(), "Unable to parse diff from response!") def test_config_diff_exception_severity_warning_still_raise(self): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>statement not found</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) self.conf.rpc.get_configuration = MagicMock(side_effect=RpcError( rsp=rsp)) self.assertRaises(RpcError, self.conf.diff) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format_set(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') def test_config_load_len_with_format_xml(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') xmldata = """<snmp> <community> <name>iBGP</name> </community> </snmp>""" self.assertEqual(self.conf.load(xmldata, format='xml'), 'rpc_contents') def test_config_load_len_with_format_text(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') textdata = """policy-options { prefix-list TEST1-NETS { 100.0.0.0/24; } policy-statement TEST1-NETS { term TEST1 { from { prefix-list TEST1-NETS; } then accept; } term REJECT { then reject; } } }""" self.assertEqual(self.conf.load(textdata), 'rpc_contents') def test_config_load_with_format_json(self): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load('test.json', format='json') self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') @patch(builtin_string + '.open') def test_config_load_with_format_json_from_file_ext(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path='test.json') self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') @patch(builtin_string + '.open') def test_config_load_update(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value=etree.fromstring("""<load-configuration-results> <ok/> </load-configuration-results>""")) op = self.conf.load(path='test.conf', update=True) self.assertEqual(op.tag, 'load-configuration-results') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_update_merge_overwrite(self): self.assertRaises(ValueError, self.conf.load, path='test.jnpr', update=True, merge=True, overwrite=True) @patch(builtin_string + '.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch(builtin_string + '.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch(builtin_string + '.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch(builtin_string + '.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') @patch(builtin_string + '.open') def test_config_load_try_load_rpcerror(self, mock_open): ex = ConfigLoadError( rsp=etree.fromstring(("""<load-configuration-results> <rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error> </load-configuration-results>"""))) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(ConfigLoadError, self.conf.load, path='config.conf') @patch(builtin_string + '.open') def test_config_load_try_load_rpctimeouterror(self, mock_open): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.load_config = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.load, path='config.conf') @patch(builtin_string + '.open') def test_config_try_load_exception(self, mock_open): class OtherException(Exception): pass self.conf.rpc.load_config = MagicMock(side_effect=OtherException()) self.assertRaises(OtherException, self.conf.load, path='config.conf') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_template_path(self, mock_etree): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock(return_value='<test/>') self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_ConnectClosedError(self, mock_jxml): ex = ConnectClosedError(dev=self) self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(ConnectClosedError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_ConnectClosedError(self, mock_jxml): ex = ConnectClosedError(dev=self) self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(ConnectClosedError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1) @patch('jnpr.junos.Device.execute') def test_rescue_action_save(self, mock_exec): self.dev.request_save_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('save')) @patch('jnpr.junos.Device.execute') def test_rescue_action_get_exception(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock(side_effect=Exception) self.assertTrue(self.conf.rescue('get') is None) @patch('jnpr.junos.Device.execute') def test_rescue_action_get(self, mock_exec): self.dev.rpc.get_rescue_information = MagicMock() self.dev.rpc.get_rescue_information.return_value = 1 self.assertEqual(self.conf.rescue('get', format='xml'), 1) @patch('jnpr.junos.Device.execute') def test_rescue_action_delete(self, mock_exec): self.dev.rpc.request_delete_rescue_configuration = MagicMock() self.assertTrue(self.conf.rescue('delete')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload(self, mock_exec): self.dev.rpc.load_configuration = MagicMock() self.dev.rpc.load_configuration.return_value = True self.assertTrue(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_reload_exception(self, mock_exec): self.dev.rpc.load_configuration = MagicMock(side_effect=Exception) self.assertFalse(self.conf.rescue('reload')) @patch('jnpr.junos.Device.execute') def test_rescue_action_unsupported_action(self, mock_exec): self.assertRaises(ValueError, self.conf.rescue, 'abc') def test_config_load_lset_from_rexp_xml(self): self.conf.rpc.load_config = MagicMock() conf = """<snmp><name>iBGP</name></snmp>""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_load_lset_from_rexp_json(self): self.conf.rpc.load_config = MagicMock() conf = """{ "configuration" : { "system" : { "services" : { "telnet" : [null] } } } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'json') def test_config_load_lset_from_rexp_set(self): self.conf.rpc.load_config = MagicMock() conf = """set system domain-name englab.nitin.net""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_set_delete(self): self.conf.rpc.load_config = MagicMock() conf = """delete snmp""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_lset_from_rexp_conf(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') def test_config_load_lset_from_rexp_conf_replace_tag(self): self.conf.rpc.load_config = MagicMock() conf = """replace: snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'replace') def test_config_load_lset_from_rexp_error(self): self.conf.rpc.load_config = MagicMock() conf = """test>""" self.assertRaises(RuntimeError, self.conf.load, conf) def test_load_merge_true(self): self.conf.rpc.load_config = MagicMock() conf = """ snmp { location USA; community iBGP { authorization read-only; } }""" self.conf.load(conf, merge=True) self.assertFalse('action' in self.conf.rpc.load_config.call_args[1]) def test_commit_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit) def test_commit_check_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.dev.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, self.conf.commit_check) def test_commit_configuration_multi_rpc_error(self): self.dev._conn.rpc = MagicMock(side_effect=self._mock_manager) try: self.dev.rpc.commit_configuration() except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) if ncclient.__version__ > (0, 4, 5): self.assertEqual( ex.message, "error: interface-range 'axp' is not defined\n" "error: interface-ranges expansion failed") self.assertEqual(ex.errs, [{ 'source': None, 'message': "interface-range 'axp' is not defined", 'bad_element': None, 'severity': 'error', 'edit_path': None }, { 'source': None, 'message': 'interface-ranges expansion failed', 'bad_element': None, 'severity': 'error', 'edit_path': None }]) else: self.assertEqual(ex.message, "interface-range 'axp' is not defined") @patch('jnpr.junos.utils.config.Config.lock') @patch('jnpr.junos.utils.config.Config.unlock') def test_config_mode_exclusive(self, mock_unlock, mock_lock): with Config(self.dev, mode='exclusive') as conf: conf.rpc.load_config = MagicMock() conf.load('conf', format='set') self.assertTrue(mock_lock.called and mock_unlock.called) @patch('jnpr.junos.Device.execute') def test_config_mode_batch(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch('jnpr.junos.Device.execute') def test_config_mode_private(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='private') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(private=True) @patch('jnpr.junos.Device.execute') def test_config_mode_dynamic(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='dynamic') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(dynamic=True) @patch('jnpr.junos.Device.execute') def test_config_mode_ephemeral_default(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='ephemeral') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(ephemeral=True) @patch('jnpr.junos.Device.execute') def test_config_mode_ephemeral_instance(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() with Config(self.dev, mode='ephemeral', ephemeral_instance='xyz') as \ conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with( ephemeral_instance='xyz') def test_config_unsupported_kwargs(self): self.dev.rpc.open_configuration = MagicMock() try: with Config(self.dev, mode='ephemeral', xyz='xyz') as conf: conf.load('conf', format='set') except Exception as ex: self.assertEqual(str(ex), 'Unsupported argument provided to Config class') @patch('jnpr.junos.Device.execute') def test_config_mode_close_configuration_ex(self, mock_exec): self.dev.rpc.open_configuration = MagicMock() ex = RpcError(rsp='ok') ex.message = 'Configuration database is not open' self.dev.rpc.close_configuration = MagicMock(side_effect=ex) try: with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, RpcError)) self.assertTrue(self.dev.rpc.close_configuration.called) def test_config_mode_undefined(self): try: with Config(self.dev, mode='unknown') as conf: conf.load('conf', format='set') except Exception as ex: self.assertTrue(isinstance(ex, ValueError)) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.utils.config.warnings') def test_config_mode_batch_open_configuration_ex(self, mock_warnings, mock_exec): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode='batch') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(batch=True) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.utils.config.warnings') def test_config_mode_private_open_configuration_ex(self, mock_warnings, mock_exec): rpc_xml = ''' <rpc-error> <error-severity>warning</error-severity> <error-info><bad-element>bgp</bad-element></error-info> <error-message>syntax error</error-message> </rpc-error> ''' rsp = etree.XML(rpc_xml) obj = RpcError(rsp=rsp) self.dev.rpc.open_configuration = MagicMock(side_effect=obj) with Config(self.dev, mode='private') as conf: conf.load('conf', format='set') self.dev.rpc.open_configuration.assert_called_with(private=True) def test__enter__private_exception_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.open_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, Config.__enter__, Config(self.dev, mode='private')) def test__enter__private_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='private')) def test__enter__dyanamic_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='dynamic')) def test__enter__batch_exception_RpcTimeoutError(self): ex = RpcTimeoutError(self.dev, None, 10) self.conf.rpc.open_configuration = MagicMock(side_effect=ex) self.assertRaises(RpcTimeoutError, Config.__enter__, Config(self.dev, mode='batch')) def test__enter__batch_exception_RpcError(self): rpc_xml = """<rpc-error> <error-severity>error</error-severity> <error-message>syntax error</error-message> </rpc-error>""" rsp = etree.XML(rpc_xml) self.conf.rpc.open_configuration = \ MagicMock(side_effect=RpcError(rsp=rsp)) self.assertRaises(RpcError, Config.__enter__, Config(self.dev, mode='batch')) def test_config_load_url(self): self.conf.rpc.load_config = MagicMock() self.conf.load(url="/var/home/user/golden.conf") self.assertEqual(self.conf.rpc.load_config.call_args[1]['url'], '/var/home/user/golden.conf') def _read_file(self, fname): fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() # specific to multi rpc error if fname == 'commit-configuration.xml': raw = etree.XML(foo) obj = RPCReply(raw) obj.parse() if ncclient.__version__ > (0, 4, 5): raise RPCError(etree.XML(foo), errs=obj._errors) else: raise RPCError(etree.XML(foo)) def _mock_manager(self, *args, **kwargs): if kwargs: device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: return self._read_file(args[0].tag + '.xml')
print "\nRoute Table Get" print '-' * 50 z_routes = RouteTable(a_device) z_routes.get() pprint(z_routes.items()) #### Config operations print print "Current static routes" print '-' * 50 pprint(z_routes.keys()) print # Create config object cfg = Config(a_device) cfg.lock() config_str = """ routing-options { static { route 1.1.1.0/24 next-hop 10.220.88.1; route 1.1.2.0/24 next-hop 10.220.88.1; route 1.1.3.0/24 next-hop 10.220.88.1; } } """ cfg.load(config_str, format="text", merge=True) #cfg.load(path=config_file, format="text", merge=True) print "Config differences..." print '-' * 50
class TestConfig(unittest.TestCase): def setUp(self): self.dev = Device(host='1.1.1.1') self.conf = Config(self.dev) def test_config_constructor(self): self.assertTrue(isinstance(self.conf._dev, Device)) def test_config_confirm(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit(confirm=True)) def test_config_commit_confirm_timeout(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(confirm=10) self.conf.rpc.commit_configuration\ .assert_called_with(**{'confirm-timeout': '10', 'confirmed': True}) def test_config_commit_comment(self): self.conf.rpc.commit_configuration = MagicMock() self.conf.commit(comment='Test') self.conf.rpc.commit_configuration.assert_called_with(log='Test') @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_commit_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = \ MagicMock(side_effect=MyException) self.assertRaises(AttributeError, self.conf.commit) def test_config_commit_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit) def test_commit_check(self): self.conf.rpc.commit_configuration = MagicMock() self.assertTrue(self.conf.commit_check()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_commit_check_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.commit_configuration = MagicMock(side_effect=MyException) # with self.assertRaises(AttributeError): self.conf.commit_check() def test_config_commit_check_exception_RpcError(self): ex = RpcError(rsp='ok') self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertTrue(self.conf.commit_check()) import xml.etree.ElementTree as ET xmldata = """<data><company name="Juniper"> <code>pyez</code> <year>2013</year> </company></data>""" root = ET.fromstring(xmldata) el = root.find('company') ex = RpcError(rsp=el) self.conf.rpc.commit_configuration = MagicMock(side_effect=ex) self.assertRaises(CommitError, self.conf.commit_check) def test_config_diff(self): self.conf.rpc.get_configuration = MagicMock() self.conf.diff() self.conf.rpc.get_configuration.\ assert_called_with({'compare': 'rollback', 'rollback': '0', 'format': 'text'}) def test_config_pdiff(self): self.conf.diff = MagicMock(return_value='Stuff') self.conf.pdiff() print self.conf.diff.call_args self.conf.diff.assert_called_once_with(0) def test_config_load(self): self.assertRaises(RuntimeError, self.conf.load) def test_config_load_vargs_len(self): self.assertRaises(RuntimeError, self.conf.load, 'test.xml') def test_config_load_len_with_format(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertEqual(self.conf.load('test.xml', format='set'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_lformat_byext_ValueError(self, mock_open): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, path='test.jnpr') def test_config_load_lset_format_ValueError(self): self.conf.rpc.load_config = \ MagicMock(return_value='rpc_contents') self.assertRaises(ValueError, self.conf.load, 'test.xml', format='set', overwrite=True) @patch('__builtin__.open') @patch('jnpr.junos.utils.config.etree.XML') def test_config_load_path_xml(self, mock_etree, mock_open): self.conf.dev.Template = MagicMock() mock_etree.return_value = 'rpc_contents' self.conf.rpc.load_config = \ MagicMock(return_value=mock_etree.return_value) self.assertEqual(self.conf.load(path='test.xml'), 'rpc_contents') @patch('__builtin__.open') def test_config_load_path_text(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.conf') self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'text') @patch('__builtin__.open') def test_config_load_path_set(self, mock_open): self.conf.rpc.load_config = MagicMock() self.conf.load(path='test.set') self.assertEqual(self.conf.rpc.load_config.call_args[1]['action'], 'set') def test_config_load_template_path(self): self.conf.rpc.load_config = MagicMock() self.conf.dev.Template = MagicMock() self.conf.load(template_path='test.xml') self.conf.dev.Template.assert_called_with('test.xml') def test_config_load_template(self): class Temp: filename = 'abc.xml' render = MagicMock() self.conf.rpc.load_config = MagicMock() self.conf.load(template=Temp) self.assertEqual(self.conf.rpc.load_config.call_args[1]['format'], 'xml') def test_config_diff_exception(self): self.conf.rpc.get_configuration = MagicMock() self.assertRaises(ValueError, self.conf.diff, 51) self.assertRaises(ValueError, self.conf.diff, -1) def test_config_lock(self): self.conf.rpc.lock_configuration = MagicMock() self.assertTrue(self.conf.lock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_lock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.lock_configuration = MagicMock(side_effect=ex) self.assertRaises(LockError, self.conf.lock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_lock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.lock_configuration = MagicMock(side_effect=MyException) self.assertRaises(LockError, self.conf.lock) def test_config_unlock(self): self.conf.rpc.unlock_configuration = MagicMock() self.assertTrue(self.conf.unlock()) @patch('jnpr.junos.utils.config.JXML.rpc_error') def test_config_unlock_LockError(self, mock_jxml): ex = RpcError(rsp='ok') self.conf.rpc.unlock_configuration = MagicMock(side_effect=ex) self.assertRaises(UnlockError, self.conf.unlock) @patch('jnpr.junos.utils.config.JXML.remove_namespaces') def test_config_unlock_exception(self, mock_jxml): class MyException(Exception): xml = 'test' self.conf.rpc.unlock_configuration = MagicMock(side_effect=MyException) self.assertRaises(UnlockError, self.conf.unlock) def test_config_rollback(self): self.conf.rpc.load_configuration = MagicMock() self.assertTrue(self.conf.rollback()) def test_config_rollback_exception(self): self.conf.rpc.load_configuration = MagicMock() self.assertRaises(ValueError, self.conf.rollback, 51) self.assertRaises(ValueError, self.conf.rollback, -1)
Add code to attempt to lock the configuration again. Gracefully handle the "LockError" exception (meaning the configuration is already locked). """ from jnpr_devices import srx2 # SRX device dictionary from jnpr.junos import Device # Device class from jnpr.junos.utils.config import Config # Config class from jnpr.junos.exception import LockError # For gracefully handling lock error from getpass import getpass # Create device object device_conn = Device(**srx2) device_conn.open() # Establish NETCONF connection device_conn.timeout = 60 # Change device timeout # Pass in NETCONF connection to Config object cnfg = Config(device_conn) print(cnfg.lock()) # Lock device to others so only we can be in config mode # Put pause in the program otherwise after program ends and connection terminates the lock is automatically released pause = input("Go check if you can go into config mode on the device: ") # Gracefully catch the lock error exception which is thrown when we try to lock the config a 2nd time try: cnfg.lock() pause = input("Wait: ") except LockError: # Run this code if this exception thrown print("Error: The configuration is already locked for editing") pause = input("Wait: ")
def main(args, loglevel): logging.basicConfig(format="%(levelname)s: %(message)s", level=loglevel) # # Do template-based config changes # # Open connection logging.info('Opening connection to {0} as {1}...'.format(args.host, args.user)) dev = Device(args.host, user=args.user) try: dev.open() except Exception as err: logging.error('Unable to connect to device {0},'.format(args.host) + \ ' aborting! Error: {0}'.format(err)) return False # Bind config object to device conf = Config(dev) # Parse options for config template, if present if args.data: data = json.loads(args.data) else: data = {} # Lock configuration to make sure noone else alter it at the same time try: conf.lock() except LockError: logging.error('Unable to lock configuration! Aborting.') dev.close() return False # Push template-based change to device logging.info('Pushing configuration change to device {0}...'.format(args.host)) try: conf.load(template_path=args.templatefile, template_vars=data) except ValueError as err: logging.error('Error when pushing configuration change: ' + \ '{0}'.format(err.message)) except Exception as err: if err.rsp.find('.//ok') is None: rpc_msg = err.rsp.findtext('.//error-message') logging.error('Unable to load configuration changes on device: ' + \ '{0}'.format(rpc_msg)) else: logging.error('Unable to load configuration changes on device.') # Close device and return failure dev.close() return False # Commit changes to device try: conf.commit() except CommitError: logging.error('Unable to commit configuration!') dev.close() return False # Unlock configuration after change try: conf.unlock() except UnlockError: logging.error('Unable to unlock configuration, exiting.') dev.close() # Return success logging.info('Finished configuration change of {0} successfully.'.format(args.host)) return True
#!/usr/bin/env python from jnpr.junos import Device from jnpr.junos.utils.config import Config from jnpr.junos.exception import LockError from pprint import pprint from jnpr_devices import srx2 jnpr_device = Device(**srx2) jnpr_device.open() jnpr_device.timeout = 60 # 3a jnpr_device_cfg = Config(jnpr_device) jnpr_device_cfg.lock() try: jnpr_device_cfg.lock() except LockError as e: print("Config session already locked") # 3b print("Set new hostname in candidate config") jnpr_device_cfg.load("set system host-name srx2-new-name", format="set", merge=True) # 3c print("Check diff") print(jnpr_device_cfg.diff())
from getpass import getpass from jnpr.junos.utils.config import Config pwd = getpass() # Create a Device instance a_device = Device(host="50.76.53.27", user="******", password=pwd) # Establish a connection with Juniper device a_device.open() # Create a Config instance cfg = Config(a_device) # Lock the Juniper device while you are doing the config changes cfg.lock() # 1. Load config via load-set command cfg.load("set system host-name juniper-test-name", format="set", merge=True) # Show the differences between running-config and candidate config print cfg.diff() # cfg.commit() # Rollback the candidate config changes cfg.rollback(0) # 2. Load new config via 'test_config.conf' file (using curly braces) # Create test_config.conf file first in the currently-running Linux directory
class Netconf(object): def __init__(self): 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'] port = params.get('port') or 830 user = params['username'] passwd = params['password'] try: self.device = Device(host, user=user, passwd=passwd, port=port, gather_facts=False) 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'): #def load_config(self, candidate, update='merge', comment=None, # confirm=None, format='text', commit=True): 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 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
class Netconf(object): def __init__(self): if not HAS_PYEZ: raise NetworkError( msg='junos-eznc >= 1.2.2 is required but does not appear to be installed. ' 'It can be installed using `pip install junos-eznc`' ) if not HAS_JXMLEASE: raise NetworkError( msg='jxmlease is required but does not appear to be installed. ' 'It can be installed using `pip install jxmlease`' ) self.device = None self.config = None self._locked = False self._connected = False self.default_output = 'xml' def raise_exc(self, msg): if self.device: if self._locked: self.config.unlock() self.disconnect() raise NetworkError(msg) def connect(self, params, **kwargs): host = params['host'] kwargs = dict() kwargs['port'] = params.get('port') or 830 kwargs['user'] = params['username'] if params['password']: kwargs['passwd'] = params['password'] if params['ssh_keyfile']: kwargs['ssh_private_key_file'] = params['ssh_keyfile'] kwargs['gather_facts'] = False try: self.device = Device(host, **kwargs) self.device.open() except ConnectError: exc = get_exception() self.raise_exc('unable to connect to %s: %s' % (host, str(exc))) self.config = Config(self.device) self._connected = True def disconnect(self): try: self.device.close() except AttributeError: pass self._connected = False ### Command methods ### def run_commands(self, commands): responses = list() for cmd in commands: meth = getattr(self, cmd.args.get('command_type')) responses.append(meth(str(cmd), output=cmd.output)) for index, cmd in enumerate(commands): if cmd.output == 'xml': responses[index] = xml_to_json(responses[index]) elif cmd.args.get('command_type') == 'rpc': responses[index] = str(responses[index].text).strip() elif 'RpcError' in responses[index]: raise NetworkError(responses[index]) return responses def cli(self, commands, output='xml'): '''Send commands to the device.''' try: return self.device.cli(commands, format=output, warning=False) except (ValueError, RpcError): exc = get_exception() self.raise_exc('Unable to get cli output: %s' % str(exc)) def rpc(self, command, output='xml'): name, kwargs = rpc_args(command) meth = getattr(self.device.rpc, name) reply = meth({'format': output}, **kwargs) return reply ### Config methods ### def get_config(self, config_format="text"): if config_format not in SUPPORTED_CONFIG_FORMATS: self.raise_exc(msg='invalid config format. Valid options are ' '%s' % ', '.join(SUPPORTED_CONFIG_FORMATS)) ele = self.rpc('get_configuration', output=config_format) if config_format == 'text': return unicode(ele.text).strip() else: return ele def load_config(self, config, commit=False, replace=False, confirm=None, comment=None, config_format='text', overwrite=False): if all([replace, overwrite]): self.raise_exc('setting both replace and overwrite to True is invalid') if replace: merge = False overwrite = False elif overwrite: merge = True overwrite = False else: merge = True overwrite = False if overwrite and config_format == 'set': self.raise_exc('replace cannot be True when config_format is `set`') self.lock_config() try: candidate = '\n'.join(config) self.config.load(candidate, format=config_format, merge=merge, overwrite=overwrite) except ConfigLoadError: exc = get_exception() self.raise_exc('Unable to load config: %s' % str(exc)) diff = self.config.diff() self.check_config() if all((commit, diff)): self.commit_config(comment=comment, confirm=confirm) self.unlock_config() return diff def save_config(self): raise NotImplementedError ### end of Config ### def get_facts(self, refresh=True): if refresh: self.device.facts_refresh() return self.device.facts def unlock_config(self): try: self.config.unlock() self._locked = False except UnlockError: exc = get_exception() raise NetworkError('unable to unlock config: %s' % str(exc)) def lock_config(self): try: self.config.lock() self._locked = True except LockError: exc = get_exception() raise NetworkError('unable to lock config: %s' % str(exc)) def check_config(self): if not self.config.commit_check(): self.raise_exc(msg='Commit check failed') def commit_config(self, comment=None, confirm=None): try: kwargs = dict(comment=comment) if confirm and confirm > 0: kwargs['confirm'] = confirm return self.config.commit(**kwargs) except CommitError: exc = get_exception() raise NetworkError('unable to commit config: %s' % str(exc)) def confirm_commit(self, checkonly=False): try: resp = self.rpc('get_commit_information') needs_confirm = 'commit confirmed, rollback' in resp[0][4].text if checkonly: return needs_confirm return self.commit_config() except IndexError: # if there is no comment tag, the system is not in a commit # confirmed state so just return pass def rollback_config(self, identifier, commit=True, comment=None): self.lock_config() try: self.config.rollback(identifier) except ValueError: exc = get_exception() self.raise_exc('Unable to rollback config: $s' % str(exc)) diff = self.config.diff() if commit: self.commit_config(comment=comment) self.unlock_config() return diff
def run(self): # import pdb; pdb.set_trace() # dbg dev = Device(host=self.host, user=self.user, password=self.passw) try: dev.open(auto_probe=7) except: self.result += "Could not connect to host\n" return if not self.mode: self.result += "A mode of operation must be specified" elif self.mode == "configure": confc = Config(dev) if self.action == "commit": self.result += confc.commit(confirm=True, comment="Commited " + str( datetime.datetime.now() ) + " by jCnC") elif self.action == "commit_check": if confc.commit_check(): self.result += "Commit Check Succeeds" else: self.result += "Commit Check Failed" elif self.action == "diff": x = int(self.param) self.result += confc.diff() #self.param) elif self.action == "load": self.result += confc.load(path=param, overwrite=True, format='conf') elif self.action == "lock": self.result += confc.lock() elif self.action == "rescue": self.result += confc.rescue(param) elif self.action == "rollback": self.result += confc.rollback(param) elif self.action == "save": shell = self.start_shell() stdin, stdout, stderr = shell.exec_command("cli show configuration | cat") config = "" for line in stdout.readlines(): self.result += line config += line ## check for host dir, create if not found hostpath = self.host if not os.path.exists(hostpath): os.makedirs(hostpath) hostpath += "/configuration" ## copy file into directory with open(hostpath, 'w') as output: output.write(config) shell.exec_command("rm /tmp/configuration\n") shell.close elif self.action == "unlock": self.result += confc.unlock() else: self.result += "Configuration Action not found" elif self.mode == "software": softw = SW(dev) if self.action == "install": hash = str('') with open(param+'.md5') as hashfile: hash = hashfile.read() hashfile.closed() self.action += softw.install(param, remote_path='/var/tmp', progress=dev, validate=False, checksum=hash, cleanfs=False, no_copy=False, timout=1800) elif action == "rollback": self.action += softw.rollback() elif self.mode == "cli": shell = self.start_shell() if self.action == "terminal": stdin, stdout, stderr = shell.exec_command("cli") stdin.write(self.param + '\n') stdin.write("exit\n") stdin.flush() for line in stdout.readlines(): self.result += line elif self.action == "file": self.result += "\n" stdin, stdout, stderr = shell.exec_command("cli") cfile = open(self.param, 'r') for line in cfile: stdin.write(line + '\n') stdin.write("exit\n") data = stdout.readlines() for line in data: self.result += "\n" + line shell.close() elif self.mode == "info": shell = self.start_shell() if self.action == "alarms": stdin, stdout, stderr = shell.exec_command("cli show chassis alarms") data = stdout.readlines() for line in data: self.result += line elif self.action == "active_ports": stdin, stdout, stderr = shell.exec_command('cli show interfaces terse | grep -v "\.0" | grep -v down') data = stdout.readlines() for line in data: self.result += line elif self.action == "inactive_ports": stdin, stdout, stderr = shell.exec_command('cli show interfaces terse | grep -v "\.0" | grep down') data = stdout.readlines() for line in data: self.result += line else: self.result += "Information Action not found" shell.close() else: self.result = "Operation Mode not found" dev.close() self.result += "\n"