def setUp(self):
        """ Prepare the mock objects for use with the tests
        """
        self.session = AttrDict()
        self.context = AttrDict({
            'default_cred_name': 'default',
            'credentials': Credentials({
                'default': {'username': '******', 'password': '******'},
                'mycred': {'username': '******', 'password': '******'},
                'enable': {'password': '******'},
            })
        })

        class MockSpawn:
            pass

        def mock_sendline(*args, **kwargs):
            print("Sendline called with: %s %s" % (args, kwargs))

        self.spawn = MockSpawn()
        self.spawn.spawn_command = 'ssh -l cisco@router'
        self.spawn.last_sent = 'ssh -l cisco@router'
        self.spawn.sendline = Mock(side_effect=mock_sendline)
        self.spawn.match = AttrDict()
        self.spawn.match.match_output = ""
        self.spawn.settings = Mock()
 def test_add_to_testbed(self):
     testbed = AttrDict(servers=AttrDict())
     with FileServer(protocol='ftp',
                     subnet='127.0.0.1/32',
                     testbed=testbed,
                     name='myserver') as fs:
         self.assertEqual(testbed.servers.myserver, fs)
Ejemplo n.º 3
0
    def setUp(self):
        """ Prepare the mock objects for use with the tests
        """
        self.session = AttrDict()
        self.context = AttrDict({
            'username': '******',
            'tacacs_password': '******',
            'enable_password': "******",
            'line_password': "******"
        })

        class MockSpawn:
            pass

        def mock_sendline(*args, **kwargs):
            print("Sendline called with: %s %s" % (args, kwargs))

        self.spawn = MockSpawn()
        self.spawn.buffer = ''
        self.spawn.spawn_command = 'ssh -l cisco@router'
        self.spawn.last_sent = 'ssh -l cisco@router'
        self.spawn.sendline = Mock(side_effect=mock_sendline)
        self.spawn.match = AttrDict()
        self.spawn.match.match_output = ""
        self.spawn.settings = Mock()
        self.spawn.settings.PASSWORD_ATTEMPTS = 3
Ejemplo n.º 4
0
    def load_netbox(self, steps):
        with steps.start("Loading Devices and VLANs from Netbox."):
            from get_from_netbox import devices, vlans

            netbox = AttrDict()
            netbox.devices = devices
            netbox.vlans = vlans
            self.parent.parameters.update(netbox=netbox)
Ejemplo n.º 5
0
    def __init__(self):
        '''Built-in __init__

        Initializes GenieTelemetry object with default values required for the
        parser.
        '''

        # collect environment information
        # -------------------------------
        self.env = AttrDict(argv=' '.join(sys.argv),
                            prefix=sys.prefix,
                            user=getpass.getuser(),
                            host=platform.node())

        # enable double ctrl-c SIGINT handler
        # -----------------------------------
        sig_handlers.enable_double_ctrl_c()

        # create command-line argv parser
        # -------------------------------
        self.parser = Parser()
        self.manager = None
        self.liveview = None

        self.stream_logger = StreamToLogger()
        sys.stdout = self.stream_logger
Ejemplo n.º 6
0
    def _parse(raw_cli_output, cmd, nos):
        # Boilerplate code to get the parser functional
        # tb = Testbed()
        device = Device("new_device", os=nos)

        device.custom.setdefault("abstraction", {})["order"] = ["os"]
        device.cli = AttrDict({"execute": None})

        # User input checking of the command provided. Does the command have a Genie parser?
        try:
            get_parser(cmd, device)
        except Exception as e:
            raise AnsibleFilterError(
                "genie_parse: {0} - Available parsers: {1}".format(
                    to_native(e),
                    "https://pubhub.devnetcloud.com/media/pyats-packages/docs/genie/genie_libs/#/parsers"
                ))

        try:
            parsed_output = device.parse(cmd, output=raw_cli_output)
            return parsed_output
        except Exception as e:
            raise AnsibleFilterError(
                "genie_parse: {0} - Failed to parse command output.".format(
                    to_native(e)))
Ejemplo n.º 7
0
    def __enter__(self):

        # Start server, usually by spawning a process and get new info
        info = self.start_server()
        recursive_update(self.server_info, info)

        # Verify server is successfully running using a client
        try:
            self.verify_server()
        except Exception as e:
            self.stop_server()
            raise OSError('Failed to verify %s' % str(type(self))) from e

        # Log address of server
        address = self.server_info.get('address', '0.0.0.0')
        port = self.server_info.get('port')
        if port:
            address += ':%s' % port
        logger.info('%s File Server started on %s' %
                    (self.protocol.upper(), address))

        # Update testbed with new server info
        if self.testbed is not None and self.name:
            recursive_update(
                self.testbed.servers.setdefault(self.name, AttrDict()),
                self.server_info)

        return self.server_info
Ejemplo n.º 8
0
    def genie_parser(self, cli_output, command, os):
        if not PY3:
            raise AnsibleFilterError("Genie requires Python 3")

        if not HAS_GENIE:
            raise AnsibleFilterError(
                "Genie not found. Run 'pip install genie'")

        if not HAS_PYATS:
            raise AnsibleFilterError(
                "pyATS not found. Run 'pip install pyats'")

        device = Device("new_device", os=os)

        device.custom.setdefault("abstraction", {})["order"] = ["os"]
        device.cli = AttrDict({"execute": None})

        try:
            get_parser(command, device)
        except Exception as e:
            raise AnsibleFilterError(
                "Unable to find parser for command '{0}' ({1})".format(
                    command, e))

        try:
            parsed_output = device.parse(command, output=cli_output)
        except Exception as e:
            raise AnsibleFilterError(
                "Unable to parse output for command '{0}' ({1})".format(
                    command, e))

        if parsed_output:
            return parsed_output
        else:
            return None
