Example #1
0
File: junos.py Project: bryson/salt
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
Example #2
0
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("+++++++++++++++++++++++++++++++++++++++++++++++++")
Example #3
0
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()
Example #4
0
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 ("+++++++++++++++++++++++++++++++++++++++++++++++++")
Example #5
0
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()
Example #6
0
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()
Example #7
0
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()
Example #8
0
 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)
Example #9
0
    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()
Example #11
0
 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)
Example #12
0
    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
Example #13
0
    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)
Example #14
0
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()
Example #15
0
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()
Example #16
0
    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)
Example #17
0
    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()
Example #20
0
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')
Example #21
0
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")
Example #22
0
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
Example #23
0
 def test_sw_local_sha1(self, mock_built_open):
     package = "test.tgz"
     self.assertEqual(
         SW.local_checksum(package, algorithm="sha1"),
         "da39a3ee5e6b4b0d3255bfef95601890afd80709",
     )
Example #24
0
 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)
Example #25
0
 def test_sw_local_sha1(self, mock_built_open):
     package = 'test.tgz'
     self.assertEqual(SW.local_sha1(package),
                      'da39a3ee5e6b4b0d3255bfef95601890afd80709')
Example #26
0
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")
Example #27
0
 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")
Example #28
0
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')
Example #29
0
 def test_sw_local_sha256(self, mock_built_open):
     package = "test.tgz"
     self.assertEqual(
         SW.local_checksum(package, algorithm="sha256"),
         "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934" "ca495991b7852b855",
     )
Example #30
0
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')
Example #31
0
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")
Example #32
0
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
Example #33
0
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()
Example #35
0
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')
Example #36
0
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()
Example #37
0
 def test_sw_local_sha256(self, mock_built_open):
     package = 'test.tgz'
     self.assertEqual(SW.local_sha256(package),
                      'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934'
                      'ca495991b7852b855')
Example #38
0
 def test_sw_local_md5(self, mock_built_open):
     package = 'test.tgz'
     self.assertEqual(SW.local_md5(package),
                      'd41d8cd98f00b204e9800998ecf8427e')
Example #39
0
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")
Example #40
0
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')
Example #41
0
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')
Example #42
0
 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)
Example #43
0
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')
Example #44
0
 def test_sw_local_md5(self, mock_built_open):
     package = 'test.tgz'
     self.assertEqual(SW.local_md5(package),
                      'd41d8cd98f00b204e9800998ecf8427e')
Example #45
0
 def test_sw_local_sha1(self, mock_built_open):
     package = 'test.tgz'
     self.assertEqual(SW.local_sha1(package),
                      'da39a3ee5e6b4b0d3255bfef95601890afd80709')
Example #46
0
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()
Example #47
0
 def get_sw(self, mock_execute):
     mock_execute.side_effect = self._mock_manager
     return SW(self.dev)
Example #48
0
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
Example #49
0
 def test_sw_local_sha256(self, mock_built_open):
     package = 'test.tgz'
     self.assertEqual(
         SW.local_sha256(package),
         'e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934'
         'ca495991b7852b855')
Example #50
0
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()
Example #52
0
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")