def shutdown(time=0): ''' Shuts down the device after the given time. Usage: .. code-block:: bash salt 'device_name' junos.shutdown 10 Options: * time: Time in seconds after which the device should shutdown (default=0) ''' conn = __proxy__['junos.conn']() ret = dict() sw = SW(conn) try: shut = sw.poweroff() shut(time) ret['message'] = 'Successfully powered off.' ret['out'] = False except Exception as exception: ret['message'] = 'Could not poweroff' ret['out'] = False return ret
def main(): #iterate over csv for row in devList: #Make Device Connection dev = Device(host=row[1], user=userName, password=userPassword) try: #Print Opening Header for Status now1 = datetime.datetime.now() pprint("Work starts on " + row[0] + " | " + row[1] + " at " + now1.strftime("%Y-%m-%d %H:%M")) #Open Device with Custom Timer dev.open() dev.timeout = 900 except Exception as err: sys.stderr.write('Cannot connect to device: {0}\n'.format(err)) #Do RPC/Work try: #Start Work here #Create an instance of SW sw = SW(dev) try: ok = sw.install(package=package, remote_path=remote_path, progress=myprogress, validate=validate, no_copy=noCopy, timeout=1800) except Exception as err: msg = 'Unable to install software, {0}'.format(err) print(msg) ok = False if ok is True: print('Software installation complete. Rebooting') rsp = sw.reboot() print('Upgrade pending reboot cycle, please be patient.') print(rsp) else: msg = 'Unable to install software, {0}'.format(ok) print(msg) #Write Element Seperator print("+++++++++++++++++++++++++++++++++++++++++++++++++") #Close Device dev.close() except Exception as err: sys.stderr.write('Cannot perform RPC on device: ' + row[1] + '\n'.format(err)) print("+++++++++++++++++++++++++++++++++++++++++++++++++")
def main(): print("\nWelcome to Junos Upgrade Tool \n") # Request which code to upgrade with fileList = getFileList(code_path) package = getOptionAnswer("Choose a junos package", fileList) package = code_path + package # Request IP for the system to upgrade host = getInputAnswer("IP Address of the host") # Get username and password parameters username=getInputAnswer("\nEnter your device username") password=getpass(prompt="\nEnter your device password: ") # initialize logging logging.basicConfig(filename=logfile, level=logging.INFO, format='%(asctime)s:%(name)s: %(message)s') logging.getLogger().name = host sys.stdout.write('Information logged in {0}\n'.format(logfile)) # verify package exists if (os.path.isfile(package)): found = True else: msg = 'Software package does not exist: {0}. '.format(package) sys.exit(msg + '\nExiting program') dev = Device(host,user=username,password=password) try: dev.open() except Exception as err: sys.stderr.write('Cannot connect to device: {0}\n'.format(err)) return # Increase the default RPC timeout to accommodate install operations dev.timeout = 300 # Create an instance of SW sw = SW(dev) try: do_log('Starting the software upgrade process: {0}'.format(package)) ok = sw.install(package=package, remote_path=remote_path, progress=update_progress, validate=validate) except Exception as err: msg = 'Unable to install software, {0}'.format(err) do_log(msg, level='error') else: if ok is True: do_log('Software installation complete. Rebooting') rsp = sw.reboot() do_log('Upgrade pending reboot cycle, please be patient.') do_log(rsp) # End the NETCONF session and close the connection dev.close()
def main(): # iterate over csv for row in devList: # Make Device Connection dev = Device(host=row[1], user=userName, password=userPassword) try: # Print Opening Header for Status now1 = datetime.datetime.now() pprint("Work starts on " + row[0] + " | " + row[1] + " at " + now1.strftime("%Y-%m-%d %H:%M")) # Open Device with Custom Timer dev.open() dev.timeout = 900 except Exception as err: sys.stderr.write("Cannot connect to device: {0}\n".format(err)) # Do RPC/Work try: # Start Work here # Create an instance of SW sw = SW(dev) try: ok = sw.safe_copy( package=package, remote_path=remote_path, progress=myprogress, clean_fs=freeSpace, timeout=1800 ) except Exception as err: msg = "Unable to copy software, {0}".format(err) print (msg) ok = False if ok is True: print ("Software copy complete.") else: msg = "Unable to copy software, {0}".format(ok) print (msg) # Write Element Seperator print ("+++++++++++++++++++++++++++++++++++++++++++++++++") # Close Device dev.close() except Exception as err: sys.stderr.write("Cannot perform RPC on device: " + row[1] + "\n".format(err)) print ("+++++++++++++++++++++++++++++++++++++++++++++++++")
def install_package(module, device): junos = SW(device) package = module.params['src'] no_copy = module.params['no_copy'] def progress_log(dev, report): module.log(report) module.log('installing package') result = junos.install(package, progress=progress_log, no_copy=no_copy) if not result: module.fail_json(msg='Unable to install package on device') if module.params['reboot']: module.log('rebooting system') junos.reboot()
def main(): # initialize logging logging.basicConfig(filename=logfile, level=logging.INFO, format='%(asctime)s:%(name)s: %(message)s') logging.getLogger().name = host logging.getLogger().addHandler(logging.StreamHandler()) logging.info('Information logged in {0}'.format(logfile)) # verify package exists if not (os.path.isfile(package)): msg = 'Software package does not exist: {0}. '.format(package) logging.error(msg) sys.exit() try: dev = Device(host=host) dev.open() except ConnectError as err: logging.error('Cannot connect to device: {0}\n'.format(err)) return # Create an instance of SW sw = SW(dev) try: logging.info('Starting the software upgrade process: {0}'.format(package)) ok = sw.install(package=package, remote_path=remote_path, progress=update_progress, validate=validate) except Exception as err: msg = 'Unable to install software, {0}'.format(err) logging.error(msg) ok = False if ok is True: logging.info('Software installation complete. Rebooting') # rsp = sw.reboot() logging.info('Upgrade pending reboot cycle, please be patient.') logging.info(rsp) else: msg = 'Unable to install software, {0}'.format(ok) logging.error(msg) # End the NETCONF session and close the connection dev.close()
def install_package(module, device): junos = SW(device) package = module.params['src'] no_copy = module.params['no_copy'] validate = module.params['validate'] force_host = module.params['force_host'] issu = module.params['issu'] def progress_log(dev, report): module.log(report) module.log('installing package') result = junos.install(package, progress=progress_log, no_copy=no_copy, validate=validate, force_host=force_host, issu=issu) if not result: module.fail_json(msg='Unable to install package on device') if module.params['reboot']: module.log('rebooting system') junos.reboot()
def test_sw_put_ftp(self, mock_ftp_put): dev = Device(host='1.1.1.1', user='******', password='******', mode='telnet', port=23, gather_facts=False) dev.facts = facts sw = SW(dev) sw.put(package='test.tgz') self.assertTrue( call('test.tgz', '/var/tmp') in mock_ftp_put.mock_calls)
def __init__(self, host, username, password, *args, **kwargs): super(JunosDevice, self).__init__(host, username, password, *args, vendor='juniper', device_type='juniper_junos_netconf', **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativdSW(self.native)
def main(): # initialize logging logging.basicConfig(filename=logfile, level=logging.INFO, format='%(asctime)s:%(name)s: %(message)s') logging.getLogger().name = host logging.getLogger().addHandler(logging.StreamHandler()) logging.info('Information logged in {0}'.format(logfile)) # verify package exists if not (os.path.isfile(package)): msg = 'Software package does not exist: {0}. '.format(package) logging.error(msg) sys.exit() dev = Device(host=host, user=junos_username, passwd=junos_password) try: dev.open() except ConnectError as err: logging.error('Cannot connect to device: {0}\n'.format(err)) return # Create an instance of SW sw = SW(dev) try: logging.info( 'Starting the software upgrade process: {0}'.format(package)) #ok = sw.install(package=package,progress=update_progress) except Exception as err: msg = 'Unable to install software, {0}'.format(err) logging.error(msg) ok = False #UPGRADED SUCCESSFULLY logging.info("!!!!!!!!!!!!!") #logging.info(dev.cli("request system firmware upgrade pic pic-slot 0 fpc-slot 1")) print dev.cli("show system firmware") logging.info("!!!!!!!!!!!!!") if ok is True: logging.info('Software installation complete. Rebooting') #rsp = sw.reboot() logging.info('Upgrade pending reboot cycle, please be patient.') logging.info(rsp) else: msg = 'Unable to install software, {0}'.format(ok) logging.error(msg) # End the NETCONF session and close the connection dev.close()
def test_sw_put_ftp(self, mock_ftp_put): dev = Device( host="1.1.1.1", user="******", password="******", mode="telnet", port=23, gather_facts=False, ) dev.facts = facts sw = SW(dev) sw.put(package="test.tgz") self.assertTrue(call("test.tgz", "/var/tmp") in mock_ftp_put.mock_calls)
def junos_auto_install(self, host_ip, path, device): """ Use PyEz to secure install new junos version to remote host """ sw = SW(device) path = os.path.join(os.getcwd(), path) print path, type(path) try: ok = sw.install(package=path, progress=install_progress) except Exception as err: print("Install error") raise err if ok is True: print("\nSoftware installation succeeded") else: print(ok) time.sleep(30) try: rsp = sw.reboot() print(rsp) except exception.ConnectClosedError: print("About to loose connection ..") finally: print("Please wait for the box to wake-up!") time.sleep(120) dev = self.device_connect(host_ip) feeds = dev.probe(10) while not feeds: feeds = dev.probe(20) #print("probing in 20 seconds interval") print("\n\nConnecting to box now ...") dev.open() print("Connected") print("New version:") self.print_base_info(dev) return dev
def __init__(self, host, username, password, *args, **kwargs): super(JunosDevice, self).__init__(host, username, password, *args, vendor='juniper', device_type=JNPR_DEVICE_TYPE, **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativdSW(self.native)
def install_package(module): junos = SW(module.connection.device) package = module.params['src'] no_copy = module.params['no_copy'] progress_log = lambda x, y: module.log(y) module.log('installing package') result = junos.install(package, progress=progress_log, no_copy=no_copy) if not result: module.fail_json(msg='Unable to install package on device') if module.params['reboot']: module.log('rebooting system') junos.reboot()
def InstallOnHost(hostname, username, password, softwareFilePath, rebootTime): dev = Device(host=hostname, user=username, password=password) softw = SW(dev) hash = SW.local_md5(softwareFilePath) softw.install(softwareFilePath, remote_path='/var/tmp', progress=dev, validate=False, checksum=hash, cleanfs=False, no_copy=False, timeout=1800) if rebootTime != 0: softw.reboot(rebootTime) dev.close()
def __init__(self, host, username, password, *args, **kwargs): super().__init__(host, username, password, *args, device_type="juniper_junos_netconf", **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativeSW(self.native)
def reboot(self, timer=0, **kwargs): """ Reload the controller or controller pair. Args: timer (int, optional): The time to wait before reloading. Defaults to 0. Example: >>> device = JunosDevice(**connection_args) >>> device.reboot() >>> """ if kwargs.get("confirm"): warnings.warn("Passing 'confirm' to reboot method is deprecated.", DeprecationWarning) self.sw = JunosNativeSW(self.native) self.sw.reboot(in_min=timer)
def main(): module = AnsibleModule(argument_spec=dict(host=dict(type='str', required=True), port=dict(type='int', default=830), user=dict(type='str', default='root'), password=dict(type='str', default=None, no_log=True), license=dict(type='str', required=True), shutdown=dict(type='bool', default=False)), supports_check_mode=True) args = module.params if not isfile(args['license']): module.fail_json(msg="license not found: {0}".format(args['license'])) return dev = Device(args['host'], user=args['user'], password=args['password'], port=args['port']).open() with MyStartShell(dev) as sh: license = open(args['license']).read().splitlines() for line in license: sh.run('echo %s >> /var/tmp/license.lic' % line) sh.run('cli -c "request system license add /var/tmp/license.lic"') if args['shutdown']: try: SW(dev).poweroff() except RpcError: pass module.exit_json(failed=False, changed=True)
#!/usr/bin/python ''' Script para hacer un shutdown en 5 minutos ''' from jnpr.junos import Device from jnpr.junos.utils.sw import SW import time if __name__ == '__main__': dev = Device(host='192.168.108.199', user='******', passwd='lab123') dev.open() mi_sw = SW(dev) print mi_sw.poweroff(5) print "Fin del script.." time.sleep(2) dev.close()
class TestSW(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.dev._facts = facts self.sw = self.get_sw() @patch('jnpr.junos.Device.execute') def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch('__builtin__.open', mock_open(), create=True): import jnpr.junos.utils.sw with open('foo') as h: h.read.side_effect = ('abc', 'a', '') jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_RE) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch('__builtin__.open') def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha256(package), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855') @patch('__builtin__.open') def test_sw_local_md5(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_md5(package), 'd41d8cd98f00b204e9800998ecf8427e') @patch('__builtin__.open') def test_sw_local_sha1(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha1(package), 'da39a3ee5e6b4b0d3255bfef95601890afd80709') def test_sw_progress(self): with self.capture(SW.progress, self.dev, 'running') as output: self.assertEqual('1.1.1.1: running\n', output) @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_put(self, mock_scp_put, mock_scp): # mock_scp_put.side_effect = self.mock_put package = 'test.tgz' self.sw.put(package) self.assertTrue(call('test.tgz', '/var/tmp') in mock_scp_put.mock_calls) @patch('jnpr.junos.utils.scp.SCP.__exit__') @patch('jnpr.junos.utils.scp.SCP.__init__') @patch('jnpr.junos.utils.scp.SCP.__enter__') def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = 'test.tgz' mock_scp.side_effect = self._fake_scp self.sw.put(package, progress=self._myprogress) self.assertEqual(mock_scp.call_args_list[0][1]['progress'].by10pct, 50) def _fake_scp(self, *args, **kwargs): progress = kwargs['progress'] progress('test.tgz', 100, 50) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgadd(package)) @patch('jnpr.junos.Device.execute') def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'package.tgz' self.assertTrue(self.sw.validate(package)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() SW.local_md5 = MagicMock() self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True, checksum='96a35ab371e1ca10408c3caecdbd8a67')) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() SW.local_md5 = MagicMock() self.assertFalse(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) SW.local_md5.assert_called_with(package) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() SW.local_md5 = MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67') self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'install.tgz' self.sw.put = MagicMock() SW.local_md5 = MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67') self.assertTrue(self.sw.install(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.utils.sw.SW.safe_copy') def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install('file')) @patch('jnpr.junos.utils.sw.SW.validate') def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install('file', validate=True, no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_mx(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_rollback(self, mock_execute): # we need proper xml for this test case, update request-package-roll # back.xml mock_execute.side_effect = self._mock_manager self.assertEqual(self.sw.rollback(), '') def test_sw_inventory(self): self.sw.dev.rpc.file_list = \ MagicMock(side_effect=self._mock_manager) self.assertEqual(self.sw.inventory, {'current': None, 'rollback': None}) @patch('jnpr.junos.Device.execute') def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.poweroff()) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.poweroff()) def _myprogress(self, dev, report): pass @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply())._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs: if 'path' in kwargs: if kwargs['path'] == '/packages': return self._read_file('file-list_dir.xml') 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 TestSW(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.dev._facts = facts self.sw = self.get_sw() @patch("jnpr.junos.Device.execute") def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch("ncclient.operations.session.CloseSession.request") def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch("__builtin__.open", mock_open(), create=True): import jnpr.junos.utils.sw with open("foo") as h: h.read.side_effect = ("abc", "a", "") jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch("jnpr.junos.Device.execute") def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_RE) @patch("jnpr.junos.Device.execute") def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch("__builtin__.open") def test_sw_local_sha256(self, mock_built_open): package = "test.tgz" self.assertEqual( SW.local_sha256(package), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934" "ca495991b7852b855" ) @patch("__builtin__.open") def test_sw_local_md5(self, mock_built_open): package = "test.tgz" self.assertEqual(self.sw.local_md5(package), "d41d8cd98f00b204e9800998ecf8427e") @patch("__builtin__.open") def test_sw_local_sha1(self, mock_built_open): package = "test.tgz" self.assertEqual(SW.local_sha1(package), "da39a3ee5e6b4b0d3255bfef95601890afd80709") def test_sw_progress(self): with self.capture(SW.progress, self.dev, "running") as output: self.assertEqual("1.1.1.1: running\n", output) @patch("paramiko.SSHClient") @patch("scp.SCPClient.put") def test_sw_put(self, mock_scp_put, mock_scp): # mock_scp_put.side_effect = self.mock_put package = "test.tgz" self.sw.put(package) self.assertTrue(call("test.tgz", "/var/tmp") in mock_scp_put.mock_calls) @patch("jnpr.junos.utils.scp.SCP.__exit__") @patch("jnpr.junos.utils.scp.SCP.__init__") @patch("jnpr.junos.utils.scp.SCP.__enter__") def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = "test.tgz" mock_scp.side_effect = self._fake_scp self.sw.put(package, progress=self._myprogress) self.assertEqual(mock_scp.call_args_list[0][1]["progress"].by10pct, 50) def _fake_scp(self, *args, **kwargs): progress = kwargs["progress"] progress("test.tgz", 100, 50) @patch("jnpr.junos.Device.execute") def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.assertTrue(self.sw.pkgadd(package)) @patch("jnpr.junos.Device.execute") def test_sw_pkgadd_pkg_set(self, mock_execute): mock_execute.side_effect = self._mock_manager pkg_set = ["abc.tgz", "pqr.tgz"] self.sw._mixed_VC = True self.sw.pkgadd(pkg_set) self.assertEqual([i.text for i in mock_execute.call_args[0][0].findall("set")], pkg_set) @patch("jnpr.junos.Device.execute") def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "package.tgz" self.assertTrue(self.sw.validate(package)) @patch("jnpr.junos.Device.execute") def test_sw_remote_checksum_not_found(self, mock_execute): xml = """<rpc-error> <error-severity>error</error-severity> <error-message> md5: /var/tmp/123: No such file or directory </error-message> </rpc-error>""" mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = "test.tgz" self.assertEqual(self.sw.remote_checksum(package), None) @patch("jnpr.junos.Device.execute") def test_sw_remote_checksum_not_rpc_error(self, mock_execute): xml = """<rpc-error> <error-severity>error</error-severity> <error-message> something else! </error-message> </rpc-error>""" mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = "test.tgz" with self.assertRaises(RpcError): self.sw.remote_checksum(package) @patch("jnpr.junos.Device.execute") def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "safecopy.tgz" self.sw.put = MagicMock() with patch("jnpr.junos.utils.sw.SW.local_md5"): self.assertTrue( self.sw.safe_copy( package, progress=self._myprogress, cleanfs=True, checksum="96a35ab371e1ca10408c3caecdbd8a67" ) ) @patch("jnpr.junos.Device.execute") def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = "safecopy.tgz" self.sw.put = MagicMock() with patch("jnpr.junos.utils.sw.SW.local_md5"): self.assertFalse(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch("jnpr.junos.Device.execute") def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "safecopy.tgz" self.sw.put = MagicMock() with patch("jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="96a35ab371e1ca10408c3caecdbd8a67")): self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch("jnpr.junos.Device.execute") def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "install.tgz" self.sw.put = MagicMock() with patch("jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="96a35ab371e1ca10408c3caecdbd8a67")): self.assertTrue(self.sw.install(package, progress=self._myprogress, cleanfs=True)) @patch("jnpr.junos.utils.sw.SW.safe_copy") def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install("file")) @patch("jnpr.junos.utils.sw.SW.validate") def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install("file", validate=True, no_copy=True)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_multi_mx(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install("file", no_copy=True)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ("version_RE0", "version_RE1") self.assertTrue(self.sw.install("file", no_copy=True)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw._RE_list = ("version_RE0", "version_RE1") self.assertTrue(self.sw.install(pkg_set=["abc.tgz", "pqr.tgz"], no_copy=True)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc_with_copy(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.put = MagicMock() self.sw.remote_checksum = MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e") self.sw._RE_list = ("version_RE0", "version_RE1") with patch("jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e")): self.assertTrue(self.sw.install(pkg_set=["install.tgz", "install.tgz"], cleanfs=False)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc_safe_copy_false(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.safe_copy = MagicMock(return_value=False) self.sw.remote_checksum = MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e") self.sw._RE_list = ("version_RE0", "version_RE1") with patch("jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e")): self.assertFalse(self.sw.install(pkg_set=["install.tgz", "install.tgz"], cleanfs=False)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc_ValueError(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.remote_checksum = MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e") self.sw._RE_list = ("version_RE0", "version_RE1") with patch("jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e")): self.assertRaises(ValueError, self.sw.install, pkg_set="install.tgz", cleanfs=False) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc_TypeError(self, mock_pkgadd): self.assertRaises(TypeError, self.sw.install, cleanfs=False) @patch("jnpr.junos.Device.execute") def test_sw_install_kwargs_force_host(self, mock_execute): self.sw.install("file", no_copy=True, force_host=True) rpc = """<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>""" self.assertEqual(etree.tostring(mock_execute.call_args[0][0]), rpc) @patch("jnpr.junos.Device.execute") def test_sw_rollback(self, mock_execute): rsp = "<rpc-reply><output>junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot</output></rpc-reply>" mock_execute.side_effect = etree.XML(rsp) msg = "junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot" self.assertEqual(self.sw.rollback(), msg) @patch("jnpr.junos.Device.execute") def test_sw_rollback_multi(self, mock_execute): mock_execute.side_effect = self._mock_manager msg = "{'fpc1': \"Junos version 'D10.2' will become active at next reboot\", 'fpc0': 'JUNOS version \"D10.2\" will become active at next reboot'}" self.assertEqual(self.sw.rollback(), msg) @patch("jnpr.junos.Device.execute") def test_sw_rollback_multi_exception(self, mock_execute): fname = "request-package-rollback-multi-error.xml" mock_execute.side_effect = self._read_file(fname) self.assertRaises(SwRollbackError, self.sw.rollback) @patch("jnpr.junos.Device.execute") def test_sw_rollback_exception(self, mock_execute): rsp = "<rpc-reply><output>WARNING: Cannot rollback, /packages/junos.old is not valid</output></rpc-reply>" mock_execute.side_effect = etree.XML(rsp) self.assertRaises(SwRollbackError, self.sw.rollback) def test_sw_inventory(self): self.sw.dev.rpc.file_list = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.sw.inventory, {"current": None, "rollback": None}) @patch("jnpr.junos.Device.execute") def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue("Shutdown NOW" in self.sw.reboot()) @patch("jnpr.junos.Device.execute") def test_sw_reboot_at(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue("Shutdown at" in self.sw.reboot(at="201407091815")) @patch("jnpr.junos.Device.execute") def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue("Shutdown NOW" in self.sw.reboot()) @patch("jnpr.junos.Device.execute") def test_sw_reboot_mixed_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw.reboot() self.assertTrue("all-members" in etree.tostring(mock_execute.call_args[0][0])) @patch("jnpr.junos.Device.execute") def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML("<rpc-reply><a>test</a></rpc-reply>") mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch("jnpr.junos.Device.execute") def test_sw_reboot_exception_RpcTimeoutError(self, mock_execute): rsp = (self.dev, "request-reboot", 60) mock_execute.side_effect = RpcTimeoutError(*rsp) self.assertRaises(Exception, self.sw.reboot) @patch("jnpr.junos.Device.execute") def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue("Shutdown NOW" in self.sw.poweroff()) @patch("jnpr.junos.Device.execute") def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML("<rpc-reply><a>test</a></rpc-reply>") mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch("jnpr.junos.Device.execute") def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue("Shutdown NOW" in self.sw.poweroff()) def _myprogress(self, dev, report): pass @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), "rpc-reply", fname) foo = open(fpath).read() rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply())._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs: # Little hack for mocked execute if "dev_timeout" in kwargs: return self._read_file(args[0].tag + ".xml") if "path" in kwargs: if kwargs["path"] == "/packages": return self._read_file("file-list_dir.xml") device_params = kwargs["device_params"] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].find("at") is not None: return self._read_file("request-reboot-at.xml") else: return self._read_file(args[0].tag + ".xml")
def shutdown(**kwargs): ''' Shut down (power off) or reboot a device running Junos OS. This includes all Routing Engines in a Virtual Chassis or a dual Routing Engine system. .. note:: One of ``shutdown`` or ``reboot`` must be set to ``True`` or no action will be taken. shutdown : False Set this to ``True`` if you want to shutdown the machine. This is a safety mechanism so that the user does not accidentally shutdown the junos device. reboot : False If ``True``, reboot instead of shutting down at Used when rebooting, to specify the date and time the reboot should take place. The value of this option must match the JunOS CLI reboot syntax. in_min Used when shutting down. Specify the delay (in minutes) before the device will be shut down. CLI Examples: .. code-block:: bash salt 'device_name' junos.shutdown reboot=True salt 'device_name' junos.shutdown shutdown=True in_min=10 salt 'device_name' junos.shutdown shutdown=True ''' conn = __proxy__['junos.conn']() ret = dict() sw = SW(conn) op = dict() if '__pub_arg' in kwargs: if kwargs['__pub_arg']: if isinstance(kwargs['__pub_arg'][-1], dict): op.update(kwargs['__pub_arg'][-1]) else: op.update(kwargs) if 'shutdown' not in op and 'reboot' not in op: ret['message'] = \ 'Provide either one of the arguments: shutdown or reboot.' ret['out'] = False return ret try: if 'reboot' in op and op['reboot']: shut = sw.reboot elif 'shutdown' in op and op['shutdown']: shut = sw.poweroff else: ret['message'] = 'Nothing to be done.' ret['out'] = False return ret if 'in_min' in op: shut(in_min=op['in_min']) elif 'at' in op: shut(at=op['at']) else: shut() ret['message'] = 'Successfully powered off/rebooted.' ret['out'] = True except Exception as exception: ret['message'] = \ 'Could not poweroff/reboot beacause "{0}"'.format(exception) ret['out'] = False return ret
def test_sw_local_sha1(self, mock_built_open): package = "test.tgz" self.assertEqual( SW.local_checksum(package, algorithm="sha1"), "da39a3ee5e6b4b0d3255bfef95601890afd80709", )
def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC)
def test_sw_local_sha1(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha1(package), 'da39a3ee5e6b4b0d3255bfef95601890afd80709')
class JunosDevice(BaseDevice): """Juniper JunOS Device Implementation.""" vendor = "juniper" def __init__(self, host, username, password, *args, **kwargs): super().__init__(host, username, password, *args, device_type="juniper_junos_netconf", **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativeSW(self.native) def _file_copy_local_file_exists(self, filepath): return os.path.isfile(filepath) def _file_copy_local_md5(self, filepath, blocksize=2**20): if self._file_copy_local_file_exists(filepath): m = hashlib.md5() with open(filepath, "rb") as f: buf = f.read(blocksize) while buf: m.update(buf) buf = f.read(blocksize) return m.hexdigest() def _file_copy_remote_md5(self, filename): return self.fs.checksum(filename) def _get_interfaces(self): eth_ifaces = EthPortTable(self.native) eth_ifaces.get() loop_ifaces = LoopbackTable(self.native) loop_ifaces.get() ifaces = eth_ifaces.keys() ifaces.extend(loop_ifaces.keys()) return ifaces def _image_booted(self, image_name, **vendor_specifics): raise NotImplementedError def _uptime_components(self, uptime_full_string): match_days = re.search(r"(\d+) days?", uptime_full_string) match_hours = re.search(r"(\d+) hours?", uptime_full_string) match_minutes = re.search(r"(\d+) minutes?", uptime_full_string) match_seconds = re.search(r"(\d+) seconds?", uptime_full_string) days = int(match_days.group(1)) if match_days else 0 hours = int(match_hours.group(1)) if match_hours else 0 minutes = int(match_minutes.group(1)) if match_minutes else 0 seconds = int(match_seconds.group(1)) if match_seconds else 0 return days, hours, minutes, seconds def _uptime_to_seconds(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components( uptime_full_string) seconds += days * 24 * 60 * 60 seconds += hours * 60 * 60 seconds += minutes * 60 return seconds def _uptime_to_string(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components( uptime_full_string) return "%02d:%02d:%02d:%02d" % (days, hours, minutes, seconds) def _wait_for_device_reboot(self, timeout=3600): start = time.time() while time.time() - start < timeout: try: self.open() return except: # noqa E722 pass raise RebootTimeoutError(hostname=self.facts["hostname"], wait_time=timeout) def backup_running_config(self, filename): with open(filename, "w") as f: f.write(self.running_config) @property def boot_options(self): return self.facts["os_version"] def checkpoint(self, filename): self.save(filename) def close(self): if self.connected: self.native.close() def config(self, command, format="set"): try: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandError(command, e.message) def config_list(self, commands, format="set"): try: for command in commands: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandListError(commands, command, e.message) @property def connected(self): return self.native.connected @property def facts(self): if self._facts is None: native_facts = self.native.facts try: native_uptime_string = native_facts["RE0"]["up_time"] except (AttributeError, TypeError): native_uptime_string = None self._facts = { "hostname": native_facts.get("hostname"), "fqdn": native_facts.get("fqdn"), "model": native_facts.get("model"), "uptime": None, "uptime_string": None, "serial_number": native_facts.get("serialnumber"), "interfaces": self._get_interfaces(), "vendor": self.vendor, "version": native_facts.get("version"), } # TODO: Use a more reliable method for determining uptime (show system uptime) if native_uptime_string is not None: self._facts["uptime"] = self._uptime_to_seconds( native_uptime_string) self._facts["uptime_string"] = self._uptime_to_string( native_uptime_string) return self._facts def file_copy(self, src, dest=None, **kwargs): if not self.file_copy_remote_exists(src, dest, **kwargs): if dest is None: dest = os.path.basename(src) with SCP(self.native) as scp: scp.put(src, remote_path=dest) if not self.file_copy_remote_exists(src, dest, **kwargs): raise FileTransferError( message= "Attempted file copy, but could not validate file existed after transfer" ) # TODO: Make this an internal method since exposing file_copy should be sufficient def file_copy_remote_exists(self, src, dest=None, **kwargs): if dest is None: dest = os.path.basename(src) local_hash = self._file_copy_local_md5(src) remote_hash = self._file_copy_remote_md5(dest) if local_hash is not None and local_hash == remote_hash: return True return False def install_os(self, image_name, **vendor_specifics): raise NotImplementedError def open(self): if not self.connected: self.native.open() def reboot(self, timer=0, confirm=False): self.sw = JunosNativeSW(self.native) if confirm: self.sw.reboot(in_min=timer) else: print("Need to confirm reboot with confirm=True") def rollback(self, filename): self.native.timeout = 60 temp_file = NamedTemporaryFile() with SCP(self.native) as scp: scp.get(filename, local_path=temp_file.name) self.cu.load(path=temp_file.name, format="text", overwrite=True) self.cu.commit() temp_file.close() self.native.timeout = 30 @property def running_config(self): return self.show("show config") def save(self, filename=None): if filename is None: self.cu.commit() return temp_file = NamedTemporaryFile() temp_file.write(self.show("show config")) temp_file.flush() with SCP(self.native) as scp: scp.put(temp_file.name, remote_path=filename) temp_file.close() return True def set_boot_options(self, sys): raise NotImplementedError def show(self, command, raw_text=True): if not raw_text: raise ValueError('Juniper only supports raw text output. \ Append " | display xml" to your commands for a structured string.' ) if not command.startswith("show"): raise CommandError( command, 'Juniper "show" commands must begin with "show".') return self.native.cli(command, warning=False) def show_list(self, commands, raw_text=True): responses = [] for command in commands: responses.append(self.show(command, raw_text=raw_text)) return responses @property def startup_config(self): return self.show("show config")
def reboot(self, timer=0, confirm=False): self.sw = JunosNativeSW(self.native) if confirm: self.sw.reboot(in_min=timer) else: print("Need to confirm reboot with confirm=True")
class TestSW(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.dev.facts = facts self.sw = self.get_sw() @patch('jnpr.junos.Device.execute') def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch(builtin_string + '.open', mock_open(), create=True): import jnpr.junos.utils.sw with open('foo') as h: h.read.side_effect = ('abc', 'a', '') jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertTrue(self.sw._multi_RE) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch(builtin_string + '.open') def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_checksum(package, algorithm='sha256'), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855') @patch(builtin_string + '.open') def test_sw_local_md5(self, mock_built_open): package = 'test.tgz' self.assertEqual(self.sw.local_checksum(package, algorithm='md5'), 'd41d8cd98f00b204e9800998ecf8427e') @patch(builtin_string + '.open') def test_sw_local_sha1(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_checksum(package, algorithm='sha1'), 'da39a3ee5e6b4b0d3255bfef95601890afd80709') def test_sw_local_checksum_unknown_alg(self): self.assertRaises(ValueError, SW.local_checksum, 'foo.tgz', algorithm='foo') def test_sw_progress(self): with self.capture(SW.progress, self.dev, 'running') as output: self.assertEqual('1.1.1.1: running\n', output) @patch('jnpr.junos.Device.execute') @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_progress_true(self, scp_put, mock_paramiko, mock_execute): mock_execute.side_effect = self._mock_manager with self.capture(SW.progress, self.dev, 'testing') as output: self.sw.install('test.tgz', progress=True, checksum=345, cleanfs=False) self.assertEqual('1.1.1.1: testing\n', output) @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_put(self, mock_scp_put, mock_scp): package = 'test.tgz' self.sw.put(package) self.assertTrue( call( 'test.tgz', '/var/tmp') in mock_scp_put.mock_calls) @patch('jnpr.junos.utils.sw.FTP') def test_sw_put_ftp(self, mock_ftp_put): dev = Device(host='1.1.1.1', user='******', password='******', mode='telnet', port=23, gather_facts=False) sw = SW(dev) sw.put(package='test.tgz') self.assertTrue( call( 'test.tgz', '/var/tmp') in mock_ftp_put.mock_calls) @patch('jnpr.junos.utils.scp.SCP.__exit__') @patch('jnpr.junos.utils.scp.SCP.__init__') @patch('jnpr.junos.utils.scp.SCP.__enter__') def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = 'test.tgz' mock_scp.side_effect = self._fake_scp with self.capture(self.sw.put, package, progress=self._my_scp_progress) as output: self.assertEqual('test.tgz 100 50\n', output) def _fake_scp(self, *args, **kwargs): progress = kwargs['progress'] progress('test.tgz', 100, 50) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgadd(package)) @patch('jnpr.junos.Device.execute') def test_sw_install_single_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = False self.assertTrue(self.sw.install('test.tgz', no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_issu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.install(package, issu=True, no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_nssu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.install(package, nssu=True, no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_issu_nssu_both_error(self, mock_execute): mock_execute.side_effect = self._mock_manager try: self.sw.install('test.tgz', issu=True, nssu=True) except TypeError as ex: self.assertEqual( str(ex), 'install function can either take issu or nssu not both') @patch('jnpr.junos.Device.execute') def test_sw_install_issu_single_re_error(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = False try: self.sw.install('test.tgz', issu=True) except TypeError as ex: self.assertEqual(str(ex), 'ISSU/NSSU requires Multi RE setup') @patch('jnpr.junos.Device.execute') def test_sw_install_issu_nssu_single_re_error(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.sw._multi_RE = False self.assertRaises(TypeError, self.sw.install, package, nssu=True, issu=True) @patch('jnpr.junos.Device.execute') def test_sw_pkgaddISSU(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgaddISSU(package)) @patch('jnpr.junos.Device.execute') def test_sw_pkgaddNSSU(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgaddNSSU(package)) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd_pkg_set(self, mock_execute): mock_execute.side_effect = self._mock_manager pkg_set = ['abc.tgz', 'pqr.tgz'] self.sw._mixed_VC = True self.sw.pkgadd(pkg_set) self.assertEqual([i.text for i in mock_execute.call_args[0][0].findall('set')], pkg_set) @patch('jnpr.junos.Device.execute') def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue(self.sw.validate('package.tgz')) @patch('jnpr.junos.Device.execute') def test_sw_validate_nssu(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw.log = MagicMock() # get_config returns false self.assertFalse(self.sw.validate('package.tgz', nssu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: GRES is not Enabled in configuration') @patch('jnpr.junos.Device.execute') def test_sw_validate_issu(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.assertTrue(self.sw.validate('package.tgz', issu=True)) @patch('jnpr.junos.Device.execute') def test_sw_val_issu_request_shell_execute_gres_on(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.request_shell_execute = MagicMock() self.dev.rpc.request_shell_execute.return_value = etree.fromstring( """<rpc-reply> <output>Graceful switchover: On</output> </rpc-reply>""") self.assertTrue(self.sw.validate('package.tgz', issu=True)) @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_2re_false(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.facts['2RE'] = False self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.dev.facts['2RE'] = True @patch('paramiko.SSHClient') @patch('jnpr.junos.utils.start_shell.StartShell.wait_for') def test_sw_validate_issu_request_shell_execute(self, mock_ss, mock_ssh): self._issu_test_helper() with patch('jnpr.junos.utils.start_shell.StartShell.run') as ss: ss.return_value = (True, 'Graceful switchover: On') self.assertTrue(self.sw.validate('package.tgz', issu=True)) @patch('paramiko.SSHClient') @patch('jnpr.junos.utils.start_shell.StartShell.wait_for') def test_sw_validate_issu_ss_login_other_re_fail(self, mock_ss, mock_ssh): self._issu_test_helper() with patch('jnpr.junos.utils.start_shell.StartShell.run') as ss: ss.return_value = (False, 'Graceful switchover: On') self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: Not able run "show system switchover"') @patch('paramiko.SSHClient') @patch('jnpr.junos.utils.start_shell.StartShell.wait_for') def test_sw_validate_issu_ss_graceful_off(self, mock_ss, mock_ssh): self._issu_test_helper() with patch('jnpr.junos.utils.start_shell.StartShell.run') as ss: ss.return_value = (True, 'Graceful switchover: Off') self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: Graceful switchover status is not On') def _issu_test_helper(self): self.sw.log = MagicMock() self.dev.rpc.request_shell_execute = MagicMock() self.dev.rpc = MagicMock() self.dev.rpc.get_routing_task_replication_state.return_value = \ self._read_file('get-routing-task-replication-state.xml') self.dev.rpc.check_in_service_upgrade.return_value = \ self._read_file('check-in-service-upgrade.xml') self.dev.rpc.request_shell_execute.side_effect = \ RpcError(rsp='not ok') @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_stateful_replication_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_routing_task_replication_state = MagicMock() self.sw.log = MagicMock() self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: Either Stateful Replication is not Enabled or RE mode\nis not Master') @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_commit_sync_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_config.return_value = etree.fromstring(""" <configuration> <chassis> <redundancy> <graceful-switchover> </graceful-switchover> </redundancy> </chassis> </configuration>""") self.sw.log = MagicMock() self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: commit synchronize is not Enabled in configuration') @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_nonstop_routing_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_config.side_effect = iter([etree.fromstring(""" <configuration> <chassis> <redundancy> <graceful-switchover> </graceful-switchover> </redundancy> </chassis> </configuration>"""), etree.fromstring(""" <configuration> <system> <commit> <synchronize/> </commit> </system> </configuration>"""), etree.fromstring("""<configuration> <routing-options></routing-options> </configuration>""")]) self.sw.log = MagicMock() self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: NSR is not Enabled in configuration') @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_validation_succeeded(self, mock_execute): rpc_reply = """<rpc-reply><output>mgd: commit complete Validation succeeded </output> <package-result>1</package-result> </rpc-reply>""" mock_execute.side_effect = etree.fromstring(rpc_reply) package = 'package.tgz' self.assertFalse(self.sw.validate(package, issu=True)) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_not_found(self, mock_execute): xml = '''<rpc-error> <error-severity>error</error-severity> <error-message> md5: /var/tmp/123: No such file or directory </error-message> </rpc-error>''' mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = 'test.tgz' self.assertEqual(self.sw.remote_checksum(package), None) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_not_rpc_error(self, mock_execute): xml = '''<rpc-error> <error-severity>error</error-severity> <error-message> something else! </error-message> </rpc-error>''' mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = 'test.tgz' with self.assertRaises(RpcError): self.sw.remote_checksum(package) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_md5(self, mock_execute): xml = '''<rpc-reply> <checksum-information> <file-checksum> <computation-method>MD5</computation-method> <input-file>/var/tmp/foo.tgz</input-file> <checksum>8a04cfc475e21507be5145bc0e82ce09</checksum> </file-checksum> </checksum-information> </rpc-reply>''' mock_execute.side_effect = etree.fromstring(xml) package = 'foo.tgz' self.assertEqual(self.sw.remote_checksum(package), '8a04cfc475e21507be5145bc0e82ce09') @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_sha1(self, mock_execute): xml = '''<rpc-reply> <checksum-information> <file-checksum> <computation-method>SHA1</computation-method> <input-file>/var/tmp/foo.tgz</input-file> <checksum>33c12913e81599452270ee849511e2e7578db00c</checksum> </file-checksum> </checksum-information> </rpc-reply>''' mock_execute.side_effect = etree.fromstring(xml) package = 'foo.tgz' self.assertEqual(self.sw.remote_checksum(package, algorithm='sha1'), '33c12913e81599452270ee849511e2e7578db00c') @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_sha256(self, mock_execute): xml = '''<rpc-reply> <checksum-information> <file-checksum> <computation-method>SHA256</computation-method> <input-file>/var/tmp/foo.tgz</input-file> <checksum>27bccf64babe4ea6687d3461e6d724d165aa140933e77b582af615dad4f02170</checksum> </file-checksum> </checksum-information> </rpc-reply>''' mock_execute.side_effect = etree.fromstring(xml) package = 'foo.tgz' self.assertEqual(self.sw.remote_checksum(package, algorithm='sha256'), '27bccf64babe4ea6687d3461e6d724d165aa140933e77b582af615dad4f02170') @patch('jnpr.junos.Device.execute') def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True, checksum='96a35ab371e1ca10408c3caecdbd8a67')) @patch('jnpr.junos.Device.execute') @patch('jnpr.junos.utils.sw.SW.local_checksum') def test_sw_safe_copy_missing_local_file(self, mock_checksum, mock_execute): mock_execute.side_effect = self._mock_manager mock_checksum.side_effect = IOError() package = 'foo.tgz' self.assertFalse(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_cleanfs_fail(self, mock_execute): mock_execute.side_effect = RpcError() package = 'foo.tgz' self.assertFalse(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True, checksum='96a35ab371e1ca10408c3caecdbd8a67')) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertFalse(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'install.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue( self.sw.install( package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.utils.sw.SW.safe_copy') def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install('file')) @patch('jnpr.junos.utils.sw.SW.validate') def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install('file', validate=True, no_copy=True)) @patch(builtin_string + '.print') @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_mx(self, mock_pkgadd, mock_print): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install('file', no_copy=True, progress=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install(pkg_set=['abc.tgz', 'pqr.tgz'], no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc_mode_disabled(self, mock_pkgadd): mock_pkgadd.return_value = True self.dev._facts = {'2RE': True, 'domain': None, 'RE1': { 'status': 'OK', 'model': 'RE-EX8208', 'mastership_state': 'backup'}, 'ifd_style': 'SWITCH', 'version_RE1': '12.3R7.7', 'version_RE0': '12.3', 'serialnumber': 'XXXXXX', 'fqdn': 'XXXXXX', 'RE0': {'status': 'OK', 'model': 'RE-EX8208', 'mastership_state': 'master'}, 'switch_style': 'VLAN', 'version': '12.3R5-S3.1', 'master': 'RE0', 'hostname': 'XXXXXX', 'HOME': '/var/home/sn', 'vc_mode': 'Disabled', 'model': 'EX8208', 'vc_capable': True, 'personality': 'SWITCH'} sw = self.get_sw() sw.install(package='abc.tgz', no_copy=True) self.assertFalse(sw._multi_VC) calls = [call('/var/tmp/abc.tgz', dev_timeout=1800, re0=True), call('/var/tmp/abc.tgz', dev_timeout=1800, re1=True)] mock_pkgadd.assert_has_calls(calls) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_with_copy(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.put = MagicMock() self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertTrue( self.sw.install( pkg_set=[ 'install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_safe_copy_false(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.safe_copy = MagicMock(return_value=False) self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertFalse( self.sw.install( pkg_set=[ 'install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_ValueError(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertRaises( ValueError, self.sw.install, pkg_set='install.tgz', cleanfs=False) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_TypeError(self, mock_pkgadd): self.assertRaises(TypeError, self.sw.install, cleanfs=False) @patch('jnpr.junos.Device.execute') def test_sw_install_kwargs_force_host(self, mock_execute): self.sw.install('file', no_copy=True, force_host=True) rpc = [ '<request-package-add><force-host/><no-validate/><re1/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><force-host/><re1/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><re1/><force-host/></request-package-add>', '<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name><re1/></request-package-add>', '<request-package-add><force-host/><re1/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><re1/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><force-host/><re1/></request-package-add>', '<request-package-add><force-host/><package-name>/var/tmp/file</package-name><no-validate/><re1/></request-package-add>', '<request-package-add><re1/><no-validate/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><re1/><force-host/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>', '<request-package-add><re1/><package-name>/var/tmp/file</package-name><force-host/><no-validate/></request-package-add>', '<request-package-add><re1/><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><force-host/><re1/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><no-validate/><re1/></request-package-add>', '<request-package-add><no-validate/><re1/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><re1/><no-validate/></request-package-add>', '<request-package-add><no-validate/><force-host/><package-name>/var/tmp/file</package-name><re1/></request-package-add>', '<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><force-host/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><force-host/></request-package-add>', '<request-package-add><no-validate/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><no-validate/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><re1/><no-validate/><force-host/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><re1/><force-host/><no-validate/></request-package-add>', '<request-package-add><force-host/><package-name>/var/tmp/file</package-name><re1/><no-validate/></request-package-add>', '<request-package-add><re1/><package-name>/var/tmp/file</package-name><no-validate/><force-host/></request-package-add>', '<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><re1/><force-host/></request-package-add>', '<request-package-add><re1/><no-validate/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><force-host/><re1/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>'] self.assertTrue(etree.tostring( mock_execute.call_args[0][0]).decode('utf-8') in rpc) @patch('jnpr.junos.Device.execute') def test_sw_rollback(self, mock_execute): rsp = '<rpc-reply><output>junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) msg = 'junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi(self, mock_execute): mock_execute.side_effect = self._mock_manager msg = {'fpc1': "Junos version 'D10.2' will become active at next reboot", 'fpc0': 'JUNOS version "D10.2" will become active at next reboot'} self.assertEqual(eval(self.sw.rollback()), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi_exception(self, mock_execute): fname = 'request-package-rollback-multi-error.xml' mock_execute.side_effect = self._read_file(fname) self.assertRaises(SwRollbackError, self.sw.rollback) @patch('jnpr.junos.Device.execute') def test_sw_rollback_exception(self, mock_execute): rsp = '<rpc-reply><output>WARNING: Cannot rollback, /packages/junos.old is not valid</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) self.assertRaises(SwRollbackError, self.sw.rollback) def test_sw_inventory(self): self.sw.dev.rpc.file_list = \ MagicMock(side_effect=self._mock_manager) self.assertEqual( self.sw.inventory, { 'current': None, 'rollback': None}) @patch('jnpr.junos.Device.execute') def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_at(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Shutdown at' in self.sw.reboot(at='201407091815')) @patch('jnpr.junos.Device.execute') def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_mixed_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw._multi_VC = True self.sw.reboot() self.assertTrue('all-members' in (etree.tostring(mock_execute.call_args[0][0]).decode('utf-8'))) @patch('jnpr.junos.Device.execute') def test_sw_reboot_mixed_vc_all_re_false(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw._multi_VC = True self.sw.reboot(all_re=False) self.assertTrue('all-members' not in (etree.tostring(mock_execute.call_args[0][0]).decode('utf-8'))) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception_RpcTimeoutError(self, mock_execute): rsp = (self.dev, 'request-reboot', 60) mock_execute.side_effect = RpcTimeoutError(*rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.poweroff()) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.poweroff()) def _myprogress(self, dev, report): pass def _my_scp_progress(self, _path, _total, _xfrd): print (_path, _total, _xfrd) @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() rpc_reply = NCElement( foo, self.dev._conn._device_handler.transform_reply())._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs: # Little hack for mocked execute if 'dev_timeout' in kwargs: return self._read_file(args[0].tag + '.xml') if 'path' in kwargs: if kwargs['path'] == '/packages': return self._read_file('file-list_dir.xml') device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].find('at') is not None: return self._read_file('request-reboot-at.xml') else: return self._read_file(args[0].tag + '.xml')
def test_sw_local_sha256(self, mock_built_open): package = "test.tgz" self.assertEqual( SW.local_checksum(package, algorithm="sha256"), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934" "ca495991b7852b855", )
class JunosDevice(BaseDevice): def __init__(self, host, username, password, *args, **kwargs): super(JunosDevice, self).__init__(host, username, password, *args, vendor='juniper', device_type=JNPR_DEVICE_TYPE, **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.connected = False self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativdSW(self.native) def open(self): if not self.connected: self.native.open() self.connected = True def close(self): if self.connected: self.native.close() self.connected = False def show(self, command, raw_text=True): if not raw_text: raise ValueError('Juniper only supports raw text output. \ Append " | display xml" to your commands for a structured string.') if not command.startswith('show'): raise CommandError(command, 'Juniper "show" commands must begin with "show".') return self.native.cli(command, warning=False) def show_list(self, commands, raw_text=True): responses = [] for command in commands: responses.append(self.show(command, raw_text=raw_text)) return responses def backup_running_config(self, filename): with open(filename, 'w') as f: f.write(self.running_config) def config(self, command, format='set'): try: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandError(command, e.message) def config_list(self, commands, format='set'): try: for command in commands: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandListError(commands, command, e.message) def _uptime_components(self, uptime_full_string): match_days = re.search(r'(\d+) days?', uptime_full_string) match_hours = re.search(r'(\d+) hours?', uptime_full_string) match_minutes = re.search(r'(\d+) minutes?', uptime_full_string) match_seconds = re.search(r'(\d+) seconds?', uptime_full_string) days = int(match_days.group(1)) if match_days else 0 hours = int(match_hours.group(1)) if match_hours else 0 minutes = int(match_minutes.group(1)) if match_minutes else 0 seconds = int(match_seconds.group(1)) if match_seconds else 0 return days, hours, minutes, seconds def _uptime_to_string(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components(uptime_full_string) return '%02d:%02d:%02d:%02d' % (days, hours, minutes, seconds) def _uptime_to_seconds(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components(uptime_full_string) seconds += days * 24 * 60 * 60 seconds += hours * 60 * 60 seconds += minutes * 60 return seconds def _get_interfaces(self): eth_ifaces = EthPortTable(self.native) eth_ifaces.get() loop_ifaces = LoopbackTable(self.native) loop_ifaces.get() ifaces = eth_ifaces.keys() ifaces.extend(loop_ifaces.keys()) return ifaces def checkpoint(self, filename): self.save(filename) def rollback(self, filename): self.native.timeout = 60 temp_file = NamedTemporaryFile() with SCP(self.native) as scp: scp.get(filename, local_path=temp_file.name) self.cu.load(path=temp_file.name, format='text', overwrite=True) self.cu.commit() temp_file.close() self.native.timeout = 30 @property def facts(self): if hasattr(self, '_facts'): return self._facts native_facts = self.native.facts facts = {} facts['hostname'] = native_facts['hostname'] facts['fqdn'] = native_facts['fqdn'] facts['model'] = native_facts['model'] native_uptime_string = native_facts['RE0']['up_time'] facts['uptime'] = self._uptime_to_seconds(native_uptime_string) facts['uptime_string'] = self._uptime_to_string(native_uptime_string) facts['serial_number'] = native_facts['serialnumber'] facts['interfaces'] = self._get_interfaces() for fact_key in native_facts: if fact_key.startswith('version') and fact_key != 'version_info': facts['os_version'] = native_facts[fact_key] break facts['vendor'] = self.vendor self._facts = facts return self._facts def _file_copy_local_file_exists(self, filepath): return os.path.isfile(filepath) def _file_copy_local_md5(self, filepath, blocksize=2**20): if self._file_copy_local_file_exists(filepath): m = hashlib.md5() with open(filepath, "rb") as f: buf = f.read(blocksize) while buf: m.update(buf) buf = f.read(blocksize) return m.hexdigest() def _file_copy_remote_md5(self, filename): return self.fs.checksum(filename) def file_copy_remote_exists(self, src, dest=None): if dest is None: dest = os.path.basename(src) local_hash = self._file_copy_local_md5(src) remote_hash = self._file_copy_remote_md5(dest) if local_hash is not None: if local_hash == remote_hash: return True return False def file_copy(self, src, dest=None): if dest is None: dest = os.path.basename(src) with SCP(self.native) as scp: scp.put(src, remote_path=dest) def get_boot_options(self): return self.facts['os_version'] def set_boot_options(self, sys): raise NotImplementedError def reboot(self, timer=0, confirm=False): if confirm: self.sw.reboot(in_min=timer) else: print('Need to confirm reboot with confirm=True') @property def running_config(self): return self.show('show config') def save(self, filename=None): if filename is None: self.cu.commit() return temp_file = NamedTemporaryFile() temp_file.write(self.show('show config')) temp_file.flush() with SCP(self.native) as scp: scp.put(temp_file.name, remote_path=filename) temp_file.close() return True @property def startup_config(self): return self.show('show config')
from jnpr.junos import Device from jnpr.junos.utils.sw import SW import sys dev = Device('host', user='******', password='******') try: dev.open() except Exception as err: print "Unable to connect to host:", err sys.exit(1) sft= SW(dev) print sft.reboot() #print sft.reboot(in_min=5) #print ("Before Shutdown\n") #print sft.poweroff() #print ("After Shutdown\n")
def shutdown(**kwargs): """ Shut down (power off) or reboot a device running Junos OS. This includes all Routing Engines in a Virtual Chassis or a dual Routing Engine system. .. note:: One of ``shutdown`` or ``reboot`` must be set to ``True`` or no action will be taken. shutdown : False Set this to ``True`` if you want to shutdown the machine. This is a safety mechanism so that the user does not accidentally shutdown the junos device. reboot : False If ``True``, reboot instead of shutting down at Used when rebooting, to specify the date and time the reboot should take place. The value of this option must match the JunOS CLI reboot syntax. in_min Used when shutting down. Specify the delay (in minutes) before the device will be shut down. CLI Examples: .. code-block:: bash salt 'device_name' junos.shutdown reboot=True salt 'device_name' junos.shutdown shutdown=True in_min=10 salt 'device_name' junos.shutdown shutdown=True """ conn = __proxy__["junos.conn"]() ret = {} sw = SW(conn) op = {} if "__pub_arg" in kwargs: if kwargs["__pub_arg"]: if isinstance(kwargs["__pub_arg"][-1], dict): op.update(kwargs["__pub_arg"][-1]) else: op.update(kwargs) if "shutdown" not in op and "reboot" not in op: ret["message"] = "Provide either one of the arguments: shutdown or reboot." ret["out"] = False return ret try: if "reboot" in op and op["reboot"]: shut = sw.reboot elif "shutdown" in op and op["shutdown"]: shut = sw.poweroff else: ret["message"] = "Nothing to be done." ret["out"] = False return ret if "in_min" in op: shut(in_min=op["in_min"]) elif "at" in op: shut(at=op["at"]) else: shut() ret["message"] = "Successfully powered off/rebooted." ret["out"] = True except Exception as exception: # pylint: disable=broad-except ret["message"] = 'Could not poweroff/reboot beacause "{0}"'.format( exception) ret["out"] = False return ret
from jnpr.junos import Device from jnpr.junos.utils.sw import SW import sys dev = Device('host', user='******', password='******') try: dev.open() except Exception as err: print "Unable to connect to host:", err sys.exit(1) sft = SW(dev) print sft.reboot() #print sft.reboot(in_min=5) #print ("Before Shutdown\n") #print sft.poweroff() #print ("After Shutdown\n")
from jnpr.junos import Device from jnpr.junos.utils.sw import SW dev = Device(host='xxxx', user='******', password='******', gather_facts=False) dev.open() def update_progress(dev, report): print dev.hostname, '> ', report sw = SW(dev) ok = sw.install(package=r'/Users/nitinkr/Downloads/jinstall-1x.1xxxx.tgz', progress=update_progress) # progress takes boolean values too from 1.2.3 version onwards #ok = sw.install(package=r'/Users/nitinkr/Downloads/jinstall-1x.1xxxx.tgz', progress=True) if ok: print 'rebooting' sw.reboot()
class TestSW(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.dev._facts = facts self.sw = self.get_sw() @patch('jnpr.junos.Device.execute') def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch(builtin_string + '.open', mock_open(), create=True): import jnpr.junos.utils.sw with open('foo') as h: h.read.side_effect = ('abc', 'a', '') jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertTrue(self.sw._multi_RE) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch(builtin_string + '.open') def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha256(package), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855') @patch(builtin_string + '.open') def test_sw_local_md5(self, mock_built_open): package = 'test.tgz' self.assertEqual(self.sw.local_md5(package), 'd41d8cd98f00b204e9800998ecf8427e') @patch(builtin_string + '.open') def test_sw_local_sha1(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha1(package), 'da39a3ee5e6b4b0d3255bfef95601890afd80709') def test_sw_progress(self): with self.capture(SW.progress, self.dev, 'running') as output: self.assertEqual('1.1.1.1: running\n', output) def test_sw_progress(self): with self.capture(SW.progress, self.dev, 'running') as output: self.assertEqual('1.1.1.1: running\n', output) @patch('jnpr.junos.Device.execute') @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_progress_true(self, scp_put, mock_paramiko, mock_execute): mock_execute.side_effect = self._mock_manager with self.capture(SW.progress, self.dev, 'testing') as output: self.sw.install('test.tgz', progress=True, checksum=345, cleanfs=False) self.assertEqual('1.1.1.1: testing\n', output) @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_put(self, mock_scp_put, mock_scp): package = 'test.tgz' self.sw.put(package) self.assertTrue( call( 'test.tgz', '/var/tmp') in mock_scp_put.mock_calls) @patch('jnpr.junos.utils.sw.FTP') def test_sw_put_ftp(self, mock_ftp_put): dev = Device(host='1.1.1.1', user='******', password='******', mode='telnet', port=23, gather_facts=False) sw = SW(dev) sw.put(package='test.tgz') self.assertTrue( call( 'test.tgz', '/var/tmp') in mock_ftp_put.mock_calls) @patch('jnpr.junos.utils.scp.SCP.__exit__') @patch('jnpr.junos.utils.scp.SCP.__init__') @patch('jnpr.junos.utils.scp.SCP.__enter__') def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = 'test.tgz' mock_scp.side_effect = self._fake_scp with self.capture(self.sw.put, package, progress=self._my_scp_progress) as output: self.assertEqual('test.tgz 100 50\n', output) def _fake_scp(self, *args, **kwargs): progress = kwargs['progress'] progress('test.tgz', 100, 50) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgadd(package)) @patch('jnpr.junos.Device.execute') def test_sw_install_issu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.install(package, issu=True, no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_nssu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.install(package, nssu=True, no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_issu_nssu_both_error(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertRaises(TypeError, self.sw.install, package, nssu=True, issu=True) @patch('jnpr.junos.Device.execute') def test_sw_install_issu_single_re_error(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.sw._multi_RE = False self.assertRaises(TypeError, self.sw.install, package, nssu=True, issu=True) @patch('jnpr.junos.Device.execute') def test_sw_pkgaddISSU(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgaddISSU(package)) @patch('jnpr.junos.Device.execute') def test_sw_pkgaddNSSU(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgaddNSSU(package)) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd_pkg_set(self, mock_execute): mock_execute.side_effect = self._mock_manager pkg_set = ['abc.tgz', 'pqr.tgz'] self.sw._mixed_VC = True self.sw.pkgadd(pkg_set) self.assertEqual([i.text for i in mock_execute.call_args[0][0].findall('set')], pkg_set) @patch('jnpr.junos.Device.execute') def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'package.tgz' self.assertTrue(self.sw.validate(package)) @patch('jnpr.junos.Device.execute') def test_sw_validate_issu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'package.tgz' self.assertTrue(self.sw.validate(package, issu=True)) @patch('jnpr.junos.Device.execute') def test_sw_validate_issu(self, mock_execute): rpc_reply = """<rpc-reply><output>mgd: commit complete Validation succeeded </output> <package-result>1</package-result> </rpc-reply>""" mock_execute.side_effect = etree.fromstring(rpc_reply) package = 'package.tgz' self.assertFalse(self.sw.validate(package, issu=True)) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_not_found(self, mock_execute): xml = '''<rpc-error> <error-severity>error</error-severity> <error-message> md5: /var/tmp/123: No such file or directory </error-message> </rpc-error>''' mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = 'test.tgz' self.assertEqual(self.sw.remote_checksum(package), None) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_not_rpc_error(self, mock_execute): xml = '''<rpc-error> <error-severity>error</error-severity> <error-message> something else! </error-message> </rpc-error>''' mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = 'test.tgz' with self.assertRaises(RpcError): self.sw.remote_checksum(package) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True, checksum='96a35ab371e1ca10408c3caecdbd8a67')) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertFalse(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'install.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue( self.sw.install( package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.utils.sw.SW.safe_copy') def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install('file')) @patch('jnpr.junos.utils.sw.SW.validate') def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install('file', validate=True, no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_mx(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install(pkg_set=['abc.tgz', 'pqr.tgz'], no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc_mode_disabled(self, mock_pkgadd): mock_pkgadd.return_value = True self.dev._facts = {'2RE': True, 'domain': None, 'RE1': { 'status': 'OK', 'model': 'RE-EX8208', 'mastership_state': 'backup'}, 'ifd_style': 'SWITCH', 'version_RE1': '12.3R7.7', 'version_RE0': '12.3', 'serialnumber': 'XXXXXX', 'fqdn': 'XXXXXX', 'RE0': {'status': 'OK', 'model': 'RE-EX8208', 'mastership_state': 'master'}, 'switch_style': 'VLAN', 'version': '12.3R5-S3.1', 'master': 'RE0', 'hostname': 'XXXXXX', 'HOME': '/var/home/sn', 'vc_mode': 'Disabled', 'model': 'EX8208', 'vc_capable': True, 'personality': 'SWITCH'} sw = self.get_sw() sw.install(package='abc.tgz', no_copy=True) self.assertFalse(sw._multi_VC) calls = [call('/var/tmp/abc.tgz', dev_timeout=1800, re0=True), call('/var/tmp/abc.tgz', dev_timeout=1800, re1=True)] mock_pkgadd.assert_has_calls(calls) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_with_copy(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.put = MagicMock() self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertTrue( self.sw.install( pkg_set=[ 'install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_safe_copy_false(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.safe_copy = MagicMock(return_value=False) self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertFalse( self.sw.install( pkg_set=[ 'install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_ValueError(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertRaises( ValueError, self.sw.install, pkg_set='install.tgz', cleanfs=False) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_TypeError(self, mock_pkgadd): self.assertRaises(TypeError, self.sw.install, cleanfs=False) @patch('jnpr.junos.Device.execute') def test_sw_install_kwargs_force_host(self, mock_execute): self.sw.install('file', no_copy=True, force_host=True) rpc = [ '<request-package-add><force-host/><no-validate/><re1/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><force-host/><re1/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><re1/><force-host/></request-package-add>', '<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name><re1/></request-package-add>', '<request-package-add><force-host/><re1/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><re1/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><force-host/><re1/></request-package-add>', '<request-package-add><force-host/><package-name>/var/tmp/file</package-name><no-validate/><re1/></request-package-add>', '<request-package-add><re1/><no-validate/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><re1/><force-host/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>', '<request-package-add><re1/><package-name>/var/tmp/file</package-name><force-host/><no-validate/></request-package-add>', '<request-package-add><re1/><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><force-host/><re1/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><no-validate/><re1/></request-package-add>', '<request-package-add><no-validate/><re1/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><re1/><no-validate/></request-package-add>', '<request-package-add><no-validate/><force-host/><package-name>/var/tmp/file</package-name><re1/></request-package-add>', '<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><force-host/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><force-host/></request-package-add>', '<request-package-add><no-validate/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><no-validate/></request-package-add>'] self.assertTrue(etree.tostring( mock_execute.call_args[0][0]).decode('utf-8') in rpc) @patch('jnpr.junos.Device.execute') def test_sw_rollback(self, mock_execute): rsp = '<rpc-reply><output>junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) msg = 'junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi(self, mock_execute): mock_execute.side_effect = self._mock_manager msg = {'fpc1': "Junos version 'D10.2' will become active at next reboot", 'fpc0': 'JUNOS version "D10.2" will become active at next reboot'} self.assertEqual(eval(self.sw.rollback()), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi_exception(self, mock_execute): fname = 'request-package-rollback-multi-error.xml' mock_execute.side_effect = self._read_file(fname) self.assertRaises(SwRollbackError, self.sw.rollback) @patch('jnpr.junos.Device.execute') def test_sw_rollback_exception(self, mock_execute): rsp = '<rpc-reply><output>WARNING: Cannot rollback, /packages/junos.old is not valid</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) self.assertRaises(SwRollbackError, self.sw.rollback) def test_sw_inventory(self): self.sw.dev.rpc.file_list = \ MagicMock(side_effect=self._mock_manager) self.assertEqual( self.sw.inventory, { 'current': None, 'rollback': None}) @patch('jnpr.junos.Device.execute') def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_at(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Shutdown at' in self.sw.reboot(at='201407091815')) @patch('jnpr.junos.Device.execute') def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_mixed_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw._multi_VC = True self.sw.reboot() self.assertTrue('all-members' in (etree.tostring(mock_execute.call_args[0][0]).decode('utf-8'))) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception_RpcTimeoutError(self, mock_execute): rsp = (self.dev, 'request-reboot', 60) mock_execute.side_effect = RpcTimeoutError(*rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.poweroff()) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.poweroff()) def _myprogress(self, dev, report): pass def _my_scp_progress(self, _path, _total, _xfrd): print (_path, _total, _xfrd) @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() rpc_reply = NCElement( foo, self.dev._conn._device_handler.transform_reply())._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs: # Little hack for mocked execute if 'dev_timeout' in kwargs: return self._read_file(args[0].tag + '.xml') if 'path' in kwargs: if kwargs['path'] == '/packages': return self._read_file('file-list_dir.xml') device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].find('at') is not None: return self._read_file('request-reboot-at.xml') else: return self._read_file(args[0].tag + '.xml')
from jnpr.junos import Device from jnpr.junos.utils.sw import SW import sys dev = Device('host', user='******', password='******') try: dev.open() except Exception as err: print "Unable to connect to host:", err sys.exit(1) sft= SW(dev) print sft.install('/var/tmp/jpuppet-3.6.1_3.0_x86-32.tgz') print dev.cli("show version", warning=False) #print sft.reboot() dev.close()
def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha256(package), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855')
def test_sw_local_md5(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_md5(package), 'd41d8cd98f00b204e9800998ecf8427e')
class TestSW(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.dev.facts = facts self.sw = self.get_sw() @patch("jnpr.junos.Device.execute") def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch("ncclient.operations.session.CloseSession.request") def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch(builtin_string + ".open", mock_open(), create=True): import jnpr.junos.utils.sw with open("foo") as h: h.read.side_effect = ("abc", "a", "") jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch("jnpr.junos.Device.execute") def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertTrue(self.sw._multi_RE) @patch("jnpr.junos.Device.execute") def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch(builtin_string + ".open") def test_sw_local_sha256(self, mock_built_open): package = "test.tgz" self.assertEqual( SW.local_checksum(package, algorithm="sha256"), "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934" "ca495991b7852b855", ) @patch(builtin_string + ".open") def test_sw_local_md5(self, mock_built_open): package = "test.tgz" self.assertEqual( self.sw.local_checksum(package, algorithm="md5"), "d41d8cd98f00b204e9800998ecf8427e", ) @patch(builtin_string + ".open") def test_sw_local_sha1(self, mock_built_open): package = "test.tgz" self.assertEqual( SW.local_checksum(package, algorithm="sha1"), "da39a3ee5e6b4b0d3255bfef95601890afd80709", ) def test_sw_local_checksum_unknown_alg(self): self.assertRaises(ValueError, SW.local_checksum, "foo.tgz", algorithm="foo") def test_sw_progress(self): with self.capture(SW.progress, self.dev, "running") as output: self.assertEqual("1.1.1.1: running\n", output) @patch("jnpr.junos.Device.execute") @patch("paramiko.SSHClient") @patch("scp.SCPClient.put") def test_sw_progress_true(self, scp_put, mock_paramiko, mock_execute): mock_execute.side_effect = self._mock_manager with self.capture(SW.progress, self.dev, "testing") as output: self.sw.install("test.tgz", progress=True, checksum=345, cleanfs=False) self.assertEqual("1.1.1.1: testing\n", output) @patch("paramiko.SSHClient") @patch("scp.SCPClient.put") def test_sw_put(self, mock_scp_put, mock_scp): package = "test.tgz" self.sw.put(package) self.assertTrue( call("test.tgz", "/var/tmp") in mock_scp_put.mock_calls) @patch("jnpr.junos.utils.sw.FTP") def test_sw_put_ftp(self, mock_ftp_put): dev = Device( host="1.1.1.1", user="******", password="******", mode="telnet", port=23, gather_facts=False, ) dev.facts = facts sw = SW(dev) sw.put(package="test.tgz") self.assertTrue( call("test.tgz", "/var/tmp") in mock_ftp_put.mock_calls) @patch("jnpr.junos.utils.scp.SCP.__exit__") @patch("jnpr.junos.utils.scp.SCP.__init__") @patch("jnpr.junos.utils.scp.SCP.__enter__") def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = "test.tgz" mock_scp.side_effect = self._fake_scp with self.capture(self.sw.put, package, progress=self._my_scp_progress) as output: self.assertEqual("test.tgz 100 50\n", output) def _fake_scp(self, *args, **kwargs): progress = kwargs["progress"] progress("test.tgz", 100, 50) @patch("jnpr.junos.Device.execute") def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.assertTrue(self.sw.pkgadd(package)) @patch("jnpr.junos.Device.execute") @patch("jnpr.junos.utils.sw.SW.local_md5") def test_sw_install_url_in_pkg_set(self, mock_md5, mock_execute): mock_md5.return_value = "96a35ab371e1ca10408c3caecdbd8a67" mock_execute.side_effect = self._mock_manager self.sw.put = MagicMock() self.sw._mixed_VC = True self.assertTrue( self.sw.install(pkg_set=[ "safecopy.tgz", "safecopy.tgz", "ftp://server/path/test.tgz" ])) @patch("jnpr.junos.Device.execute") def test_sw_install_via_url(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue(self.sw.install(package="ftp://server/path/test.tgz")) @patch("jnpr.junos.Device.execute") def test_sw_install_single_re_on_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.assertTrue(self.sw.install("test.tgz", all_re=False, no_copy=True)) @patch("jnpr.junos.Device.execute") def test_sw_install_single_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = False self.assertTrue(self.sw.install("test.tgz", no_copy=True)) @patch("jnpr.junos.Device.execute") def test_sw_install_srx_branch_cluster(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = False self.sw._dev.facts["personality"] = "SRX_BRANCH" self.sw._dev.facts["srx_cluster"] = True self.assertTrue(self.sw.install("test.tgz", no_copy=True)) @patch("jnpr.junos.Device.execute") def test_sw_install_no_package_result(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = False self.assertTrue(self.sw.install("test_no_result.tgz", no_copy=True)) @patch("jnpr.junos.Device.execute") def test_sw_install_issu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.assertTrue(self.sw.install(package, issu=True, no_copy=True)) @patch("jnpr.junos.Device.execute") def test_sw_install_nssu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.assertTrue(self.sw.install(package, nssu=True, no_copy=True)) @patch("jnpr.junos.Device.execute") def test_sw_install_issu_nssu_both_error(self, mock_execute): mock_execute.side_effect = self._mock_manager try: self.sw.install("test.tgz", issu=True, nssu=True) except TypeError as ex: self.assertEqual( str(ex), "install function can either take issu or nssu not both") @patch("jnpr.junos.Device.execute") def test_sw_install_issu_single_re_error(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = False try: self.sw.install("test.tgz", issu=True) except TypeError as ex: self.assertEqual(str(ex), "ISSU/NSSU requires Multi RE setup") @patch("jnpr.junos.Device.execute") def test_sw_install_issu_nssu_single_re_error(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.sw._multi_RE = False self.assertRaises(TypeError, self.sw.install, package, nssu=True, issu=True) @patch("jnpr.junos.Device.execute") def test_sw_pkgaddISSU(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.assertTrue(self.sw.pkgaddISSU(package)) @patch("jnpr.junos.Device.execute") def test_sw_pkgaddNSSU(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.assertTrue(self.sw.pkgaddNSSU(package)) @patch("jnpr.junos.Device.execute") def test_sw_pkgadd_pkg_set(self, mock_execute): mock_execute.side_effect = self._mock_manager pkg_set = ["abc.tgz", "pqr.tgz"] self.sw._mixed_VC = True self.sw.pkgadd(pkg_set) self.assertEqual( [i.text for i in mock_execute.call_args[0][0].findall("set")], pkg_set) @patch("jnpr.junos.Device.execute") def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue(self.sw.validate("package.tgz")) @patch("jnpr.junos.Device.execute") def test_sw_validate_nssu(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw.log = MagicMock() # get_config returns false self.assertFalse(self.sw.validate("package.tgz", nssu=True)) self.sw.log.assert_called_with( "Requirement FAILED: GRES is not Enabled in configuration") @patch("jnpr.junos.Device.execute") def test_sw_validate_issu(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.assertTrue(self.sw.validate("package.tgz", issu=True)) @patch("jnpr.junos.Device.execute") def test_sw_val_issu_request_shell_execute_gres_on(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.request_shell_execute = MagicMock() self.dev.rpc.request_shell_execute.return_value = etree.fromstring( """<rpc-reply> <output>Graceful switchover: On</output> </rpc-reply>""") self.assertTrue(self.sw.validate("package.tgz", issu=True)) @patch("jnpr.junos.Device.execute") def test_sw_validate_issu_2re_false(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.facts["2RE"] = False self.assertFalse(self.sw.validate("package.tgz", issu=True)) self.dev.facts["2RE"] = True @patch("paramiko.SSHClient") @patch("jnpr.junos.utils.start_shell.StartShell.wait_for") def test_sw_validate_issu_request_shell_execute(self, mock_ss, mock_ssh): self._issu_test_helper() with patch("jnpr.junos.utils.start_shell.StartShell.run") as ss: ss.return_value = (True, "Graceful switchover: On") self.assertTrue(self.sw.validate("package.tgz", issu=True)) @patch("paramiko.SSHClient") @patch("jnpr.junos.utils.start_shell.StartShell.wait_for") def test_sw_validate_issu_ss_login_other_re_fail(self, mock_ss, mock_ssh): self._issu_test_helper() with patch("jnpr.junos.utils.start_shell.StartShell.run") as ss: ss.return_value = (False, "Graceful switchover: On") self.assertFalse(self.sw.validate("package.tgz", issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: Not able run "show system switchover"') @patch("paramiko.SSHClient") @patch("jnpr.junos.utils.start_shell.StartShell.wait_for") def test_sw_validate_issu_ss_graceful_off(self, mock_ss, mock_ssh): self._issu_test_helper() with patch("jnpr.junos.utils.start_shell.StartShell.run") as ss: ss.return_value = (True, "Graceful switchover: Off") self.assertFalse(self.sw.validate("package.tgz", issu=True)) self.sw.log.assert_called_with( "Requirement FAILED: Graceful switchover status is not On") def _issu_test_helper(self): self.sw.log = MagicMock() self.dev.rpc.request_shell_execute = MagicMock() self.dev.rpc = MagicMock() self.dev.rpc.get_routing_task_replication_state.return_value = self._read_file( "get-routing-task-replication-state.xml") self.dev.rpc.check_in_service_upgrade.return_value = self._read_file( "check-in-service-upgrade.xml") self.dev.rpc.request_shell_execute.side_effect = RpcError(rsp="not ok") @patch("jnpr.junos.Device.execute") def test_sw_validate_issu_stateful_replication_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_routing_task_replication_state = MagicMock() self.sw.log = MagicMock() self.assertFalse(self.sw.validate("package.tgz", issu=True)) self.sw.log.assert_called_with( "Requirement FAILED: Either Stateful Replication is not Enabled " "or RE mode\nis not Master") @patch("jnpr.junos.Device.execute") def test_sw_validate_issu_commit_sync_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_config.return_value = etree.fromstring(""" <configuration> <chassis> <redundancy> <graceful-switchover> </graceful-switchover> </redundancy> </chassis> </configuration>""") self.sw.log = MagicMock() self.assertFalse(self.sw.validate("package.tgz", issu=True)) self.sw.log.assert_called_with( "Requirement FAILED: commit synchronize is not Enabled " "in configuration") @patch("jnpr.junos.Device.execute") def test_sw_validate_issu_nonstop_routing_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_config.side_effect = iter([ etree.fromstring(""" <configuration> <chassis> <redundancy> <graceful-switchover> </graceful-switchover> </redundancy> </chassis> </configuration>"""), etree.fromstring(""" <configuration> <system> <commit> <synchronize/> </commit> </system> </configuration>"""), etree.fromstring("""<configuration> <routing-options></routing-options> </configuration>"""), ]) self.sw.log = MagicMock() self.assertFalse(self.sw.validate("package.tgz", issu=True)) self.sw.log.assert_called_with( "Requirement FAILED: NSR is not Enabled in configuration") @patch("jnpr.junos.Device.execute") def test_sw_validate_issu_validation_succeeded(self, mock_execute): rpc_reply = """<rpc-reply><output>mgd: commit complete Validation succeeded </output> <package-result>1</package-result> </rpc-reply>""" mock_execute.side_effect = etree.fromstring(rpc_reply) package = "package.tgz" self.assertFalse(self.sw.validate(package, issu=True)) @patch("jnpr.junos.Device.execute") def test_sw_remote_checksum_not_found(self, mock_execute): xml = """<rpc-error> <error-severity>error</error-severity> <error-message> md5: /var/tmp/123: No such file or directory </error-message> </rpc-error>""" mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = "test.tgz" self.assertEqual(self.sw.remote_checksum(package), None) @patch("jnpr.junos.Device.execute") def test_sw_remote_checksum_not_rpc_error(self, mock_execute): xml = """<rpc-error> <error-severity>error</error-severity> <error-message> something else! </error-message> </rpc-error>""" mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = "test.tgz" with self.assertRaises(RpcError): self.sw.remote_checksum(package) @patch("jnpr.junos.Device.execute") def test_sw_remote_checksum_md5(self, mock_execute): xml = """<rpc-reply> <checksum-information> <file-checksum> <computation-method>MD5</computation-method> <input-file>/var/tmp/foo.tgz</input-file> <checksum>8a04cfc475e21507be5145bc0e82ce09</checksum> </file-checksum> </checksum-information> </rpc-reply>""" mock_execute.side_effect = etree.fromstring(xml) package = "foo.tgz" self.assertEqual(self.sw.remote_checksum(package), "8a04cfc475e21507be5145bc0e82ce09") @patch("jnpr.junos.Device.execute") def test_sw_remote_checksum_sha1(self, mock_execute): xml = """ <rpc-reply> <checksum-information> <file-checksum> <computation-method>SHA1</computation-method> <input-file>/var/tmp/foo.tgz</input-file> <checksum>33c12913e81599452270ee849511e2e7578db00c</checksum> </file-checksum> </checksum-information> </rpc-reply>""" mock_execute.side_effect = etree.fromstring(xml) package = "foo.tgz" self.assertEqual( self.sw.remote_checksum(package, algorithm="sha1"), "33c12913e81599452270ee849511e2e7578db00c", ) @patch("jnpr.junos.Device.execute") def test_sw_remote_checksum_sha256(self, mock_execute): xml = """ <rpc-reply> <checksum-information> <file-checksum> <computation-method>SHA256</computation-method> <input-file>/var/tmp/foo.tgz</input-file> <checksum>27bccf64babe4ea6687d3461e6d724d165aa140933e77b582af615dad4f02170</checksum> </file-checksum> </checksum-information> </rpc-reply>""" mock_execute.side_effect = etree.fromstring(xml) package = "foo.tgz" self.assertEqual( self.sw.remote_checksum(package, algorithm="sha256"), "27bccf64babe4ea6687d3461e6d724d165aa140933e77b582af615dad4f02170", ) def test_sw_remote_checksum_unknown_alg(self): self.assertRaises(ValueError, self.sw.remote_checksum, "foo.tgz", algorithm="foo") @patch("jnpr.junos.Device.execute") def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "safecopy.tgz" self.sw.put = MagicMock() with patch("jnpr.junos.utils.sw.SW.local_md5"): self.assertTrue( self.sw.safe_copy( package, progress=self._myprogress, cleanfs=True, checksum="96a35ab371e1ca10408c3caecdbd8a67", )) @patch("jnpr.junos.Device.execute") @patch("jnpr.junos.utils.sw.SW.local_checksum") def test_sw_safe_copy_missing_local_file(self, mock_checksum, mock_execute): mock_execute.side_effect = self._mock_manager mock_checksum.side_effect = IOError() package = "foo.tgz" self.assertFalse( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch("jnpr.junos.Device.execute") def test_sw_safe_copy_cleanfs_fail(self, mock_execute): mock_execute.side_effect = RpcError() package = "foo.tgz" self.assertFalse( self.sw.safe_copy( package, progress=self._myprogress, cleanfs=True, checksum="96a35ab371e1ca10408c3caecdbd8a67", )) @patch("jnpr.junos.Device.execute") def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = "safecopy.tgz" self.sw.put = MagicMock() with patch("jnpr.junos.utils.sw.SW.local_md5"): self.assertFalse( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch("jnpr.junos.Device.execute") def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "safecopy.tgz" self.sw.put = MagicMock() with patch( "jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="96a35ab371e1ca10408c3caecdbd8a67"), ): self.assertTrue( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch("jnpr.junos.Device.execute") def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "install.tgz" self.sw.put = MagicMock() with patch( "jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="96a35ab371e1ca10408c3caecdbd8a67"), ): self.assertTrue( self.sw.install(package, progress=self._myprogress, cleanfs=True)) @patch("jnpr.junos.utils.sw.SW.safe_copy") def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install("file")) @patch("jnpr.junos.utils.sw.SW.validate") def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install("file", validate=True, no_copy=True)) @patch(builtin_string + ".print") @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_multi_mx(self, mock_pkgadd, mock_print): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install("file", no_copy=True, progress=True)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ("version_RE0", "version_RE1") self.assertTrue(self.sw.install("file", no_copy=True)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw._RE_list = ("version_RE0", "version_RE1") self.assertTrue( self.sw.install(pkg_set=["abc.tgz", "pqr.tgz"], no_copy=True)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_multi_vc_mode_disabled(self, mock_pkgadd): mock_pkgadd.return_value = True self.dev._facts = { "2RE": True, "domain": None, "RE1": { "status": "OK", "model": "RE-EX8208", "mastership_state": "backup" }, "ifd_style": "SWITCH", "version_RE1": "12.3R7.7", "version_RE0": "12.3", "serialnumber": "XXXXXX", "fqdn": "XXXXXX", "RE0": { "status": "OK", "model": "RE-EX8208", "mastership_state": "master" }, "switch_style": "VLAN", "version": "12.3R5-S3.1", "master": "RE0", "hostname": "XXXXXX", "HOME": "/var/home/sn", "vc_mode": "Disabled", "model": "EX8208", "vc_capable": True, "personality": "SWITCH", } sw = self.get_sw() sw.install(package="abc.tgz", no_copy=True) self.assertFalse(sw._multi_VC) calls = [ call("/var/tmp/abc.tgz", dev_timeout=1800, vmhost=False, re0=True), call("/var/tmp/abc.tgz", dev_timeout=1800, re1=True, vmhost=False), ] mock_pkgadd.assert_has_calls(calls) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc_with_copy(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.put = MagicMock() self.sw.remote_checksum = MagicMock( return_value="d41d8cd98f00b204e9800998ecf8427e") self.sw._RE_list = ("version_RE0", "version_RE1") with patch( "jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e"), ): self.assertTrue( self.sw.install(pkg_set=["install.tgz", "install.tgz"], cleanfs=False)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc_safe_copy_false(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.safe_copy = MagicMock(return_value=False) self.sw.remote_checksum = MagicMock( return_value="d41d8cd98f00b204e9800998ecf8427e") self.sw._RE_list = ("version_RE0", "version_RE1") with patch( "jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e"), ): self.assertFalse( self.sw.install(pkg_set=["install.tgz", "install.tgz"], cleanfs=False)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc_ValueError(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.remote_checksum = MagicMock( return_value="d41d8cd98f00b204e9800998ecf8427e") self.sw._RE_list = ("version_RE0", "version_RE1") with patch( "jnpr.junos.utils.sw.SW.local_md5", MagicMock(return_value="d41d8cd98f00b204e9800998ecf8427e"), ): self.assertRaises(ValueError, self.sw.install, pkg_set="install.tgz", cleanfs=False) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_install_mixed_vc_TypeError(self, mock_pkgadd): self.assertRaises(TypeError, self.sw.install, cleanfs=False) @patch("jnpr.junos.Device.execute") def test_sw_install_vmhost(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.assertTrue(self.sw.install(package, no_copy=True, vmhost=True)) @patch("jnpr.junos.Device.execute") def test_sw_install_kwargs_force_host(self, mock_execute): self.sw.install("file", no_copy=True, force_host=True) rpc = [ "<request-package-add><force-host/><no-validate/><re1/><package-name>/var/tmp/file</package-name></request-package-add>", "<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><force-host/><re1/></request-package-add>", "<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><re1/><force-host/></request-package-add>", "<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name><re1/></request-package-add>", "<request-package-add><force-host/><re1/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>", "<request-package-add><no-validate/><re1/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>", "<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><force-host/><re1/></request-package-add>", "<request-package-add><force-host/><package-name>/var/tmp/file</package-name><no-validate/><re1/></request-package-add>", "<request-package-add><re1/><no-validate/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>", "<request-package-add><re1/><force-host/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>", "<request-package-add><re1/><package-name>/var/tmp/file</package-name><force-host/><no-validate/></request-package-add>", "<request-package-add><re1/><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>", "<request-package-add><no-validate/><force-host/><re1/><package-name>/var/tmp/file</package-name></request-package-add>", "<request-package-add><package-name>/var/tmp/file</package-name><force-host/><no-validate/><re1/></request-package-add>", "<request-package-add><no-validate/><re1/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>", "<request-package-add><package-name>/var/tmp/file</package-name><force-host/><re1/><no-validate/></request-package-add>", "<request-package-add><no-validate/><force-host/><package-name>/var/tmp/file</package-name><re1/></request-package-add>", "<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>", "<request-package-add><force-host/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>", "<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><force-host/></request-package-add>", "<request-package-add><no-validate/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>", "<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>", "<request-package-add><package-name>/var/tmp/file</package-name><force-host/><no-validate/></request-package-add>", "<request-package-add><package-name>/var/tmp/file</package-name><re1/><no-validate/><force-host/></request-package-add>", "<request-package-add><package-name>/var/tmp/file</package-name><re1/><force-host/><no-validate/></request-package-add>", "<request-package-add><force-host/><package-name>/var/tmp/file</package-name><re1/><no-validate/></request-package-add>", "<request-package-add><re1/><package-name>/var/tmp/file</package-name><no-validate/><force-host/></request-package-add>", "<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><re1/><force-host/></request-package-add>", "<request-package-add><re1/><no-validate/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>", "<request-package-add><force-host/><re1/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>", ] self.assertTrue( etree.tostring(mock_execute.call_args[0][0]).decode("utf-8") in rpc) @patch("jnpr.junos.Device.execute") def test_sw_rollback(self, mock_execute): rsp = ("<rpc-reply><output>junos-vsrx-12.1X46-D30.2-domestic will " "become active at next reboot</output></rpc-reply>") mock_execute.side_effect = etree.XML(rsp) msg = "junos-vsrx-12.1X46-D30.2-domestic will become active " "at next reboot" self.assertEqual(self.sw.rollback(), msg) @patch("jnpr.junos.Device.execute") def test_sw_rollback_multi(self, mock_execute): mock_execute.side_effect = self._mock_manager msg = { "fpc1": "Junos version 'D10.2' will become active at next reboot", "fpc0": 'JUNOS version "D10.2" will become active at next reboot', } self.assertEqual(eval(self.sw.rollback()), msg) @patch("jnpr.junos.Device.execute") @unittest.skipIf(sys.platform == "win32", "will work for windows in coming days") def test_sw_rollback_multi_exception(self, mock_execute): fname = "request-package-rollback-multi-error.xml" mock_execute.side_effect = self._read_file(fname) self.assertRaises(SwRollbackError, self.sw.rollback) @patch("jnpr.junos.Device.execute") def test_sw_rollback_exception(self, mock_execute): rsp = ("<rpc-reply><output>WARNING: Cannot rollback, " "/packages/junos.old is not valid</output></rpc-reply>") mock_execute.side_effect = etree.XML(rsp) self.assertRaises(SwRollbackError, self.sw.rollback) def test_sw_inventory(self): self.sw.dev.rpc.file_list = MagicMock(side_effect=self._mock_manager) self.assertEqual(self.sw.inventory, { "current": None, "rollback": None }) @patch("jnpr.junos.Device.execute") def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue("Shutdown NOW" in self.sw.reboot()) @patch("jnpr.junos.Device.execute") def test_sw_reboot_at(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue("Shutdown at" in self.sw.reboot(at="201407091815")) @patch("jnpr.junos.Device.execute") def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue("Shutdown NOW" in self.sw.reboot()) @patch("jnpr.junos.Device.execute") def test_sw_reboot_mixed_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw._multi_VC = True self.sw.reboot() self.assertTrue("all-members" in ( etree.tostring(mock_execute.call_args[0][0]).decode("utf-8"))) @patch("jnpr.junos.Device.execute") def test_sw_reboot_mixed_vc_all_re_false(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw._multi_VC = True self.sw.reboot(all_re=False) self.assertTrue("all-members" not in ( etree.tostring(mock_execute.call_args[0][0]).decode("utf-8"))) @patch("jnpr.junos.Device.execute") def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML("<rpc-reply><a>test</a></rpc-reply>") mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch("jnpr.junos.Device.execute") def test_sw_reboot_exception_RpcTimeoutError(self, mock_execute): rsp = (self.dev, "request-reboot", 60) mock_execute.side_effect = RpcTimeoutError(*rsp) self.assertRaises(Exception, self.sw.reboot) @patch("jnpr.junos.Device.execute") def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue("Shutdown NOW" in self.sw.poweroff()) @patch("jnpr.junos.Device.execute") def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML("<rpc-reply><a>test</a></rpc-reply>") mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch("jnpr.junos.Device.execute") def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue("Shutdown NOW" in self.sw.poweroff()) @patch("jnpr.junos.Device.execute") def test_sw_check_pending_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = "test.tgz" self.assertFalse(self.sw.install(package)) @patch("jnpr.junos.utils.sw.SW.pkgadd") def test_sw_check_pending_install_RpcError_continue(self, mock_pkgadd): mock_pkgadd.return_value = True self.assertTrue(self.sw.install("test.tgz", no_copy=True)) def _myprogress(self, dev, report): pass def _my_scp_progress(self, _path, _total, _xfrd): print(_path, _total, _xfrd) @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), "rpc-reply", fname) foo = open(fpath).read() rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply() )._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs and "ignore_warning" not in kwargs: # Little hack for mocked execute if "dev_timeout" in kwargs: if (args and args[0].findtext("package-name") == "/var/tmp/test_no_result.tgz"): return self._read_file(args[0].tag + ".no_result.xml") else: return self._read_file(args[0].tag + ".xml") if "path" in kwargs: if kwargs["path"] == "/packages": return self._read_file("file-list_dir.xml") device_params = kwargs["device_params"] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].find("at") is not None: return self._read_file("request-reboot-at.xml") elif self._testMethodName == "test_sw_check_pending_install": if args[0].text == "request-package-check-pending-install": return self._read_file( "request-package-check-pending-install-error.xml") elif (self._testMethodName == "test_sw_check_pending_install_RpcError_continue"): if args[0].text == "request-package-check-pending-install": xml = """<rpc-error> <error-type>protocol</error-type> <error-tag>operation-failed</error-tag> <error-severity>error</error-severity> <error-message>syntax error</error-message> <error-info> <bad-element>request-package-check-pendings-install</bad-element> </error-info> </rpc-error>""" return RpcError(rsp=etree.fromstring(xml)) else: return self._read_file(args[0].tag + ".xml")
class TestSW(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.dev.facts = facts self.sw = self.get_sw() @patch('jnpr.junos.Device.execute') def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch(builtin_string + '.open', mock_open(), create=True): import jnpr.junos.utils.sw with open('foo') as h: h.read.side_effect = ('abc', 'a', '') jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertTrue(self.sw._multi_RE) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch(builtin_string + '.open') def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual( SW.local_sha256(package), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855') @patch(builtin_string + '.open') def test_sw_local_md5(self, mock_built_open): package = 'test.tgz' self.assertEqual(self.sw.local_md5(package), 'd41d8cd98f00b204e9800998ecf8427e') @patch(builtin_string + '.open') def test_sw_local_sha1(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha1(package), 'da39a3ee5e6b4b0d3255bfef95601890afd80709') def test_sw_progress(self): with self.capture(SW.progress, self.dev, 'running') as output: self.assertEqual('1.1.1.1: running\n', output) @patch('jnpr.junos.Device.execute') @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_progress_true(self, scp_put, mock_paramiko, mock_execute): mock_execute.side_effect = self._mock_manager with self.capture(SW.progress, self.dev, 'testing') as output: self.sw.install('test.tgz', progress=True, checksum=345, cleanfs=False) self.assertEqual('1.1.1.1: testing\n', output) @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_put(self, mock_scp_put, mock_scp): package = 'test.tgz' self.sw.put(package) self.assertTrue( call('test.tgz', '/var/tmp') in mock_scp_put.mock_calls) @patch('jnpr.junos.utils.sw.FTP') def test_sw_put_ftp(self, mock_ftp_put): dev = Device(host='1.1.1.1', user='******', password='******', mode='telnet', port=23, gather_facts=False) sw = SW(dev) sw.put(package='test.tgz') self.assertTrue( call('test.tgz', '/var/tmp') in mock_ftp_put.mock_calls) @patch('jnpr.junos.utils.scp.SCP.__exit__') @patch('jnpr.junos.utils.scp.SCP.__init__') @patch('jnpr.junos.utils.scp.SCP.__enter__') def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = 'test.tgz' mock_scp.side_effect = self._fake_scp with self.capture(self.sw.put, package, progress=self._my_scp_progress) as output: self.assertEqual('test.tgz 100 50\n', output) def _fake_scp(self, *args, **kwargs): progress = kwargs['progress'] progress('test.tgz', 100, 50) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgadd(package)) @patch('jnpr.junos.Device.execute') def test_sw_install_single_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = False self.assertTrue(self.sw.install('test.tgz', no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_issu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.install(package, issu=True, no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_nssu(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.install(package, nssu=True, no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_issu_nssu_both_error(self, mock_execute): mock_execute.side_effect = self._mock_manager try: self.sw.install('test.tgz', issu=True, nssu=True) except TypeError as ex: self.assertEqual( str(ex), 'install function can either take issu or nssu not both') @patch('jnpr.junos.Device.execute') def test_sw_install_issu_single_re_error(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = False try: self.sw.install('test.tgz', issu=True) except TypeError as ex: self.assertEqual(str(ex), 'ISSU/NSSU requires Multi RE setup') @patch('jnpr.junos.Device.execute') def test_sw_install_issu_nssu_single_re_error(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.sw._multi_RE = False self.assertRaises(TypeError, self.sw.install, package, nssu=True, issu=True) @patch('jnpr.junos.Device.execute') def test_sw_pkgaddISSU(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgaddISSU(package)) @patch('jnpr.junos.Device.execute') def test_sw_pkgaddNSSU(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgaddNSSU(package)) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd_pkg_set(self, mock_execute): mock_execute.side_effect = self._mock_manager pkg_set = ['abc.tgz', 'pqr.tgz'] self.sw._mixed_VC = True self.sw.pkgadd(pkg_set) self.assertEqual( [i.text for i in mock_execute.call_args[0][0].findall('set')], pkg_set) @patch('jnpr.junos.Device.execute') def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue(self.sw.validate('package.tgz')) @patch('jnpr.junos.Device.execute') def test_sw_validate_nssu(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw.log = MagicMock() # get_config returns false self.assertFalse(self.sw.validate('package.tgz', nssu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: GRES is not Enabled in configuration') @patch('jnpr.junos.Device.execute') def test_sw_validate_issu(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.assertTrue(self.sw.validate('package.tgz', issu=True)) @patch('jnpr.junos.Device.execute') def test_sw_val_issu_request_shell_execute_gres_on(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.request_shell_execute = MagicMock() self.dev.rpc.request_shell_execute.return_value = etree.fromstring( """<rpc-reply> <output>Graceful switchover: On</output> </rpc-reply>""") self.assertTrue(self.sw.validate('package.tgz', issu=True)) @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_2re_false(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.facts['2RE'] = False self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.dev.facts['2RE'] = True @patch('paramiko.SSHClient') @patch('jnpr.junos.utils.start_shell.StartShell.wait_for') def test_sw_validate_issu_request_shell_execute(self, mock_ss, mock_ssh): self._issu_test_helper() with patch('jnpr.junos.utils.start_shell.StartShell.run') as ss: ss.return_value = (True, 'Graceful switchover: On') self.assertTrue(self.sw.validate('package.tgz', issu=True)) @patch('paramiko.SSHClient') @patch('jnpr.junos.utils.start_shell.StartShell.wait_for') def test_sw_validate_issu_ss_login_other_re_fail(self, mock_ss, mock_ssh): self._issu_test_helper() with patch('jnpr.junos.utils.start_shell.StartShell.run') as ss: ss.return_value = (False, 'Graceful switchover: On') self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: Not able run "show system switchover"') @patch('paramiko.SSHClient') @patch('jnpr.junos.utils.start_shell.StartShell.wait_for') def test_sw_validate_issu_ss_graceful_off(self, mock_ss, mock_ssh): self._issu_test_helper() with patch('jnpr.junos.utils.start_shell.StartShell.run') as ss: ss.return_value = (True, 'Graceful switchover: Off') self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: Graceful switchover status is not On') def _issu_test_helper(self): self.sw.log = MagicMock() self.dev.rpc.request_shell_execute = MagicMock() self.dev.rpc = MagicMock() self.dev.rpc.get_routing_task_replication_state.return_value = \ self._read_file('get-routing-task-replication-state.xml') self.dev.rpc.check_in_service_upgrade.return_value = \ self._read_file('check-in-service-upgrade.xml') self.dev.rpc.request_shell_execute.side_effect = \ RpcError(rsp='not ok') @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_stateful_replication_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_routing_task_replication_state = MagicMock() self.sw.log = MagicMock() self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: Either Stateful Replication is not Enabled or RE mode\nis not Master' ) @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_commit_sync_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_config.return_value = etree.fromstring(""" <configuration> <chassis> <redundancy> <graceful-switchover> </graceful-switchover> </redundancy> </chassis> </configuration>""") self.sw.log = MagicMock() self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: commit synchronize is not Enabled in configuration' ) @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_nonstop_routing_off(self, mock_execute): mock_execute.side_effect = self._mock_manager self.dev.rpc.get_config = MagicMock() self.dev.rpc.get_config.side_effect = iter([ etree.fromstring(""" <configuration> <chassis> <redundancy> <graceful-switchover> </graceful-switchover> </redundancy> </chassis> </configuration>"""), etree.fromstring(""" <configuration> <system> <commit> <synchronize/> </commit> </system> </configuration>"""), etree.fromstring("""<configuration> <routing-options></routing-options> </configuration>""") ]) self.sw.log = MagicMock() self.assertFalse(self.sw.validate('package.tgz', issu=True)) self.sw.log.assert_called_with( 'Requirement FAILED: NSR is not Enabled in configuration') @patch('jnpr.junos.Device.execute') def test_sw_validate_issu_validation_succeeded(self, mock_execute): rpc_reply = """<rpc-reply><output>mgd: commit complete Validation succeeded </output> <package-result>1</package-result> </rpc-reply>""" mock_execute.side_effect = etree.fromstring(rpc_reply) package = 'package.tgz' self.assertFalse(self.sw.validate(package, issu=True)) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_not_found(self, mock_execute): xml = '''<rpc-error> <error-severity>error</error-severity> <error-message> md5: /var/tmp/123: No such file or directory </error-message> </rpc-error>''' mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = 'test.tgz' self.assertEqual(self.sw.remote_checksum(package), None) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_not_rpc_error(self, mock_execute): xml = '''<rpc-error> <error-severity>error</error-severity> <error-message> something else! </error-message> </rpc-error>''' mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = 'test.tgz' with self.assertRaises(RpcError): self.sw.remote_checksum(package) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertTrue( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True, checksum='96a35ab371e1ca10408c3caecdbd8a67')) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertFalse( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'install.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue( self.sw.install(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.utils.sw.SW.safe_copy') def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install('file')) @patch('jnpr.junos.utils.sw.SW.validate') def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install('file', validate=True, no_copy=True)) @patch(builtin_string + '.print') @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_mx(self, mock_pkgadd, mock_print): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install('file', no_copy=True, progress=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue( self.sw.install(pkg_set=['abc.tgz', 'pqr.tgz'], no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc_mode_disabled(self, mock_pkgadd): mock_pkgadd.return_value = True self.dev._facts = { '2RE': True, 'domain': None, 'RE1': { 'status': 'OK', 'model': 'RE-EX8208', 'mastership_state': 'backup' }, 'ifd_style': 'SWITCH', 'version_RE1': '12.3R7.7', 'version_RE0': '12.3', 'serialnumber': 'XXXXXX', 'fqdn': 'XXXXXX', 'RE0': { 'status': 'OK', 'model': 'RE-EX8208', 'mastership_state': 'master' }, 'switch_style': 'VLAN', 'version': '12.3R5-S3.1', 'master': 'RE0', 'hostname': 'XXXXXX', 'HOME': '/var/home/sn', 'vc_mode': 'Disabled', 'model': 'EX8208', 'vc_capable': True, 'personality': 'SWITCH' } sw = self.get_sw() sw.install(package='abc.tgz', no_copy=True) self.assertFalse(sw._multi_VC) calls = [ call('/var/tmp/abc.tgz', dev_timeout=1800, re0=True), call('/var/tmp/abc.tgz', dev_timeout=1800, re1=True) ] mock_pkgadd.assert_has_calls(calls) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_with_copy(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.put = MagicMock() self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertTrue( self.sw.install(pkg_set=['install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_safe_copy_false(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.safe_copy = MagicMock(return_value=False) self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertFalse( self.sw.install(pkg_set=['install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_ValueError(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertRaises(ValueError, self.sw.install, pkg_set='install.tgz', cleanfs=False) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_TypeError(self, mock_pkgadd): self.assertRaises(TypeError, self.sw.install, cleanfs=False) @patch('jnpr.junos.Device.execute') def test_sw_install_kwargs_force_host(self, mock_execute): self.sw.install('file', no_copy=True, force_host=True) rpc = [ '<request-package-add><force-host/><no-validate/><re1/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><force-host/><re1/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><re1/><force-host/></request-package-add>', '<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name><re1/></request-package-add>', '<request-package-add><force-host/><re1/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><re1/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><force-host/><re1/></request-package-add>', '<request-package-add><force-host/><package-name>/var/tmp/file</package-name><no-validate/><re1/></request-package-add>', '<request-package-add><re1/><no-validate/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><re1/><force-host/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>', '<request-package-add><re1/><package-name>/var/tmp/file</package-name><force-host/><no-validate/></request-package-add>', '<request-package-add><re1/><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><force-host/><re1/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><no-validate/><re1/></request-package-add>', '<request-package-add><no-validate/><re1/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><re1/><no-validate/></request-package-add>', '<request-package-add><no-validate/><force-host/><package-name>/var/tmp/file</package-name><re1/></request-package-add>', '<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><force-host/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><no-validate/><force-host/></request-package-add>', '<request-package-add><no-validate/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><force-host/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><force-host/><no-validate/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><re1/><no-validate/><force-host/></request-package-add>', '<request-package-add><package-name>/var/tmp/file</package-name><re1/><force-host/><no-validate/></request-package-add>', '<request-package-add><force-host/><package-name>/var/tmp/file</package-name><re1/><no-validate/></request-package-add>', '<request-package-add><re1/><package-name>/var/tmp/file</package-name><no-validate/><force-host/></request-package-add>', '<request-package-add><no-validate/><package-name>/var/tmp/file</package-name><re1/><force-host/></request-package-add>', '<request-package-add><re1/><no-validate/><force-host/><package-name>/var/tmp/file</package-name></request-package-add>', '<request-package-add><force-host/><re1/><package-name>/var/tmp/file</package-name><no-validate/></request-package-add>' ] self.assertTrue( etree.tostring(mock_execute.call_args[0][0]).decode('utf-8') in rpc) @patch('jnpr.junos.Device.execute') def test_sw_rollback(self, mock_execute): rsp = '<rpc-reply><output>junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) msg = 'junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi(self, mock_execute): mock_execute.side_effect = self._mock_manager msg = { 'fpc1': "Junos version 'D10.2' will become active at next reboot", 'fpc0': 'JUNOS version "D10.2" will become active at next reboot' } self.assertEqual(eval(self.sw.rollback()), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi_exception(self, mock_execute): fname = 'request-package-rollback-multi-error.xml' mock_execute.side_effect = self._read_file(fname) self.assertRaises(SwRollbackError, self.sw.rollback) @patch('jnpr.junos.Device.execute') def test_sw_rollback_exception(self, mock_execute): rsp = '<rpc-reply><output>WARNING: Cannot rollback, /packages/junos.old is not valid</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) self.assertRaises(SwRollbackError, self.sw.rollback) def test_sw_inventory(self): self.sw.dev.rpc.file_list = \ MagicMock(side_effect=self._mock_manager) self.assertEqual(self.sw.inventory, { 'current': None, 'rollback': None }) @patch('jnpr.junos.Device.execute') def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_at(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Shutdown at' in self.sw.reboot(at='201407091815')) @patch('jnpr.junos.Device.execute') def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_mixed_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw._multi_VC = True self.sw.reboot() self.assertTrue('all-members' in ( etree.tostring(mock_execute.call_args[0][0]).decode('utf-8'))) @patch('jnpr.junos.Device.execute') def test_sw_reboot_mixed_vc_all_re_false(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw._multi_VC = True self.sw.reboot(all_re=False) self.assertTrue('all-members' not in ( etree.tostring(mock_execute.call_args[0][0]).decode('utf-8'))) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception_RpcTimeoutError(self, mock_execute): rsp = (self.dev, 'request-reboot', 60) mock_execute.side_effect = RpcTimeoutError(*rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.poweroff()) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.poweroff()) def _myprogress(self, dev, report): pass def _my_scp_progress(self, _path, _total, _xfrd): print(_path, _total, _xfrd) @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply() )._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs: # Little hack for mocked execute if 'dev_timeout' in kwargs: return self._read_file(args[0].tag + '.xml') if 'path' in kwargs: if kwargs['path'] == '/packages': return self._read_file('file-list_dir.xml') device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].find('at') is not None: return self._read_file('request-reboot-at.xml') else: return self._read_file(args[0].tag + '.xml')
class TestSW(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.dev._facts = facts self.sw = self.get_sw() @patch('jnpr.junos.Device.execute') def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch('__builtin__.open', mock_open(), create=True): import jnpr.junos.utils.sw with open('foo') as h: h.read.side_effect = ('abc', 'a', '') jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_RE) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch('__builtin__.open') def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual( SW.local_sha256(package), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855') @patch('__builtin__.open') def test_sw_local_md5(self, mock_built_open): package = 'test.tgz' self.assertEqual(self.sw.local_md5(package), 'd41d8cd98f00b204e9800998ecf8427e') @patch('__builtin__.open') def test_sw_local_sha1(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha1(package), 'da39a3ee5e6b4b0d3255bfef95601890afd80709') def test_sw_progress(self): with self.capture(SW.progress, self.dev, 'running') as output: self.assertEqual('1.1.1.1: running\n', output) @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_put(self, mock_scp_put, mock_scp): # mock_scp_put.side_effect = self.mock_put package = 'test.tgz' self.sw.put(package) self.assertTrue( call('test.tgz', '/var/tmp') in mock_scp_put.mock_calls) @patch('jnpr.junos.utils.scp.SCP.__exit__') @patch('jnpr.junos.utils.scp.SCP.__init__') @patch('jnpr.junos.utils.scp.SCP.__enter__') def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = 'test.tgz' mock_scp.side_effect = self._fake_scp with self.capture(self.sw.put, package, progress=self._my_scp_progress) as output: self.assertEqual('test.tgz 100 50\n', output) def _fake_scp(self, *args, **kwargs): progress = kwargs['progress'] progress('test.tgz', 100, 50) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgadd(package)) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd_pkg_set(self, mock_execute): mock_execute.side_effect = self._mock_manager pkg_set = ['abc.tgz', 'pqr.tgz'] self.sw._mixed_VC = True self.sw.pkgadd(pkg_set) self.assertEqual( [i.text for i in mock_execute.call_args[0][0].findall('set')], pkg_set) @patch('jnpr.junos.Device.execute') def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'package.tgz' self.assertTrue(self.sw.validate(package)) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_not_found(self, mock_execute): xml = '''<rpc-error> <error-severity>error</error-severity> <error-message> md5: /var/tmp/123: No such file or directory </error-message> </rpc-error>''' mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = 'test.tgz' self.assertEqual(self.sw.remote_checksum(package), None) @patch('jnpr.junos.Device.execute') def test_sw_remote_checksum_not_rpc_error(self, mock_execute): xml = '''<rpc-error> <error-severity>error</error-severity> <error-message> something else! </error-message> </rpc-error>''' mock_execute.side_effect = RpcError(rsp=etree.fromstring(xml)) package = 'test.tgz' with self.assertRaises(RpcError): self.sw.remote_checksum(package) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertTrue( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True, checksum='96a35ab371e1ca10408c3caecdbd8a67')) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertFalse( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'install.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue( self.sw.install(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.utils.sw.SW.safe_copy') def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install('file')) @patch('jnpr.junos.utils.sw.SW.validate') def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install('file', validate=True, no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_mx(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue( self.sw.install(pkg_set=['abc.tgz', 'pqr.tgz'], no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc_mode_disabled(self, mock_pkgadd): mock_pkgadd.return_value = True self.dev._facts = { 'domain': None, 'RE1': { 'status': 'OK', 'model': 'RE-EX8208', 'mastership_state': 'backup' }, 'ifd_style': 'SWITCH', 'version_RE1': '12.3R7.7', 'version_RE0': '12.3', '2RE': True, 'serialnumber': 'XXXXXX', 'fqdn': 'XXXXXX', 'RE0': { 'status': 'OK', 'model': 'RE-EX8208', 'mastership_state': 'master' }, 'switch_style': 'VLAN', 'version': '12.3R5-S3.1', 'master': 'RE0', 'hostname': 'XXXXXX', 'HOME': '/var/home/sn', 'vc_mode': 'Disabled', 'model': 'EX8208', 'vc_capable': True, 'personality': 'SWITCH' } sw = self.get_sw() sw.install(package='abc.tgz', no_copy=True) self.assertFalse(sw._multi_VC) calls = [ call('/var/tmp/abc.tgz', dev_timeout=1800, re0=True), call('/var/tmp/abc.tgz', dev_timeout=1800, re1=True) ] mock_pkgadd.assert_has_calls(calls) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_with_copy(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.put = MagicMock() self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertTrue( self.sw.install(pkg_set=['install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_safe_copy_false(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.safe_copy = MagicMock(return_value=False) self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertFalse( self.sw.install(pkg_set=['install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_ValueError(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertRaises(ValueError, self.sw.install, pkg_set='install.tgz', cleanfs=False) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_TypeError(self, mock_pkgadd): self.assertRaises(TypeError, self.sw.install, cleanfs=False) @patch('jnpr.junos.Device.execute') def test_sw_install_kwargs_force_host(self, mock_execute): self.sw.install('file', no_copy=True, force_host=True) rpc = """<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>""" self.assertEqual(etree.tostring(mock_execute.call_args[0][0]), rpc) @patch('jnpr.junos.Device.execute') def test_sw_rollback(self, mock_execute): rsp = '<rpc-reply><output>junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) msg = 'junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi(self, mock_execute): mock_execute.side_effect = self._mock_manager msg = '{\'fpc1\': "Junos version \'D10.2\' will become active at next reboot", \'fpc0\': \'JUNOS version "D10.2" will become active at next reboot\'}' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi_exception(self, mock_execute): fname = 'request-package-rollback-multi-error.xml' mock_execute.side_effect = self._read_file(fname) self.assertRaises(SwRollbackError, self.sw.rollback) @patch('jnpr.junos.Device.execute') def test_sw_rollback_exception(self, mock_execute): rsp = '<rpc-reply><output>WARNING: Cannot rollback, /packages/junos.old is not valid</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) self.assertRaises(SwRollbackError, self.sw.rollback) def test_sw_inventory(self): self.sw.dev.rpc.file_list = \ MagicMock(side_effect=self._mock_manager) self.assertEqual(self.sw.inventory, { 'current': None, 'rollback': None }) @patch('jnpr.junos.Device.execute') def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_at(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Shutdown at' in self.sw.reboot(at='201407091815')) @patch('jnpr.junos.Device.execute') def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_mixed_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw.reboot() self.assertTrue( 'all-members' in etree.tostring(mock_execute.call_args[0][0])) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception_RpcTimeoutError(self, mock_execute): rsp = (self.dev, 'request-reboot', 60) mock_execute.side_effect = RpcTimeoutError(*rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.poweroff()) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.poweroff()) def _myprogress(self, dev, report): pass def _my_scp_progress(self, _path, _total, _xfrd): print _path, _total, _xfrd @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply() )._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs: # Little hack for mocked execute if 'dev_timeout' in kwargs: return self._read_file(args[0].tag + '.xml') if 'path' in kwargs: if kwargs['path'] == '/packages': return self._read_file('file-list_dir.xml') device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].find('at') is not None: return self._read_file('request-reboot-at.xml') else: return self._read_file(args[0].tag + '.xml')
class TestSW(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.dev._facts = facts self.sw = self.get_sw() @patch('jnpr.junos.Device.execute') def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch('__builtin__.open', mock_open(), create=True): import jnpr.junos.utils.sw with open('foo') as h: h.read.side_effect = ('abc', 'a', '') jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_RE) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch('__builtin__.open') def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual( SW.local_sha256(package), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855') @patch('__builtin__.open') def test_sw_local_md5(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_md5(package), 'd41d8cd98f00b204e9800998ecf8427e') @patch('__builtin__.open') def test_sw_local_sha1(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha1(package), 'da39a3ee5e6b4b0d3255bfef95601890afd80709') def test_sw_progress(self): with self.capture(SW.progress, self.dev, 'running') as output: self.assertEqual('1.1.1.1: running\n', output) @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_put(self, mock_scp_put, mock_scp): # mock_scp_put.side_effect = self.mock_put package = 'test.tgz' self.sw.put(package) self.assertTrue( call('test.tgz', '/var/tmp') in mock_scp_put.mock_calls) @patch('jnpr.junos.utils.scp.SCP.__exit__') @patch('jnpr.junos.utils.scp.SCP.__init__') @patch('jnpr.junos.utils.scp.SCP.__enter__') def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = 'test.tgz' mock_scp.side_effect = self._fake_scp self.sw.put(package, progress=self._myprogress) self.assertEqual(mock_scp.call_args_list[0][1]['progress'].by10pct, 50) def _fake_scp(self, *args, **kwargs): progress = kwargs['progress'] progress('test.tgz', 100, 50) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgadd(package)) @patch('jnpr.junos.Device.execute') def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'package.tgz' self.assertTrue(self.sw.validate(package)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() SW.local_md5 = MagicMock() self.assertTrue( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True, checksum='96a35ab371e1ca10408c3caecdbd8a67')) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() SW.local_md5 = MagicMock() self.assertFalse( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) SW.local_md5.assert_called_with(package) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() SW.local_md5 = MagicMock( return_value='96a35ab371e1ca10408c3caecdbd8a67') self.assertTrue( self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'install.tgz' self.sw.put = MagicMock() SW.local_md5 = MagicMock( return_value='96a35ab371e1ca10408c3caecdbd8a67') self.assertTrue( self.sw.install(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.utils.sw.SW.safe_copy') def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install('file')) @patch('jnpr.junos.utils.sw.SW.validate') def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install('file', validate=True, no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_mx(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.Device.execute') def test_sw_install_kwargs_force_host(self, mock_execute): self.sw.install('file', no_copy=True, force_host=True) rpc = """<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>""" self.assertEqual(etree.tostring(mock_execute.call_args[0][0]), rpc) @patch('jnpr.junos.Device.execute') def test_sw_rollback(self, mock_execute): rsp = '<rpc-reply><output>junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) msg = 'junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi(self, mock_execute): mock_execute.side_effect = self._mock_manager msg = '{\'fpc1\': "Junos version \'D10.2\' will become active at next reboot", \'fpc0\': \'JUNOS version "D10.2" will become active at next reboot\'}' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi_exception(self, mock_execute): fname = 'request-package-rollback-multi-error.xml' mock_execute.side_effect = self._read_file(fname) self.assertRaises(SwRollbackError, self.sw.rollback) @patch('jnpr.junos.Device.execute') def test_sw_rollback_exception(self, mock_execute): rsp = '<rpc-reply><output>WARNING: Cannot rollback, /packages/junos.old is not valid</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) self.assertRaises(SwRollbackError, self.sw.rollback) def test_sw_inventory(self): self.sw.dev.rpc.file_list = \ MagicMock(side_effect=self._mock_manager) self.assertEqual(self.sw.inventory, { 'current': None, 'rollback': None }) @patch('jnpr.junos.Device.execute') def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_at(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Shutdown at' in self.sw.reboot(at='201407091815')) @patch('jnpr.junos.Device.execute') def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.poweroff()) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.poweroff()) def _myprogress(self, dev, report): pass @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() rpc_reply = NCElement(foo, self.dev._conn._device_handler.transform_reply() )._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs: # Little hack for mocked execute if kwargs == {'dev_timeout': 1800}: return self._read_file(args[0].tag + '.xml') if 'path' in kwargs: if kwargs['path'] == '/packages': return self._read_file('file-list_dir.xml') device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].find('at') is not None: return self._read_file('request-reboot-at.xml') else: return self._read_file(args[0].tag + '.xml')
from jnpr.junos import Device from jnpr.junos.utils.sw import SW USER = "******" PASSWD = "lab123" DEVICE_IP = "10.254.0.41" def update_progress(dev, report): print(report) dev = Device(host=DEVICE_IP, user=USER, password=PASSWD) dev.open() sw = SW(dev) ok = sw.install(package="/var/tmp/junos-vmx-x86-64-17.1R2.7.tgz", no_copy=True, progress=update_progress, validate=False) print(ok) sw.reboot()
def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev)
def shutdown(**kwargs): ''' Shut down (power off) or reboot a device running Junos OS. This includes all Routing Engines in a Virtual Chassis or a dual Routing \ Engine system. Usage: .. code-block:: bash salt 'device_name' junos.shutdown reboot=True salt 'device_name' junos.shutdown shutdown=True in_min=10 salt 'device_name' junos.shutdown shutdown=True Parameters: Optional * kwargs: * shutdown: Set this to true if you want to shutdown the machine. (default=False, this is a safety mechanism so that the user does not accidentally shutdown the junos device.) * reboot: Whether to reboot instead of shutdown. (default=False) Note that either one of the above arguments has to be specified (shutdown or reboot) for this function to work. * at: Date and time the reboot should take place. The string must match the junos cli reboot syntax (To be used only if reboot=True) * in_min: Specify delay in minutes for shutdown ''' conn = __proxy__['junos.conn']() ret = dict() sw = SW(conn) op = dict() if '__pub_arg' in kwargs: if kwargs['__pub_arg']: if isinstance(kwargs['__pub_arg'][-1], dict): op.update(kwargs['__pub_arg'][-1]) else: op.update(kwargs) if 'shutdown' not in op and 'reboot' not in op: ret['message'] = \ 'Provide either one of the arguments: shutdown or reboot.' ret['out'] = False return ret try: if 'reboot' in op and op['reboot']: shut = sw.reboot elif 'shutdown' in op and op['shutdown']: shut = sw.poweroff else: ret['message'] = 'Nothing to be done.' ret['out'] = False return ret if 'in_min' in op: shut(in_min=op['in_min']) elif 'at' in op: shut(at=op['at']) else: shut() ret['message'] = 'Successfully powered off/rebooted.' ret['out'] = True except Exception as exception: ret['message'] = \ 'Could not poweroff/reboot beacause "{0}"'.format(exception) ret['out'] = False return ret
def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual( SW.local_sha256(package), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855')
class TestSW(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.dev._facts = facts self.sw = self.get_sw() @patch('jnpr.junos.Device.execute') def get_sw(self, mock_execute): mock_execute.side_effect = self._mock_manager return SW(self.dev) @patch('ncclient.operations.session.CloseSession.request') def tearDown(self, mock_session): self.dev.close() def test_sw_hashfile(self): with patch('__builtin__.open', mock_open(), create=True): import jnpr.junos.utils.sw with open('foo') as h: h.read.side_effect = ('abc', 'a', '') jnpr.junos.utils.sw._hashfile(h, MagicMock()) self.assertEqual(h.read.call_count, 3) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_re(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_RE) @patch('jnpr.junos.Device.execute') def test_sw_constructor_multi_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw = SW(self.dev) self.assertFalse(self.sw._multi_VC) @patch('__builtin__.open') def test_sw_local_sha256(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha256(package), 'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934' 'ca495991b7852b855') @patch('__builtin__.open') def test_sw_local_md5(self, mock_built_open): package = 'test.tgz' self.assertEqual(self.sw.local_md5(package), 'd41d8cd98f00b204e9800998ecf8427e') @patch('__builtin__.open') def test_sw_local_sha1(self, mock_built_open): package = 'test.tgz' self.assertEqual(SW.local_sha1(package), 'da39a3ee5e6b4b0d3255bfef95601890afd80709') def test_sw_progress(self): with self.capture(SW.progress, self.dev, 'running') as output: self.assertEqual('1.1.1.1: running\n', output) @patch('paramiko.SSHClient') @patch('scp.SCPClient.put') def test_sw_put(self, mock_scp_put, mock_scp): # mock_scp_put.side_effect = self.mock_put package = 'test.tgz' self.sw.put(package) self.assertTrue( call( 'test.tgz', '/var/tmp') in mock_scp_put.mock_calls) @patch('jnpr.junos.utils.scp.SCP.__exit__') @patch('jnpr.junos.utils.scp.SCP.__init__') @patch('jnpr.junos.utils.scp.SCP.__enter__') def test_sw_put_progress(self, mock_enter, mock_scp, mock_exit): package = 'test.tgz' mock_scp.side_effect = self._fake_scp self.sw.put(package, progress=self._myprogress) self.assertEqual(mock_scp.call_args_list[0][1]['progress'].by10pct, 50) def _fake_scp(self, *args, **kwargs): progress = kwargs['progress'] progress('test.tgz', 100, 50) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'test.tgz' self.assertTrue(self.sw.pkgadd(package)) @patch('jnpr.junos.Device.execute') def test_sw_pkgadd_pkg_set(self, mock_execute): mock_execute.side_effect = self._mock_manager pkg_set = ['abc.tgz', 'pqr.tgz'] self.sw._mixed_VC = True self.sw.pkgadd(pkg_set) self.assertEqual([i.text for i in mock_execute.call_args[0][0].findall('set')], pkg_set) @patch('jnpr.junos.Device.execute') def test_sw_validate(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'package.tgz' self.assertTrue(self.sw.validate(package)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True, checksum='96a35ab371e1ca10408c3caecdbd8a67')) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_return_false(self, mock_execute): # not passing checksum value, will get random from magicmock mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5'): self.assertFalse(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_copy_checksum_none(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'safecopy.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue(self.sw.safe_copy(package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.Device.execute') def test_sw_safe_install(self, mock_execute): mock_execute.side_effect = self._mock_manager package = 'install.tgz' self.sw.put = MagicMock() with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='96a35ab371e1ca10408c3caecdbd8a67')): self.assertTrue( self.sw.install( package, progress=self._myprogress, cleanfs=True)) @patch('jnpr.junos.utils.sw.SW.safe_copy') def test_sw_safe_install_copy_fail(self, mock_copy): mock_copy.return_value = False self.assertFalse(self.sw.install('file')) @patch('jnpr.junos.utils.sw.SW.validate') def test_sw_install_validate(self, mock_validate): mock_validate.return_value = False self.assertFalse(self.sw.install('file', validate=True, no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_mx(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_MX = True self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_multi_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._multi_RE = True self.sw._multi_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install('file', no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw._RE_list = ('version_RE0', 'version_RE1') self.assertTrue(self.sw.install(pkg_set=['abc.tgz', 'pqr.tgz'], no_copy=True)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_with_copy(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.put = MagicMock() self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertTrue( self.sw.install( pkg_set=[ 'install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_safe_copy_false(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.safe_copy = MagicMock(return_value=False) self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertFalse( self.sw.install( pkg_set=[ 'install.tgz', 'install.tgz'], cleanfs=False)) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_ValueError(self, mock_pkgadd): mock_pkgadd.return_value = True self.sw._mixed_VC = True self.sw.remote_checksum = MagicMock( return_value='d41d8cd98f00b204e9800998ecf8427e') self.sw._RE_list = ('version_RE0', 'version_RE1') with patch('jnpr.junos.utils.sw.SW.local_md5', MagicMock(return_value='d41d8cd98f00b204e9800998ecf8427e')): self.assertRaises( ValueError, self.sw.install, pkg_set='install.tgz', cleanfs=False) @patch('jnpr.junos.utils.sw.SW.pkgadd') def test_sw_install_mixed_vc_TypeError(self, mock_pkgadd): self.assertRaises(TypeError, self.sw.install, cleanfs=False) @patch('jnpr.junos.Device.execute') def test_sw_install_kwargs_force_host(self, mock_execute): self.sw.install('file', no_copy=True, force_host=True) rpc = """<request-package-add><force-host/><no-validate/><package-name>/var/tmp/file</package-name></request-package-add>""" self.assertEqual(etree.tostring(mock_execute.call_args[0][0]), rpc) @patch('jnpr.junos.Device.execute') def test_sw_rollback(self, mock_execute): rsp = '<rpc-reply><output>junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) msg = 'junos-vsrx-12.1X46-D30.2-domestic will become active at next reboot' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi(self, mock_execute): mock_execute.side_effect = self._mock_manager msg = '{\'fpc1\': "Junos version \'D10.2\' will become active at next reboot", \'fpc0\': \'JUNOS version "D10.2" will become active at next reboot\'}' self.assertEqual(self.sw.rollback(), msg) @patch('jnpr.junos.Device.execute') def test_sw_rollback_multi_exception(self, mock_execute): fname = 'request-package-rollback-multi-error.xml' mock_execute.side_effect = self._read_file(fname) self.assertRaises(SwRollbackError, self.sw.rollback) @patch('jnpr.junos.Device.execute') def test_sw_rollback_exception(self, mock_execute): rsp = '<rpc-reply><output>WARNING: Cannot rollback, /packages/junos.old is not valid</output></rpc-reply>' mock_execute.side_effect = etree.XML(rsp) self.assertRaises(SwRollbackError, self.sw.rollback) def test_sw_inventory(self): self.sw.dev.rpc.file_list = \ MagicMock(side_effect=self._mock_manager) self.assertEqual( self.sw.inventory, { 'current': None, 'rollback': None}) @patch('jnpr.junos.Device.execute') def test_sw_reboot(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_at(self, mock_execute): mock_execute.side_effect = self._mock_manager self.assertTrue('Shutdown at' in self.sw.reboot(at='201407091815')) @patch('jnpr.junos.Device.execute') def test_sw_reboot_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.reboot()) @patch('jnpr.junos.Device.execute') def test_sw_reboot_mixed_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._mixed_VC = True self.sw.reboot() self.assertTrue('all-members' in etree.tostring(mock_execute.call_args[0][0])) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_reboot_exception_RpcTimeoutError(self, mock_execute): rsp = (self.dev, 'request-reboot', 60) mock_execute.side_effect = RpcTimeoutError(*rsp) self.assertRaises(Exception, self.sw.reboot) @patch('jnpr.junos.Device.execute') def test_sw_poweroff(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_MX = True self.assertTrue('Shutdown NOW' in self.sw.poweroff()) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_exception(self, mock_execute): rsp = etree.XML('<rpc-reply><a>test</a></rpc-reply>') mock_execute.side_effect = RpcError(rsp=rsp) self.assertRaises(Exception, self.sw.poweroff) @patch('jnpr.junos.Device.execute') def test_sw_poweroff_multi_re_vc(self, mock_execute): mock_execute.side_effect = self._mock_manager self.sw._multi_RE = True self.sw._multi_VC = False self.assertTrue('Shutdown NOW' in self.sw.poweroff()) def _myprogress(self, dev, report): pass @contextmanager def capture(self, command, *args, **kwargs): out, sys.stdout = sys.stdout, StringIO() command(*args, **kwargs) sys.stdout.seek(0) yield sys.stdout.read() sys.stdout = out def _read_file(self, fname): from ncclient.xml_ import NCElement fpath = os.path.join(os.path.dirname(__file__), 'rpc-reply', fname) foo = open(fpath).read() rpc_reply = NCElement( foo, self.dev._conn._device_handler.transform_reply())._NCElement__doc[0] return rpc_reply def _mock_manager(self, *args, **kwargs): if kwargs: # Little hack for mocked execute if kwargs == {'dev_timeout': 1800}: return self._read_file(args[0].tag + '.xml') if 'path' in kwargs: if kwargs['path'] == '/packages': return self._read_file('file-list_dir.xml') device_params = kwargs['device_params'] device_handler = make_device_handler(device_params) session = SSHSession(device_handler) return Manager(session, device_handler) elif args: if args[0].find('at') is not None: return self._read_file('request-reboot-at.xml') else: return self._read_file(args[0].tag + '.xml')
from yaml import load from jnpr.junos.utils.sw import SW from jnpr.junos import Device f = open('inventory.yml', 'r') devices_list = load(f.read())['devices_list'] f.close() pkgs_list = [ 'network-agent-x86-32-18.2R1-S3.2-C1.tgz', 'junos-openconfig-x86-32-0.0.0.10-1.tgz' ] for pkg in pkgs_list: for item in devices_list: print 'adding the package ' + pkg + ' to the device ' + item[ 'device-id'] device = Device( host=item['host'], user=item['authentication']['password']['username'], password=item['authentication']['password']['password']) device.open() sw = SW(device) sw.install(package=pkg, validate=False, no_copy=False, progress=True, remote_path="/var/home/jcluser") device.close()
class JunosDevice(BaseDevice): """Juniper JunOS Device Implementation.""" vendor = "juniper" def __init__(self, host, username, password, *args, **kwargs): super().__init__(host, username, password, *args, device_type="juniper_junos_netconf", **kwargs) self.native = JunosNativeDevice(*args, host=host, user=username, passwd=password, **kwargs) self.open() self.cu = JunosNativeConfig(self.native) self.fs = JunosNativeFS(self.native) self.sw = JunosNativeSW(self.native) def _file_copy_local_file_exists(self, filepath): return os.path.isfile(filepath) def _file_copy_local_md5(self, filepath, blocksize=2**20): if self._file_copy_local_file_exists(filepath): m = hashlib.md5() # nosec with open(filepath, "rb") as f: buf = f.read(blocksize) while buf: m.update(buf) buf = f.read(blocksize) return m.hexdigest() def _file_copy_remote_md5(self, filename): return self.fs.checksum(filename) def _get_interfaces(self): eth_ifaces = EthPortTable(self.native) eth_ifaces.get() loop_ifaces = LoopbackTable(self.native) loop_ifaces.get() ifaces = eth_ifaces.keys() ifaces.extend(loop_ifaces.keys()) return ifaces def _image_booted(self, image_name, **vendor_specifics): raise NotImplementedError def _uptime_components(self, uptime_full_string): match_days = re.search(r"(\d+) days?", uptime_full_string) match_hours = re.search(r"(\d+) hours?", uptime_full_string) match_minutes = re.search(r"(\d+) minutes?", uptime_full_string) match_seconds = re.search(r"(\d+) seconds?", uptime_full_string) days = int(match_days.group(1)) if match_days else 0 hours = int(match_hours.group(1)) if match_hours else 0 minutes = int(match_minutes.group(1)) if match_minutes else 0 seconds = int(match_seconds.group(1)) if match_seconds else 0 return days, hours, minutes, seconds def _uptime_to_seconds(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components( uptime_full_string) seconds += days * 24 * 60 * 60 seconds += hours * 60 * 60 seconds += minutes * 60 return seconds def _uptime_to_string(self, uptime_full_string): days, hours, minutes, seconds = self._uptime_components( uptime_full_string) return "%02d:%02d:%02d:%02d" % (days, hours, minutes, seconds) def _wait_for_device_reboot(self, timeout=3600): start = time.time() while time.time() - start < timeout: try: self.open() return except: # noqa E722 # nosec pass raise RebootTimeoutError(hostname=self.hostname, wait_time=timeout) def backup_running_config(self, filename): with open(filename, "w") as f: f.write(self.running_config) @property def boot_options(self): return self.os_version def checkpoint(self, filename): self.save(filename) def close(self): if self.connected: self.native.close() def config(self, commands, format="set"): """Send configuration commands to a device. Args: commands (str, list): String with single command, or list with multiple commands. Raises: ConfigLoadError: Issue with loading the command. CommandError: Issue with the command provided, if its a single command, passed in as a string. CommandListError: Issue with a command in the list provided. """ if isinstance(commands, str): try: self.cu.load(commands, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandError(commands, e.message) else: try: for command in commands: self.cu.load(command, format=format) self.cu.commit() except ConfigLoadError as e: raise CommandListError(commands, command, e.message) def config_list(self, commands, format="set"): """Send configuration commands in list format to a device. DEPRECATED - Use the `config` method. Args: commands (list): List with multiple commands. """ warnings.warn("config_list() is deprecated; use config().", DeprecationWarning) self.config(commands, format=format) @property def connected(self): return self.native.connected @property def uptime(self): try: native_uptime_string = self.native.facts["RE0"]["up_time"] except (AttributeError, TypeError): native_uptime_string = None if self._uptime is None: if native_uptime_string is not None: self._uptime = self._uptime_to_seconds(native_uptime_string) return self._uptime @property def uptime_string(self): try: native_uptime_string = self.native.facts["RE0"]["up_time"] except (AttributeError, TypeError): native_uptime_string = None if self._uptime_string is None: self._uptime_string = self._uptime_to_string(native_uptime_string) return self._uptime_string @property def hostname(self): if self._hostname is None: self._hostname = self.native.facts.get("hostname") return self._hostname @property def interfaces(self): if self._interfaces is None: self._interfaces = self._get_interfaces() return self._interfaces @property def fqdn(self): if self._fqdn is None: self._fqdn = self.native.facts.get("fqdn") return self._fqdn @property def model(self): if self._model is None: self._model = self.native.facts.get("model") return self._model @property def os_version(self): if self._os_version is None: self._os_version = self.native.facts.get("version") return self._os_version @property def serial_number(self): if self._serial_number is None: self._serial_number = self.native.facts.get("serialnumber") return self._serial_number def file_copy(self, src, dest=None, **kwargs): if not self.file_copy_remote_exists(src, dest, **kwargs): if dest is None: dest = os.path.basename(src) with SCP(self.native) as scp: scp.put(src, remote_path=dest) if not self.file_copy_remote_exists(src, dest, **kwargs): raise FileTransferError( message= "Attempted file copy, but could not validate file existed after transfer" ) # TODO: Make this an internal method since exposing file_copy should be sufficient def file_copy_remote_exists(self, src, dest=None, **kwargs): if dest is None: dest = os.path.basename(src) local_hash = self._file_copy_local_md5(src) remote_hash = self._file_copy_remote_md5(dest) if local_hash is not None and local_hash == remote_hash: return True return False def install_os(self, image_name, **vendor_specifics): raise NotImplementedError def open(self): if not self.connected: self.native.open() def reboot(self, timer=0, **kwargs): """ Reload the controller or controller pair. Args: timer (int, optional): The time to wait before reloading. Defaults to 0. Example: >>> device = JunosDevice(**connection_args) >>> device.reboot() >>> """ if kwargs.get("confirm"): warnings.warn("Passing 'confirm' to reboot method is deprecated.", DeprecationWarning) self.sw = JunosNativeSW(self.native) self.sw.reboot(in_min=timer) def rollback(self, filename): self.native.timeout = 60 temp_file = NamedTemporaryFile() with SCP(self.native) as scp: scp.get(filename, local_path=temp_file.name) self.cu.load(path=temp_file.name, format="text", overwrite=True) self.cu.commit() temp_file.close() self.native.timeout = 30 @property def running_config(self): return self.show("show config") def save(self, filename=None): if filename is None: self.cu.commit() return temp_file = NamedTemporaryFile() temp_file.write(self.show("show config")) temp_file.flush() with SCP(self.native) as scp: scp.put(temp_file.name, remote_path=filename) temp_file.close() return True def set_boot_options(self, sys): raise NotImplementedError def show(self, commands): """Send configuration commands to a device. Args: commands (str, list): String with single command, or list with multiple commands. Raises: CommandError: Issue with the command provided. CommandListError: Issue with a command in the list provided. """ original_commands_is_str = isinstance(commands, str) if original_commands_is_str: commands = [commands] responses = [] for command in commands: if not command.startswith("show"): if original_commands_is_str: raise CommandError( command, 'Juniper "show" commands must begin with "show".') raise CommandListError( commands, command, 'Juniper "show" commands must begin with "show".') response = self.native.cli(command, warning=False) responses.append(response) if original_commands_is_str: return responses[0] return responses def show_list(self, commands, raw_text=True): """Send show commands in list format to a device. DEPRECATED - Use the `show` method. Args: commands (list): List with multiple commands. """ warnings.warn("show_list() is deprecated; use show().", DeprecationWarning) return self.show(commands) @property def startup_config(self): return self.show("show config")