Ejemplo n.º 9
0
    def store_structure(device, feature):

        # get feature and attributes
        [(ft, attr)] = feature.items()
        log.info(
            banner("Learning '{n}' feature with "
                   "attribues {a} on device {d}".format(n=ft, a=attr,
                                                        d=device)))

        # perform lookup per device
        lib = Lookup.from_device(device)

        # attach ops and conf
        lib.conf = getattr(lib, 'conf', conf)
        lib.ops = getattr(lib, 'ops', ops)

        # create the ops/conf instance
        try:
            obj = attrgetter(ft)(lib)
        except Exception:
            raise AttributeError('Cannot load %s for '
                                 'device %s.' % (ft, device.name))
        # conf learn_config
        if issubclass(obj, ConfBase):
            ret = obj.learn_config(device=device, attributes=attr)
            ret = _to_dict(ret[0])
            # delete the non-used objects for pcall to retrun
            ret.pop('__testbed__')
            ret.pop('devices')
            ret.pop('interfaces')
            remove_parent_from_conf_dict(ret['device_attr'][device.name])

        elif issubclass(obj, OpsBase):
            ret = obj(device, attributes=attr)
            ret.learn()
            temp = AttrDict()
            temp.info = getattr(ret, 'info', {})
            ret = temp

        ret_dict = {}

        ret_dict.setdefault('lts', {}).\
            setdefault(ft, {}).setdefault(device.name, ret)

        # return the dictionary
        return ret_dict
 def test_fu_from_device_protocol(self):
     # Instantiate a filetransferutils instance for each os and protocol
     for os_ in ['ios', 'iosxe', 'iosxr', 'nxos']:
         device = AttrDict(os=os_)
         for proto in ['ftp', 'tftp', 'scp', 'sftp', 'http']:
             fu = FileUtils.from_device(device, protocol=proto)
             self.assertIn(
                 'genie.libs.filetransferutils.plugins.{os_}.{proto}.fileutils.FileUtils'
                 .format(os_=os_, proto=proto),
                 str(fu.__class__))
             self.assertEqual(fu.protocol, proto)
             self.assertEqual(fu.os, os_)
Ejemplo n.º 11
0
 def _check_commands_against_pyats(self):
     network_os = self._task.args.get('network_os') or self._network_os
     self._pyats_device = Device("uut", os=network_os)
     self._pyats_device.custom.setdefault("abstraction",
                                          {})["order"] = ["os"]
     self._pyats_device.cli = AttrDict({"execute": None})
     for command in self._commands:
         try:
             get_parser(command['command'], self._pyats_device)
         except Exception:  # pylint: disable=W0703
             self._errors.append("PYATS: Unable to find parser for command "
                                 "'{}' for {}".format(
                                     command['command'], network_os))
     self._check_for_errors()
Ejemplo n.º 12
0
def _ixia_add_on(self, objects, device):

    # disconnecting the device for ixia, incase user didint put subsection datafile
    if device.type == 'tgn' and device.is_connected():
        device.type = 'ixia'
        device.disconnect()

    # transforming tgn input in testbed to hltapi
    device.connections['hltapi'] = AttrDict({
        'protocol':
        'hltapi',
        'ip':
        device.connections.tgn.ixia_chassis_ip,
        'tcl_server':
        device.connections.tgn.ixia_chassis_ip,
        'ixnetwork_tcl_server':
        device.connections.tgn.ixnetwork_api_server_ip + ':' +
        str(device.connections.tgn.ixnetwork_tcl_port),
        'ixia_port_list':
        device.connections.tgn.ixia_port_list
    })

    # saving the ixia saved variables (that is different than normal saved variables)
    # into the objects that would be the input to the plugin
    objects.setdefault('ixiaObjs', {})
    objects['ixiaObjs'].setdefault('ixiaNet', {})
    objects['ixiaObjs'].setdefault('ixiaNetSelf', {})
    objects['ixiaObjs'].setdefault('ixiaNetStop', {})

    # if an ixiaNet object was provided from previous ixia plugin calls it is stored
    # they should be passed into the plugin as input
    if 'save_variable_name' in self.parameters and 'ixiaNet' in self.parameters[
            'save_variable_name']:
        objects['ixiaObjs']['ixiaNet'].update(
            self.parameters['save_variable_name']['ixiaNet'])

    if 'save_variable_name' in self.parameters and 'ixiaNetSelf' in self.parameters[
            'save_variable_name']:
        objects['ixiaObjs']['ixiaNetSelf'].update(
            self.parameters['save_variable_name']['ixiaNetSelf'])

    if 'save_variable_name' in self.parameters and 'ixiaNetStop' in self.parameters[
            'save_variable_name']:
        objects['ixiaObjs']['ixiaNetStop'].update(
            self.parameters['save_variable_name']['ixiaNetStop'])

    return objects
Ejemplo n.º 13
0
def get_structured_data_genie(raw_output: str, platform: str,
                              command: str) -> Union[str, Dict[str, Any]]:
    if not sys.version_info >= (3, 4):
        raise ValueError("Genie requires Python >= 3.4")

    if not GENIE_INSTALLED:
        msg = (
            "\nGenie and PyATS are not installed. Please PIP install both Genie and PyATS:\n"
            "pip install genie\npip install pyats\n")
        raise ValueError(msg)

    if "cisco" not in platform:
        return raw_output

    genie_device_mapper = {
        "cisco_ios": "ios",
        "cisco_xe": "iosxe",
        "cisco_xr": "iosxr",
        "cisco_nxos": "nxos",
        "cisco_asa": "asa",
    }

    os = None
    # platform might be _ssh, _telnet, _serial strip that off
    if platform.count("_") > 1:
        base_list = platform.split("_")[:-1]
        base_platform = "_".join(base_list)
    else:
        base_platform = platform

    os = genie_device_mapper.get(base_platform)
    if os is None:
        return raw_output

    # Genie specific construct for doing parsing (based on Genie in Ansible)
    device = Device("new_device", os=os)
    device.custom.setdefault("abstraction", {})
    device.custom["abstraction"]["order"] = ["os"]
    device.cli = AttrDict({"execute": None})
    try:
        # Test whether there is a parser for given command (return Exception if fails)
        get_parser(command, device)
        parsed_output: Dict[str, Any] = device.parse(command,
                                                     output=raw_output)
        return parsed_output
    except Exception:
        return raw_output
Ejemplo n.º 14
0
    def test_pass_processor(self):
        [d.connect() for d in testbed.devices.values()]
        sys.argv = ['easypy', '--genietelemetry', config_file2]
        with self.assertLogs('', level='INFO') as cm:
            self.assertTrue(section.result)
            self.assertIsNone(section.message)
            # processors.runtime = Mock(side_effect=runtime)
            with patch.object(processors, 'runtime',
                              new_callable=PropertyMock) as mock_runtime:
                mock_runtime.testbed = testbed
                mock_runtime.runinfo = AttrDict()
                mock_runtime.runinfo.runinfo_dir = runinfo_dir
                processors.genie_telemetry_processor(section)

            output = '\n'.join(cm.output)
            msg = "failed to load abstration on device P1 for plugin mockplugin"
            self.assertFalse(msg in output)
            self.assertTrue(section.result)
            self.assertIsNone(section.message)
    def parse(self, *_args, **_kwargs):
        """Std entry point for a cli_parse parse execution

        :return: Errors or parsed text as structured data
        :rtype: dict

        :example:

        The parse function of a parser should return a dict:
        {"errors": [a list of errors]}
        or
        {"parsed": obj}
        """
        errors = self._check_reqs()
        errors.extend(self._check_vars())
        if errors:
            return {"errors": errors}

        command = self._task_args.get("parser").get("command")
        network_os = (
            self._task_args.get("parser").get("os")
            or self._transform_ansible_network_os()
        )
        cli_output = self._task_args.get("text")

        device = Device("new_device", os=network_os)
        device.custom.setdefault("abstraction", {})["order"] = ["os"]
        device.cli = AttrDict({"execute": None})

        try:
            parsed = device.parse(command, output=cli_output)
        except Exception as exc:
            msg = "The pyats library return an error for '{cmd}' for '{os}'. Error: {err}."
            return {
                "errors": [
                    (
                        msg.format(
                            cmd=command, os=network_os, err=to_native(exc)
                        )
                    )
                ]
            }
        return {"parsed": parsed}
Ejemplo n.º 16
0
    def _parse_generic_tabular(cli_output, os, headers, key_index):
        # Boilerplate code to get the parser functional
        tb = Testbed()
        device = Device("new_device", os=os)

        device.custom.setdefault("abstraction", {})["order"] = ["os"]
        device.cli = AttrDict({"execute": None})

        # Do the parsing
        # result = parsergen.oper_fill_tabular(device_output=cli_output, device_os=nos, header_
        # fields=headers, index=[key])
        result = parsergen.oper_fill_tabular(device_output=cli_output,
                                             device_os=os,
                                             header_fields=headers,
                                             index=key_index)

        # Structured data, but it has a blank entry because of the first line of the output
        # being blank under the headers.
        parsed_output = result.entries

        return parsed_output
Ejemplo n.º 17
0
class test_filetransferutils(unittest.TestCase):
    # Instantiate tesbed and device objects
    tb = Testbed(name='myTestbed')
    device = Device(testbed=tb, name='aDevice', os='junos')

    # Instantiate a filetransferutils instance for Junos device
    fu_device = FileUtils.from_device(device)

    # Add testbed servers for authentication
    device.testbed.servers = AttrDict(server_name=dict(username="******",
                                                       password="******",
                                                       address='1.1.1.1'), )

    # Mock device output
    raw1 = '''
            file copy golden_config ftp://[email protected]:/test/ 
            Password for [email protected]:
            ftp://[email protected]:/test/golden_config     100% of 3040  B   11 MBps

    '''

    outputs = {}
    outputs['file copy golden_config ftp://[email protected]:/test/']\
         = raw1

    def mapper(self, key, timeout=None, reply=None, prompt_recovery=False):
        return self.outputs[key]

    def test_copyfile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        # Call copyfiles
        self.fu_device.copyfile(source='golden_config',
                                destination='ftp://1.1.1.1:/test/',
                                timeout_seconds='300',
                                device=self.device)
Ejemplo n.º 18
0
def pyats_parser(cli_output, command, os):
    if not PY3:
        raise AnsibleFilterError("Genie requires Python 3")

    if GENIE_IMPORT_ERROR:
        raise_from(
            AnsibleError('genie must be installed to use this plugin'),
            GENIE_IMPORT_ERROR)

    if PYATS_IMPORT_ERROR:
        raise_from(
            AnsibleError('pyats must be installed to use this plugin'),
            PYATS_IMPORT_ERROR)

    # Translate from ansible_network_os values to pyATS
    if os in ansible_os_map.keys():
        os = ansible_os_map[os]

    device = Device("uut", os=os)

    device.custom.setdefault("abstraction", {})["order"] = ["os"]
    device.cli = AttrDict({"execute": None})

    try:
        get_parser(command, device)
    except Exception as e:
        raise AnsibleFilterError("Unable to find parser for command '{0}' ({1})".format(command, e))

    try:
        parsed_output = device.parse(command, output=cli_output)
    except Exception as e:
        raise AnsibleFilterError("Unable to parse output for command '{0}' ({1})".format(command, e))

    if parsed_output:
        return parsed_output
    else:
        return None
Ejemplo n.º 19
0
    def load_netbox(self, testbed, steps):
        # testbed = self.parameters["testbed"]
        netbox_token = os.getenv("NETBOX_TOKEN")
        netbox_url = os.getenv("NETBOX_URL")

        site_name = os.getenv("NETBOX_SITE")
        tenant_name = os.getenv("NETBOX_TENANT")

        netbox = pynetbox.api(netbox_url, token=netbox_token)

        tenant = netbox.tenancy.tenants.get(name=tenant_name)
        mgmt_tenant = netbox.tenancy.tenants.get(name="Management")
        site = netbox.dcim.sites.get(name=site_name)

        for device in testbed.devices:
            with steps.start(
                    "Pulling Device and Interface Info from Netbox.") as step:
                testbed.devices[device].netbox = AttrDict()
                testbed.devices[
                    device].netbox.device = netbox.dcim.devices.get(
                        site_id=site.id, tenant_id=tenant.id, name=device)
                if not testbed.devices[device].netbox.device is None:
                    testbed.devices[
                        device].netbox.device.interfaces = netbox.dcim.interfaces.filter(
                            device_id=testbed.devices[device].netbox.device.id)
                    if (not testbed.devices[device].netbox.device.interfaces is
                            None):
                        for interface in testbed.devices[
                                device].netbox.device.interfaces:
                            interface.ip_addresses = netbox.ipam.ip_addresses.filter(
                                interface_id=interface.id)
                            for ip_address in interface.ip_addresses:
                                ip_address.ip = ipaddress.ip_address(
                                    ip_address.address.split("/")[0])
                                ip_address.network = ipaddress.ip_network(
                                    ip_address.address, strict=False)
Ejemplo n.º 20
0
def find_plugins():
    plugin_path = os.path.dirname(unicon.plugins.__file__)
    plugin_list = []
    for subdir, dirs, files in os.walk(plugin_path):
        for file in files:
            if file == '__init__.py':
                with open(os.path.join(subdir, file), 'rb') as f:
                    content_length = len(f.read().strip())
                if content_length:
                    plugin = os.path.relpath(subdir, start=plugin_path)
                    p = plugin.split('/')
                    plugin_attributes = AttrDict()
                    if len(p):
                        plugin_attributes.os = p[0]
                    if len(p) > 1:
                        plugin_attributes.series = p[1]
                    else:
                        plugin_attributes.series = None
                    if len(p) > 2:
                        plugin_attributes.model = p[2]
                    else:
                        plugin_attributes.model = None
                    plugin_list.append(plugin_attributes)
    return plugin_list
class test_filetransferutils(unittest.TestCase):
    # Instantiate tesbed and device objects
    tb = Testbed(name='myTestbed')
    device = Device(testbed=tb, name='aDevice', os='iosxe')

    # Instantiate a filetransferutils instance for IOSXE device
    fu_device = FileUtils.from_device(device)

    # Add testbed servers for authentication
    device.testbed.servers = AttrDict(
        server_name = dict(
            username="******", password="******", address='1.1.1.1'),
    )

    dir_output = ['flash:/nvram_config', 'flash:/.rollback_timer',
        'flash:/memleak.tcl', 'flash:/bootloader_evt_handle.log',
        'flash:/ISSUCleanGolden', 'flash:/gs_script', 'flash:/.prst_sync',
        'flash:/nvram_config_bkup', 'flash:/tech_support',
        'flash:/dc_profile_dir',
        'flash:/RestoreTue_Mar_20_12_19_11_2018-Mar-20-11-20-09.900-0',
        'flash:/vlan.dat', 'flash:/core', 'flash:/tools', 'flash:/CRDU',
        'flash:/.dbpersist',
        'flash:/RestoreTue_Mar_20_12_13_39_2018-Mar-20-11-14-38.106-0',
        'flash:/iox', 'flash:/onep', 'flash:/boothelper.log',
        'flash:/stby-vlan.dat', 'flash:/.installer']

    # Mock device output
    raw1 = '''
        copy flash:/memleak.tcl ftp://1.1.1.1//auto/tftp-ssr/memleak.tcl
        Address or name of remote host [1.1.1.1]?
        Destination filename [/auto/tftp-ssr/memleak.tcl]?
        !!
        104260 bytes copied in 0.396 secs (263283 bytes/sec)
    '''

    raw2 = '''
        Directory of flash:/

        69698  drwx             4096  Mar 20 2018 10:25:11 +00:00  .installer
        69720  -rw-          2097152  Mar 20 2018 13:09:24 +00:00  nvram_config
        69700  -rw-            90761  Mar 20 2018 10:25:27 +00:00  bootloader_evt_handle.log
        69701  drwx             4096   Feb 1 2018 13:44:32 +00:00  core
        15489  drwx             4096  Mar 20 2018 10:31:08 +00:00  .prst_sync
        30977  drwx             4096   May 2 2016 07:58:53 +00:00  .rollback_timer
        38722  drwx             4096  Mar 20 2018 10:25:43 +00:00  dc_profile_dir
        69699  -rw-               76  Mar 20 2018 10:25:46 +00:00  boothelper.log
        69705  -rw-           104260  Mar 20 2018 10:26:01 +00:00  memleak.tcl
        69706  drwx             4096   May 2 2016 08:11:23 +00:00  onep
        69714  drwx             4096  Aug 13 2016 08:55:12 +00:00  iox
        69734  -rw-             3496  Mar 11 2018 17:40:26 +00:00  vlan.dat
        69708  -rw-        617329255  Sep 27 2017 09:11:39 +00:00  ISSUCleanGolden
        69709  drwx             4096   Aug 3 2016 08:07:47 +00:00  gs_script
        69712  drwx             4096  Mar 19 2017 09:26:23 +00:00  tools
        69719  drwx             4096  Feb 12 2018 11:20:01 +00:00  .dbpersist
        69703  -rw-          2097152  Mar 20 2018 13:09:25 +00:00  nvram_config_bkup
        69729  -rw-             3496  Feb 12 2018 12:51:01 +00:00  stby-vlan.dat
        69735  -rw-            27145  Mar 20 2018 11:14:45 +00:00  RestoreTue_Mar_20_12_13_39_2018-Mar-20-11-14-38.106-0
        69721  drwx             4096  Sep 25 2017 07:59:54 +00:00  CRDU
        69727  drwx             4096  Oct 23 2017 13:40:11 +00:00  tech_support
        69736  -rw-            27145  Mar 20 2018 11:20:16 +00:00  RestoreTue_Mar_20_12_19_11_2018-Mar-20-11-20-09.900-0

        1621966848 bytes total (906104832 bytes free)
    '''

    raw3 ='''
        delete flash:memleak.tcl
        Delete filename [memleak.tcl]?
        Delete flash:/memleak.tcl? [confirm]
    '''

    raw4 = '''
        rename flash:memleak.tcl new_file.tcl
        Destination filename [new_file.tcl]?
    '''

    raw5 = '''
        show clock | redirect ftp://1.1.1.1//auto/tftp-ssr/show_clock
        Writing /auto/tftp-ssr/show_clock
    '''

    raw6 = {'futlinux.check_file.return_value': '',
      'futlinux.deletefile.return_value': ''}

    raw7 = '''
         copy running-config tftp://10.1.7.250//auto/tftp-ssr/test_config.py
        Address or name of remote host [10.1.7.250]?
        Destination filename [/auto/tftp-ssr/test_config.py]?
        !!
        27092 bytes copied in 6.764 secs (4005 bytes/sec)
    '''

    outputs = {}
    outputs['copy flash:/memleak.tcl '
            'ftp://*****:*****@1.1.1.1//auto/tftp-ssr/memleak.tcl']\
            = raw1
    outputs['dir'] = raw2
    outputs['delete flash:memleak.tcl'] = raw3
    outputs['rename flash:memleak.tcl new_file.tcl'] = raw4
    outputs['show clock | redirect ftp://1.1.1.1//auto/tftp-ssr/show_clock'] = \
      raw5
    outputs['copy running-config tftp://10.1.7.250//auto/tftp-ssr/test_config.py'] = \
      raw7

    def mapper(self, key, timeout=None, reply= None, prompt_recovery=False, error_pattern=None):
        return self.outputs[key]

    def test_copyfile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        # Call copyfiles
        self.fu_device.copyfile(source='flash:/memleak.tcl',
            destination='ftp://1.1.1.1//auto/tftp-ssr/memleak.tcl',
            timeout_seconds='300', device=self.device)

    def test_dir(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        directory_output = self.fu_device.dir(target='flash:',
            timeout_seconds=300, device=self.device)

        self.assertEqual(sorted(directory_output), sorted(self.dir_output))

    def test_stat(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        file_details = self.fu_device.stat(target='flash:memleak.tcl',
          timeout_seconds=300, device=self.device)

        self.assertEqual(file_details['last_modified_date'],
          'Mar 20 2018 10:26:01 +00:00')
        self.assertEqual(file_details['permissions'], '-rw-')
        self.assertEqual(file_details['index'], '69705')
        self.assertEqual(file_details['size'], '104260')

    def test_deletefile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.deletefile(target='flash:memleak.tcl',
          timeout_seconds=300, device=self.device)

    def test_renamefile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.renamefile(source='flash:memleak.tcl',
          destination='new_file.tcl',
          timeout_seconds=300, device=self.device)

    @patch('genie.libs.filetransferutils.plugins.fileutils.FileUtils.validateserver',
        return_value=raw6)
    def test_validateserver(self, raw6):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.validateserver(
            target='ftp://1.1.1.1//auto/tftp-ssr/show_clock',
            timeout_seconds=300, device=self.device)

    def test_copyconfiguration(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.copyconfiguration(source='running-config',
          destination='tftp://10.1.7.250//auto/tftp-ssr/test_config.py',
          timeout_seconds=300, device=self.device)
Ejemplo n.º 22
0
def save_variable(self,
                  section,
                  save_variable_name,
                  output=None,
                  append=None,
                  append_in_list=None):

    # for pyATS Health Check
    # use section.parent for self.parent
    if not hasattr(self.parent, 'parameters'):
        self.parent = section.parent

    # Save output variable
    self.parameters.setdefault('save_variable_name', {})
    self.parent.parameters.setdefault('save_variable_name',
                                      AttrDict({'testscript': AttrDict({})}))

    save_variable_name_str = save_variable_name

    # if testscript. lets save in a global level
    if 'testscript.' in save_variable_name and \
        save_variable_name != 'testscript.name':

        # using AttrDict to save in parent and to retrieve
        save_variable_name = save_variable_name.replace('testscript.', '')
        saved_vars = self.parent.parameters['save_variable_name']['testscript']
    else:
        saved_vars = self.parameters['save_variable_name']

    if save_variable_name in saved_vars:

        saved_val = saved_vars[save_variable_name]
        if append:
            if output:
                saved_vars.update(
                    {save_variable_name: saved_val + '\n' + output})
                log.info(
                    'Appended the following into the variable {},  {}'.format(
                        save_variable_name_str, str(output)))

        elif append_in_list:
            if isinstance(saved_val, list):
                saved_val.append(output)
                saved_vars.update({save_variable_name: saved_val})
                log.info('Appended {} to list variable {}'.format(
                    str(output), save_variable_name_str))
        else:
            saved_vars.update(
                {save_variable_name: output if output is not None else ''})
            log.info('Saved {} in variable {}'.format(str(output),
                                                      save_variable_name_str))
    else:
        if append_in_list:
            saved_vars.update({save_variable_name: [output]})
            log.info('Saved {} in list variable {}'.format(
                str(output), save_variable_name_str))
        else:
            saved_vars.update(
                {save_variable_name: output if output is not None else ''})
            log.info('Saved {} in variable {}'.format(str(output),
                                                      save_variable_name_str))
Ejemplo n.º 23
0
def main():
    argument_spec = dict(command=dict(type='str', required=True),
                prompt=dict(type='list', required=False),
                answer=dict(type='list', required=False),
                compare=dict(type='dict', required=False),
                sendonly=dict(type='bool', default=False, required=False),
                # newline=dict(type='bool', default=True, required=False),
                # check_all=dict(type='bool', default=False, required=False),
    )
    required_together = [['prompt', 'answer']]
    module = AnsibleModule(argument_spec=argument_spec, required_together=required_together,
                           supports_check_mode=True)

    if not PY3:
        module.fail_json(msg="pyATS/Genie requires Python 3")

    if not HAS_GENIE:
        module.fail_json(msg="Genie not found. Run 'pip install genie'")

    if not HAS_PYATS:
        module.fail_json(msg="pyATS not found. Run 'pip install pyats'")

    if module.check_mode and not module.params['command'].startswith('show'):
        module.fail_json(
            msg='Only show commands are supported when using check_mode, not '
            'executing %s' % module.params['command']
        )

    warnings = list()
    result = {'changed': False, 'warnings': warnings}

    connection = Connection(module._socket_path)

    capabilities = json.loads(connection.get_capabilities())

    if capabilities['device_info']['network_os'] == 'ios':
        genie_os = 'iosxe'
    else:
        genie_os = capabilities['device_info']['network_os']

    compare = module.params.pop('compare')

    response = ''
    try:
        response = connection.get(**module.params)
    except ConnectionError as exc:
        module.fail_json(msg=to_text(exc, errors='surrogate_then_replace'))

    device = Device("uut", os=genie_os)

    device.custom.setdefault("abstraction", {})["order"] = ["os"]
    device.cli = AttrDict({"execute": None})

    try:
        get_parser(module.params['command'], device)
    except Exception as e:
        module.fail_json(msg="Unable to find parser for command '{0}' ({1})".format(module.params['command'], e))

    try:
        parsed_output = device.parse(module.params['command'], output=response)
    except Exception as e:
        module.fail_json(msg="Unable to parse output for command '{0}' ({1})".format(module.params['command'], e))

    # import sys;
    # sys.stdin = open('/dev/tty')
    # import pdb;
    # pdb.set_trace()


    if compare:
        diff = Diff(parsed_output, compare, exclude=get_parser_exclude(module.params['command'], device))
        diff.findDiff()
    else:
        diff = None


    if not module.params['sendonly']:
        try:
            result['json'] = module.from_json(response)
        except ValueError:
            pass

        result.update({
            'stdout': response,
            'structured': parsed_output,
            'diff': "{0}".format(diff),
            'exclude': get_parser_exclude(module.params['command'], device),
        })

    module.exit_json(**result)
Ejemplo n.º 24
0
    def test_passx_processor(self):
        [d.connect() for d in testbed.devices.values()]
        sys.argv = ['easypy', '--genietelemetry', config_file]
        with self.assertLogs('', level='INFO') as cm:
            # processors.runtime = Mock(side_effect=runtime)
            with patch.object(processors, 'runtime',
                              new_callable=PropertyMock) as mock_runtime:
                mock_runtime.testbed = testbed
                mock_runtime.runinfo = AttrDict()
                mock_runtime.runinfo.runinfo_dir = runinfo_dir
                processors.genie_telemetry_processor(section)

            output = '\n'.join(cm.output)
            msg = "failed to load abstration on device P1 for plugin mockplugin"
            self.assertTrue(msg in output)
            self.assertEqual(section.result, Passx)
            self.assertIsNotNone(section.message)
            msg = (
                "'genie.telemetry' caught anomalies: \n"
                "genie.telemetry.tests.scripts.mockplugin\n\tP1\n\t\tpartial")
            self.assertEqual(msg, section.message)

            with patch.object(processors, 'runtime',
                              new_callable=PropertyMock) as mock_runtime:
                mock_runtime.testbed = testbed
                mock_runtime.runinfo = AttrDict()
                mock_runtime.runinfo.runinfo_dir = runinfo_dir
                with self.assertRaises(AEtestPassxSignal) as cm:
                    processors.genie_telemetry_processor(clean_up)
                    self.assertEqual(cm.exception.reason, msg)
                fname = os.path.join(runinfo_dir, 'telemetry.yaml')
                self.assertTrue(os.path.isfile(fname))
                with open(fname, 'r') as tempfile:
                    content = yaml.safe_load(tempfile)

                expected = {
                    'common cleanup': {
                        'genie.telemetry.tests.scripts.mockplugin': {
                            'P1': {
                                'status': 'Partial'
                            }
                        },
                        'Crash Dumps Plugin': {
                            'P1': {
                                'status': 'Ok'
                            }
                        },
                        'Traceback Check Plugin': {
                            'P1': {
                                'status': 'Ok'
                            }
                        }
                    },
                    'MockSection': {
                        'genie.telemetry.tests.scripts.mockplugin': {
                            'P1': {
                                'status': 'Partial'
                            }
                        },
                        'Crash Dumps Plugin': {
                            'P1': {
                                'status': 'Ok'
                            }
                        },
                        'Traceback Check Plugin': {
                            'P1': {
                                'status': 'Ok',
                            }
                        }
                    }
                }
                self.assertEqual(sorted(content.keys()),
                                 sorted(expected.keys()))
                for key, value in expected.items():
                    self.assertTrue(key in content)
                    for plugin, devices in value.items():
                        content_devices = content[key].get(plugin, None)
                        self.assertIsNotNone(content_devices)
                        self.assertEqual(devices['P1']['status'],
                                         content_devices['P1']['status'])
Ejemplo n.º 25
0
 def __init__(self, plugins=None):
     self._plugins = AttrDict()
     self.connections = AttrDict()
     self._loader = ConfigLoader()
     self.plugins = (plugins or PluginManager)()
class test_filetransferutils(unittest.TestCase):
    # Instantiate tesbed and device objects
    tb = Testbed(name='myTestbed')
    device = Device(testbed=tb, name='aDevice', os='nxos')

    # Instantiate a filetransferutils instance for NXOS device
    fu_device = FileUtils.from_device(device)

    # Add testbed servers for authentication
    device.testbed.servers = AttrDict(server_name=dict(username="******",
                                                       password="******",
                                                       address='1.1.1.1'), )

    dir_output = [
        'bootflash:/ISSUCleanGolden.system.gbin',
        'bootflash:/ISSUCleanGolden.cfg', 'bootflash:/platform-sdk.cmd',
        'bootflash:/virt_strg_pool_bf_vdc_1/', 'bootflash:/virtual-instance/',
        'bootflash:/virtual-instance.conf', 'bootflash:/.rpmstore/',
        'bootflash:/.swtam/', 'bootflash:/scripts/'
    ]

    # Mock device output
    raw1 = '''
        copy bootflash:/virtual-instance.conf ftp://10.1.0.213//auto/tftp-ssr/virtual-instance.conf
        Enter username: rcpuser
        Password:
        ***** Transfer of file Completed Successfully *****
        Copy complete.
    '''

    raw2 = '''
        dir
               4096    Jan 25 21:00:53 2017  .rpmstore/
               4096    Jan 25 21:01:08 2017  .swtam/
                390    Jan 25 21:36:20 2017  ISSUCleanGolden.cfg
          752699904    Jan 25 21:36:26 2017  ISSUCleanGolden.system.gbin
                  0    Jan 25 21:35:55 2017  platform-sdk.cmd
               4096    Jan 25 21:01:57 2017  scripts/
               4096    Jan 25 21:02:02 2017  virt_strg_pool_bf_vdc_1/
               4096    Jan 25 21:01:21 2017  virtual-instance/
                 59    Jan 25 21:01:11 2017  virtual-instance.conf

        Usage for bootflash://
         1150812160 bytes used
         2386407424 bytes free
         3537219584 bytes total
    '''

    raw3 = '''
        delete bootflash:new_file.tcl
        Do you want to delete "/new_file.tcl" ? (yes/no/abort)   [y]
    '''

    raw4 = '''
        move bootflash:mem_leak.tcl new_file.tcl
    '''

    raw5 = '''
        show clock > ftp://10.1.7.250//auto/tftp-ssr/show_clock vrf management
        Enter username: rcpuser
        Password:
        ***** Transfer of file Completed Successfully *****
    '''

    raw6 = {
        'futlinux.check_file.return_value': '',
        'futlinux.deletefile.return_value': ''
    }

    raw7 = '''
        copy running-config tftp://10.1.7.250//auto/tftp-ssr/test_config.py vrf management
        Trying to connect to tftp server......
        Connection to Server Established.
        [                         ]         0.50KB[#                        ]         4.50KB[##                       ]         8.50KB[###                      ]        12.50KB                                                                                    TFTP put operation was successful
        Copy complete, now saving to disk (please wait)...
        Copy complete.
    '''
    raw8 = '''
        copy running-config sftp://1.1.1.1//home/virl vrf management
        Enter username: myuser

        The authenticity of host '1.1.1.1 (1.1.1.1)' can't be established.
        ECDSA key fingerprint is SHA256:Q37/fav3nPJT5Y+7IsgST4uN0c2tyToJiDF/gp+wItA.
        Are you sure you want to continue connecting (yes/no)? yes
        Warning: Permanently added '1.1.1.1' (ECDSA) to the list of known hosts.
        Outbound-ReKey for 1.1.1.1:22
        Inbound-ReKey for 1.1.1.1:22
        [email protected]'s password:
        Connected to 1.1.1.1.
        sftp> put  /var/tmp/vsh/R3_nx-running-config  /home/virl
        Uploading /var/tmp/vsh/R3_nx-running-config to /home/virl/R3_nx-running-config
        /var/tmp/vsh/R3_nx-running-config
                                                                                                                                                                                                                                                                                                                                    /var/tmp/vsh/R3_nx-running-config                                                                                                                                                                                                                                                                                                                                                                                                                                                            100%   14KB 355.1KB/s   00:00
    '''
    raw9 = '''
        copy bootflash:/virtual-instance.conf ftp://10.1.0.213//auto/tftp-ssr/virtual-instance.conf
        Enter username: rcpuser
        ftp: connect: No route to host
        ***** Transfer of file aborted, server not connected *****
        Error during copy
        ***** Transfer of file aborted *****

    '''

    outputs = {}
    outputs['copy bootflash:/virtual-instance.conf '
            'ftp://10.1.0.213//auto/tftp-ssr/virtual-instance.conf'] = raw1
    outputs['dir'] = raw2
    outputs['delete bootflash:new_file.tcl'] = raw3
    outputs['move bootflash:mem_leak.tcl new_file.tcl'] = raw4
    outputs[
        'show clock > ftp://1.1.1.1//auto/tftp-ssr/show_clock vrf management'] = raw5
    outputs[
        'copy running-config tftp://10.1.7.250//auto/tftp-ssr/test_config.py vrf management'] = raw7
    outputs[
        'copy running-config sftp://[email protected]//home/virl vrf management'] = raw8
    outputs['copy bootflash:/virtual-instance.conf '
            'ftp://10.1.0.214//auto/tftp-ssr/virtual-instance.conf'] = raw9

    def mapper(self, key, timeout=None, reply=None, prompt_recovery=False):
        return self.outputs[key]

    def is_valid_ip_mapper(self, ip, device=None, vrf=None, cache_ip=None):
        return ip != '2.2.2.2'

    def test_copyfile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        # Call copyfiles
        self.fu_device.copyfile(
            source='bootflash:/virtual-instance.conf',
            destination='ftp://10.1.0.213//auto/tftp-ssr/virtual-instance.conf',
            timeout_seconds='300',
            device=self.device)

    def test_copyfile_exception(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        # Call copyfiles
        with self.assertRaises(SubCommandFailure):
            self.fu_device.copyfile(
                source='bootflash:/virtual-instance.conf',
                destination=
                'ftp://10.1.0.214//auto/tftp-ssr/virtual-instance.conf',
                timeout_seconds='300',
                device=self.device)

    def test_copyfile_sftp(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        # Call copyfiles
        self.fu_device.copyfile(source='running-config',
                                destination='sftp://1.1.1.1//home/virl',
                                vrf='management',
                                device=self.device)

    def test_validate_and_update_url(self):
        self.fu_device.is_valid_ip = Mock()
        self.fu_device.is_valid_ip.side_effect = self.is_valid_ip_mapper
        # set multiple ip for the server
        self.device.testbed.servers.server_name['address'] = [
            '2.2.2.2', '1.1.1.1'
        ]
        not_reachable_url = self.fu_device.validate_and_update_url(
            'sftp://2.2.2.2//home/virl', device=self.device)
        reachable_url = self.fu_device.validate_and_update_url(
            'sftp://1.1.1.1//home/virl', device=self.device)
        servername_url = self.fu_device.validate_and_update_url(
            'sftp://server_name//home/virl', device=self.device)
        self.assertEqual(not_reachable_url, 'sftp://[email protected]//home/virl')
        self.assertEqual(reachable_url, 'sftp://[email protected]//home/virl')
        self.assertEqual(servername_url, 'sftp://[email protected]//home/virl')
        self.device.testbed.servers.server_name['address'] = '1.1.1.1'

    def test_dir(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        directory_output = self.fu_device.dir(target='bootflash:',
                                              timeout_seconds=300,
                                              device=self.device)

        self.assertEqual(sorted(directory_output), sorted(self.dir_output))

    def test_stat(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        file_details = self.fu_device.stat(
            target='bootflash:virtual-instance.conf',
            timeout_seconds=300,
            device=self.device)

        self.assertEqual(file_details['time'], '21:01:11')
        self.assertEqual(file_details['date'], 'Jan 25 2017')
        self.assertEqual(file_details['size'], '59')

    def test_deletefile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.deletefile(target='bootflash:new_file.tcl',
                                  timeout_seconds=300,
                                  device=self.device)

    def test_renamefile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.renamefile(source='bootflash:mem_leak.tcl',
                                  destination='new_file.tcl',
                                  timeout_seconds=300,
                                  device=self.device)

    @patch(
        'genie.libs.filetransferutils.plugins.fileutils.FileUtils.validateserver',
        return_value=raw6)
    def test_validateserver(self, raw6):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.validateserver(
            target='ftp://1.1.1.1//auto/tftp-ssr/show_clock',
            timeout_seconds=300,
            device=self.device)

    def test_copyconfiguration(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.copyconfiguration(
            source='running-config',
            destination='tftp://10.1.7.250//auto/tftp-ssr/test_config.py',
            timeout_seconds=300,
            device=self.device)
class test_filetransferutils(unittest.TestCase):
    # Instantiate tesbed and device objects
    tb = Testbed(name='myTestbed')
    device = Device(testbed=tb, name='aDevice', os='iosxr')

    # Instantiate a filetransferutils instance for IOSXE device
    fu_device = FileUtils.from_device(device)

    # Add testbed servers for authentication
    device.testbed.servers = AttrDict(
        server_name = dict(
            username="******", password="******", address='1.1.1.1'),
    )

    dir_output = ['disk0:/status_file', 'disk0:/clihistory', 'disk0:/cvac',
        'disk0:/core', 'disk0:/envoke_log', 'disk0:/lost+found',
        'disk0:/pnet_cfg.log', 'disk0:/oor_aware_process',
        'disk0:/.python-history', 'disk0:/cvac.log', 'disk0:/nvgen_traces',
        'disk0:/fake_config_2.tcl', 'disk0:/ztp',
        'disk0:/config -> /misc/config', 'disk0:/memleak.tcl']


    # Mock device output
    raw1 = '''
        copy disk0:/memleak.tcl ftp://1.1.1.1//auto/tftp-ssr/memleak.tcl
        Address or name of remote host [1.1.1.1]? 
        Destination filename [/auto/tftp-ssr/memleak.tcl]? 
        !!
        104260 bytes copied in 0.396 secs (263283 bytes/sec)
    '''

    raw2 = '''
        dir

        Directory of /misc/scratch
           32 -rw-rw-rw- 1   824 Mar  7 06:29 cvac.log
           43 -rwxr--r-- 1     0 Mar 22 08:58 fake_config_2.tcl
           41 -rw-r--r-- 1  1985 Mar 12 14:35 status_file
           13 -rw-r--r-- 1  1438 Mar  7 14:26 envoke_log
           16 -rw-r--r-- 1    98 Mar  7 06:34 oor_aware_process
         8178 drwxr-xr-x 2  4096 Mar  7 14:27 memleak.tcl
         8177 drwx---r-x 2  4096 Mar  7 14:27 clihistory
           15 lrwxrwxrwx 1    12 Mar  7 14:26 config -> /misc/config
           12 drwxr-xr-x 2  4096 Mar  7 14:26 core
           14 -rw-r--r-- 1 10429 Mar  7 14:26 pnet_cfg.log
           11 drwx------ 2 16384 Mar  7 14:26 lost+found
         8179 drwxr-xr-x 8  4096 Mar  7 07:01 ztp
           42 -rw------- 1     0 Mar 20 11:08 .python-history
        16354 drwxr-xr-x 2  4096 Mar  7 07:22 nvgen_traces
        16353 drwxrwxrwx 3  4096 Mar  7 14:29 cvac

        1012660 kbytes total (938376 kbytes free)
    '''

    raw3 = '''
        delete disk0:fake_config_2.tcl
        Delete disk0:fake_config_2.tcl[confirm]
    '''

    raw4 = '''
        show clock | redirect ftp://1.1.1.1//auto/tftp-ssr/show_clock
        Writing /auto/tftp-ssr/show_clock 
    '''

    raw5 = {'futlinux.check_file.return_value': '',
        'futlinux.deletefile.return_value': ''}

    raw6 = '''
        copy running-config ftp://10.1.6.242//auto/tftp-ssr/fake_config_2.tcl
        Host name or IP address (control-c to abort): [10.1.6.242;default]?
        Destination username: []?rcpuser
        Destination password: 
        Destination file name (control-c to abort): [/auto/tftp-ssr/fake_config_2.tcl]?
        Building configuration.
        349 lines built in 1 second
        [OK]
    '''

    raw7 =  '''
            sftp running-config [email protected]:/home/virl vrf management
            Thu Oct 10 15:45:18.989 UTC
            Connecting to 172.16.1.250...
            Password: 

            /misc/disk1/running-config
              Overwrite /home/virl/running-config on host 172.16.1.250, continu? [
              yes/no]: yes
              Transferred 11332 Bytes
              11332 bytes copied in 0 sec (251822)bytes/sec
    '''
    outputs = {}
    outputs['copy disk0:/fake_config_2.tcl '
        'ftp://1.1.1.1//auto/tftp-ssr/fake_config_2.tcl'] = raw1
    outputs['dir'] = raw2
    outputs['delete disk0:fake_config.tcl'] = raw3
    outputs['show clock | redirect ftp://1.1.1.1//auto/tftp-ssr/show_clock'] = \
        raw4
    outputs['copy running-config ftp://10.1.6.242//auto/tftp-ssr/fake_config_2.tcl'] = \
        raw6
    outputs['sftp running-config [email protected]:/home/virl'] = raw7
    def mapper(self, key, timeout=None, reply= None, prompt_recovery=False):
        return self.outputs[key]

    def test_copyfile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        # Call copyfiles
        self.fu_device.copyfile(source='disk0:/fake_config_2.tcl',
            destination='ftp://1.1.1.1//auto/tftp-ssr/fake_config_2.tcl',
            timeout_seconds='300', device=self.device)

    def test_copyfile_sftp(self):
        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        # Call copyfiles
        self.fu_device.copyfile(source='running-config',
                                destination='sftp://1.1.1.1//home/virl',
                                device=self.device)

    def test_dir(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        directory_output = self.fu_device.dir(target='disk0:',
            timeout_seconds=300, device=self.device)

        self.assertEqual(sorted(directory_output), sorted(self.dir_output))

    def test_stat(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        file_details = self.fu_device.stat(target='disk0:memleak.tcl',
          timeout_seconds=300, device=self.device)

        self.assertEqual(file_details['index'],
          '8178')
        self.assertEqual(file_details['date'], 'Mar 7 14:27')
        self.assertEqual(file_details['permission'], 'drwxr-xr-x')
        self.assertEqual(file_details['size'], '4096')

    def test_deletefile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.deletefile(target='disk0:fake_config.tcl',
          timeout_seconds=300, device=self.device)

    def test_renamefile(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        with self.assertRaisesRegex(
            NotImplementedError, "The fileutils module genie.libs."
            "filetransferutils.plugins.iosxr.fileutils does not implement "
            "renamefile."):
            self.fu_device.renamefile(source='disk0:fake_config.tcl',
              destination='memleak.tcl',
                timeout_seconds=300, device=self.device)

    @patch('genie.libs.filetransferutils.plugins.fileutils.FileUtils.validateserver',
        return_value=raw5)
    def test_validateserver(self, raw5):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.validateserver(
            target='ftp://1.1.1.1//auto/tftp-ssr/show_clock',
            timeout_seconds=300, device=self.device)

    def test_copyconfiguration(self):

        self.device.execute = Mock()
        self.device.execute.side_effect = self.mapper

        self.fu_device.copyconfiguration(source='running-config',
          destination='ftp://10.1.6.242//auto/tftp-ssr/fake_config_2.tcl',
          timeout_seconds=300, device=self.device)