示例#1
0
def golden_recovery(start,
                    device,
                    console_activity_pattern,
                    golden_image=None,
                    break_count=10,
                    timeout=600,
                    recovery_password=None,
                    tftp_boot=None,
                    item=None):
    ''' A method for starting Spawns and handling the device statements during recovery
        Args:
            device ('obj'): Device object
            start ('obj'): Start method under device object
            console_activity_pattern ('str'): Pattern to send the break at
            golden_image ('str'): Image to load the device with
            break_count ('int'): Number of sending break times
            timeout ('int'): Recovery process timeout
            recovery_password ('str'): Device password after recovery
        Returns:
            None
    '''

    break_dialog = BreakBootDialog()
    break_dialog.add_statement(Statement(pattern=console_activity_pattern,
                                         action=sendbrk_handler,
                                         args={'break_count': break_count},
                                         loop_continue=True,
                                         continue_timer=False),
                               pos=0)

    # Set a target for each recovery session
    # so it's easier to distinguish expect debug logs on the console.
    device.instantiate(connection_timeout=timeout)

    # Get device console port information
    last_word_in_start_match = re.match('.*\s(\S+)$', start)
    last_word_in_start = last_word_in_start_match.group(1) \
        if last_word_in_start_match else ""

    # Set target
    target = "{}_{}".format(device.hostname, last_word_in_start)

    spawn = Spawn(start,
                  settings=device.cli.settings,
                  target=target,
                  log=log,
                  logfile=log.handlers[1].logfile)

    if 'system' not in golden_image:
        raise Exception("System image has not been provided in the "
                        "'device_recovery' section of the clean YAML")

    dialog = RommonDialog()
    dialog.dialog.process(spawn,
                          context={
                              'sys': golden_image.get('system'),
                              'password': recovery_password
                          },
                          timeout=timeout)
    spawn.close()
示例#2
0
def device_recovery(start,
                    device,
                    console_activity_pattern,
                    golden_image=None,
                    break_count=10,
                    timeout=600,
                    recovery_password=None,
                    tftp_boot=None,
                    item=None,
                    **kwargs):
    ''' A method for starting Spawns and handling the device statements during recovery
        Args:
            device ('obj'): Device object
            start ('obj'): Start method under device object
            console_activity_pattern ('str'): Pattern to send the break at
            golden_image ('dict'): information to load golden image on the device
            break_count ('int'): Number of sending break times
            timeout ('int'): Recovery process timeout
            recovery_password ('str'): Device password after recovery
        Returns:
            None
    '''

    # Set a target for each recovery session
    # so it's easier to distinguish expect debug logs on the console.
    device.instantiate(connection_timeout=timeout)

    # Get device console port information
    last_word_in_start_match = re.match('.*\s(\S+)$', start)
    last_word_in_start = last_word_in_start_match.group(1) \
        if last_word_in_start_match else ""

    # Set target
    target = "{}_{}".format(device.hostname, last_word_in_start)

    logfile = log.handlers[1].logfile if len(log.handlers) >= 2 else None
    spawn = Spawn(spawn_command=start,
                  settings=device.cli.settings,
                  target=target,
                  log=log,
                  logfile=logfile)

    break_dialog = BreakBootDialog()
    break_dialog.add_statement(Statement(pattern=console_activity_pattern,
                                         action=sendbrk_handler,
                                         args={'break_count': break_count},
                                         loop_continue=True,
                                         continue_timer=False),
                               pos=0)
    break_dialog.dialog.process(spawn, timeout=timeout)

    dialog = RommonDialog()
    dialog.dialog.process(spawn,
                          timeout=timeout,
                          context={
                              'boot_image': golden_image[0],
                              'break_count': break_count,
                              'password': recovery_password
                          })
    spawn.close()
示例#3
0
    def ssh_vty(self, ip, port='22'):
        """Setup ssh connection to the server.

        :param ip: ssh host/ip
        :param port: ssh port
        :return: ssh_line

        """

        from .constants import WebserverConstants
        spawn = Spawn(
            'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no '
            '-l {} -p {} {} \n'.format(WebserverConstants.username, port, ip))
        d1 = Dialog([
            [
                'continue connecting (yes/no)?', 'sendline(yes)', None, True,
                False
            ],
            [
                '(p|P)assword:',
                'sendline({})'.format(WebserverConstants.login_password), None,
                False, False
            ],
        ])
        try:
            d1.process(spawn, timeout=60)
            spawn.sendline()
        except TimeoutError:
            pass

        ssh_line = WebserverLine(spawn, self.sm, 'ssh_ftd')
        return ssh_line
示例#4
0
def tftp_recovery_worker(start, device, console_activity_pattern, tftp_boot=None,
                         break_count=10, timeout=600, recovery_password=None,
                         golden_image=None, item=None):
    ''' A method for starting Spawns and handling the device statements during recovery
        Args:
            device ('obj'): Device object
            start ('obj'): Start method under device object
            console_activity_pattern ('str'): Pattern to send the break at
            tftp_boot ('dict'): Tftp boot information
            break_count ('int'): Number of sending break times
            timeout ('int'): Recovery process timeout
            recovery_password ('str'): Device password after recovery
        Returns:
            None
    '''

    log.info('Set the device in rommon and load the device with tftp boot')
    break_dialog = BreakBootDialog()
    break_dialog.add_statement(Statement(pattern=console_activity_pattern,
                                         action=sendbrk_handler,
                                         args={'break_count':break_count},
                                         loop_continue=True,
                                         continue_timer=False), pos=0)

    # Set a target for each recovery session
    # so it's easier to distinguish expect debug logs on the console.
    device.instantiate(connection_timeout=timeout)

    # Get device console port information
    last_word_in_start_match = re.match('.*\s(\S+)$', start)
    last_word_in_start = last_word_in_start_match.group(1) \
        if last_word_in_start_match else ""

    # Set target
    target = "{}_{}".format(device.hostname, last_word_in_start)

    spawn = Spawn(spawn_command=start,
                  settings=device.cli.settings,
                  target=target,
                  log=log,
                  logfile=log.handlers[1].logfile)

    rommon_dialog = TftpRommonDialog()
    rommon_dialog.hostname_statement(device.hostname)
    rommon_dialog.dialog.process(spawn, timeout=timeout,
                                 context={'device_name': device.name,
                                          'ip': tftp_boot['ip_address'][item],
                                          'password': recovery_password,
                                          'subnet_mask': tftp_boot['subnet_mask'],
                                          'gateway': tftp_boot['gateway'],
                                          'image': tftp_boot['image'],
                                          'tftp_server': tftp_boot['tftp_server'],
                                          'hostname': device.hostname})

    spawn.close()
示例#5
0
    def ssh_cimc(self,
                 ip,
                 port,
                 cimc_username='******',
                 cimc_password='******',
                 timeout=None):
        """This is the method to login to FMC via CIMC Interface.

        :param ip: FMC CIMC IP
        :param port: ssh port for FMC CIMC
        :param cimc_username: ssh username for FMC CIMC
        :param cimc_password: ssh password for FMC CIMC
        :param timeout: timeout for ssh login
        :return: ssh_line

        """

        publish_kick_metric('device.m4.ssh', 1)
        if not timeout:
            timeout = self.default_timeout
        self.spawn_id = Spawn('ssh -o UserKnownHostsFile=/dev/null'
                              ' -o StrictHostKeyChecking=no '
                              '-l {} -p {} {}'.format(cimc_username, port, ip))
        d1 = Dialog([
            [
                'continue connecting (yes/no)?', 'sendline(yes)', None, True,
                False
            ],
            [
                '[Pp]assword:', 'sendline({})'.format(cimc_password), None,
                True, False
            ],
            [self.sm.get_state('mio_state').pattern, None, None, False, False],
        ])
        try:
            d1.process(self.spawn_id, timeout=60)
            self.spawn_id.sendline()
            self.spawn_id.sendline()
        except TimeoutError:
            pass
        ssh_line = self.line_class(self.spawn_id,
                                   self.sm,
                                   'ssh_cimc',
                                   timeout=timeout)

        logger.debug("Done: connection created by ssh {} {}".format(ip, port))
        return ssh_line
示例#6
0
def recovery_worker(start,
                    device,
                    console_activity_pattern,
                    break_count=10,
                    timeout=600,
                    *args,
                    **kwargs):
    """ Starts a Spawn and processes device dialogs during recovery of a device

        Args:
            start (obj): Start method under device object
            device (obj): Device object
            console_activity_pattern (str): Pattern to send the break at
            break_count (int, optional): Number of break commands to send. Defaults to 10.
            timeout (int, optional): Recovery process timeout. Defaults to 600.

        Returns:
            None
    """
    def breakboot(spawn, break_count):
        """ Breaks the booting process on a device

            Args:
                spawn (obj): Spawn connection object
                break_count (int): Number of break commands to send

            Returns:
                None
        """

        log.info("Found the console_activity_pattern! "
                 "Breaking the boot process")

        for _ in range(break_count):
            # '\x03' == <ctrl>+C
            spawn.send("\x03")
            time.sleep(1)

    # Set a target for each recovery session
    # so it's easier to distinguish expect debug logs on the console.
    device.instantiate(connection_timeout=timeout)

    # Get device console port information
    last_word_in_start_match = re.match('.*\s(\S+)$', start)
    last_word_in_start = last_word_in_start_match.group(1) \
        if last_word_in_start_match else ""

    # Set target
    target = "{}_{}".format(device.hostname, last_word_in_start)

    if len(log.handlers) >= 2:
        logfile = log.handlers[1].logfile
    else:
        logfile = None

    spawn = Spawn(spawn_command=start,
                  settings=device.cli.settings,
                  target=target,
                  log=log,
                  logfile=logfile)

    # Stop the device from booting
    break_dialog = BreakBootDialog()
    break_dialog.add_statement(Statement(pattern=console_activity_pattern,
                                         action=breakboot,
                                         args={'break_count': break_count},
                                         loop_continue=True,
                                         continue_timer=False),
                               pos=0)
    break_dialog.dialog.process(spawn, timeout=timeout)

    # Recover the device using the specified method
    if kwargs.get('golden_image'):
        device_recovery(spawn, timeout, *args, **kwargs)
    elif kwargs.get('tftp_boot'):
        tftp_device_recovery(spawn, timeout, device, *args, **kwargs)

    spawn.close()
        # this is first entry hence we need to send login password.
        session.flag = True
        spawn.sendline(loginpw)
    else:
        # if we come here that means it is second entry and here.
        # we need to send the enable password.
        spawn.sendline(enablepw)


# construct the dialog.
# here we see how shorthand notation can make the code look leaner.
d = Dialog([
    [r'enter to continue \.\.\.', 'sendline()', None, True, False],
    [r'username:\s?$', "sendline(admin)", None, True, False],
    [
        r'password:\s?$', send_passwd, {
            'enablepw': 'lablab',
            'loginpw': 'lab'
        }, True, False
    ],
    [disable_prompt, 'sendline(enable)', None, True, False],
    [enable_prompt, None, None, False, False],
])

s = Spawn(router_command)

# at this stage we are anticipating the program to wait for a new line
d.process(s)

s.close()
示例#8
0
class M4(Fmc):
    def __init__(self,
                 hostname='firepower',
                 login_username='******',
                 login_password=KickConsts.DEFAULT_PASSWORD,
                 sudo_password=KickConsts.DEFAULT_PASSWORD,
                 cimc_hostname='',
                 *args,
                 **kwargs):
        """Constructor for FMC m4.

        :param hostname: fmc hostname or fqdn e.g. FS2000-01 or FS2000-01.cisco.com
        :param login_username: user name for login
        :param login_password: password for login
        :param cimc_hostname: host name in prompt in cimc scope mode e.g. C220-FCH1948V1N3
        :return: None

        """

        publish_kick_metric('device.m4.init', 1)

        self.patterns = M4Patterns(hostname=hostname,
                                   login_username=login_username,
                                   login_password=login_password,
                                   sudo_password=sudo_password,
                                   cimc_hostname=cimc_hostname)
        self.sm = M4Statemachine(self.patterns)
        self.line_class = M4Line

        self.set_default_timeout(DEFAULT_TIMEOUT)

    def ssh_cimc(self,
                 ip,
                 port,
                 cimc_username='******',
                 cimc_password='******',
                 timeout=None):
        """This is the method to login to FMC via CIMC Interface.

        :param ip: FMC CIMC IP
        :param port: ssh port for FMC CIMC
        :param cimc_username: ssh username for FMC CIMC
        :param cimc_password: ssh password for FMC CIMC
        :param timeout: timeout for ssh login
        :return: ssh_line

        """

        publish_kick_metric('device.m4.ssh', 1)
        if not timeout:
            timeout = self.default_timeout
        self.spawn_id = Spawn('ssh -o UserKnownHostsFile=/dev/null'
                              ' -o StrictHostKeyChecking=no '
                              '-l {} -p {} {}'.format(cimc_username, port, ip))
        d1 = Dialog([
            [
                'continue connecting (yes/no)?', 'sendline(yes)', None, True,
                False
            ],
            [
                '[Pp]assword:', 'sendline({})'.format(cimc_password), None,
                True, False
            ],
            [self.sm.get_state('mio_state').pattern, None, None, False, False],
        ])
        try:
            d1.process(self.spawn_id, timeout=60)
            self.spawn_id.sendline()
            self.spawn_id.sendline()
        except TimeoutError:
            pass
        ssh_line = self.line_class(self.spawn_id,
                                   self.sm,
                                   'ssh_cimc',
                                   timeout=timeout)

        logger.debug("Done: connection created by ssh {} {}".format(ip, port))
        return ssh_line

    def reboot_cimc(self,
                    ip,
                    port,
                    cimc_username='******',
                    cimc_password='******',
                    retries=10,
                    interval=120):
        """This is the method to reboot cimc

        :param ip: FMC CIMC IP
        :param port: ssh port for FMC CIMC
        :param cimc_username: ssh username for FMC CIMC
        :param cimc_password: ssh password for FMC CIMC
        :param retries: polling attempts to check if CIMC is back
        :param interval: polling interval
        :return: True/False to indicate sucess

        """

        self.ssh_cimc(ip, port, cimc_username, cimc_password)
        self.spawn_id.sendline("top")
        self.spawn_id.sendline("scope cimc")
        d1 = Dialog([
            ['/cimc.*#', 'sendline(reboot)', None, True, False],
            ['Continue?.*', 'sendline(y)', None, False, False],
        ])
        d1.process(self.spawn_id, timeout=60)
        logger.info("Sleeping for 60 secs..")
        time.sleep(60)
        while retries > 0:
            logger.info(
                "Wait for CIMC to be back. Attempt: {}".format(retries))
            try:
                line = self.ssh_cimc(ip, port, cimc_username, cimc_password)
                if line is not None:
                    line.disconnect()
                    break
            except:
                logger.info("CIMC didnt respond")
                time.sleep(interval)
                retries -= 1
        if retries == 0:
            logger.error("CIMC did not come back after reboot")
            return False
        else:
            return True
    def ssh_vty(self,
                ip,
                port,
                username='******',
                password='******',
                timeout=None,
                line_type='ssh',
                rsa_key=None):
        """
        Set up an ssh connection to device's interface.

        This goes into device's ip address, not console.

         :param ip: ip address of terminal server
         :param port: port of device on terminal server
         :param username: usually "admin"
         :param password: usually "Admin123"
         :param timeout: in seconds
         :param line_type: ssh line type
         :param rsa_key: identity file (full path)
         :return: a line object (where users can call execute(), for example)

         """
        publish_kick_metric('device.series3fmc.ssh_vty', 1)
        if not timeout:
            timeout = self.default_timeout

        from .constants import Series3Constants
        Series3Constants.uut_ssh_ip = ip
        Series3Constants.uut_ssh_port = port

        if rsa_key:
            resp = subprocess.getoutput('chmod 400 {}'.format(rsa_key))
            if 'No such file or directory' in resp:
                raise RuntimeError(
                    'The identity file {} you provided does not exist'.format(
                        rsa_key))
            spawn = Spawn(
                'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no '
                '-i {} -l {} -p {} {} \n'.format(rsa_key, username, port, ip))
        else:
            spawn = Spawn(
                'ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no '
                '-l {} -p {} {} \n'.format(username, port, ip))

        d1 = Dialog([
            [
                'continue connecting (yes/no)?', 'sendline(yes)', None, True,
                False
            ],
            [
                '(p|P)assword:', 'sendline({})'.format(password), None, False,
                False
            ],
        ])
        try:
            d1.process(spawn, timeout=timeout)
        # spawn.sendline()
        except TimeoutError:
            pass

        ssh_line = Series3FmcLine(spawn, self.sm, 'ssh_vty', timeout=timeout)

        return ssh_line
示例#10
0
def is_available(host, port, user=DEFAULT_USERNAME, pwd=DEFAULT_PASSWORD,
                 prompt='firepower login:'******'telnet'):
    """Checks whether device is available.

    :param host: Ip of the device/console
    :param port: console port
    :param user: username
    :param pwd: password
    :param prompt: expected prompt
    :param access: type of access: telnet or ssh
    :return: True if device is available, False if it's not

    """

    if user == DEFAULT_USERNAME:
        user = get_username(user)
    if pwd == DEFAULT_PASSWORD:
        pwd = get_password(pwd)

    VALID_PROMPTS.append(prompt)
    if access == 'telnet':
        spawn_id = Spawn('telnet {} {}\n'.format(host, port))
        try:
            spawn_id.expect(
                "Connected to.*Escape character is '\^\]'\..*Username: "******"Connected to.*Escape character is '\^\]'\..*Username: "******"Password: "******"Password OK.*")
        except TimeoutError:
            LOGGER.debug("'Password OK' message did not appear ... continue")
        spawn_id.sendline('')
        try:
            __wait_for_rommon(spawn_id, 900)
        except:
            LOGGER.info("\nFailed to get a valid prompt")
            spawn_id.close()
            return False
        LOGGER.info('%s on port %d is available' % (host, port))
        spawn_id.close()
    elif access == 'ssh':
        try:
            if port is not 22:
                clear_line(host=host, port=port % 100, access='ssh', user=user, pwd=pwd, en_password=pwd)
            spawn_id = Spawn('ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no -l {} -p {} {}'.
                             format(user, port, host))
            d1 = Dialog([
                ['continue connecting (yes/no)?', 'sendline(yes)', None, True, False],
                ['(P|p)assword:', 'sendline({})'.format(pwd), None, False, False],
                ['Connection refused', None, None, False, False],
            ])
            d1.process(spawn_id, timeout=60)
            try:
                spawn_id.expect("Password OK.*")
            except:
                pass
            spawn_id.sendline()
            time.sleep(10)
            try:
                __wait_for_rommon(spawn_id, 900)
            except:
                LOGGER.info("\nFailed to get a valid prompt")
                spawn_id.close()
                return False
            LOGGER.info('%s on port %d is available' % (host, port))
            spawn_id.close()
        except:
            return False
    else:
        raise RuntimeError('Device can be accessed only by telnet or ssh')

    return True
示例#11
0
def clear_line(host, port, user=DEFAULT_USERNAME, pwd=DEFAULT_PASSWORD, prompt='#',
               access='telnet', en_password=DEFAULT_ENPASSWORD, timeout=None):
    """Clear line corresponding to a device; this is required because only a
    single console connection is available.

    If somebody or some process failed to close the connection, it
    should be cleared explicitly.
    
    This function accepts only ssh and telnet connections.

    :param host: ip address of terminal server
    :param port: device line number in terminal server to be cleared
                for example, if port 2005 is mapped to line 5, port=5
    :param user: username
    :param pwd: password
    :param prompt: expected prompt after logging in
    :param access: ssh or telnet; default is set to telnet
    :param en_password: enable password to switch to line configuration mode
    :param timeout: how long the connection and authentication would take in seconds;
                    if not provided, default is 60s
    :return: None
    
    """

    if user == DEFAULT_USERNAME:
        user = get_username(user)
    if pwd == DEFAULT_PASSWORD:
        pwd = get_password(pwd)
    if en_password == DEFAULT_ENPASSWORD:
        en_password = get_password(en_password)

    if not timeout:
        timeout = DEFAULT_TIMEOUT

    d1 = None
    spawn = None

    # establish a connection to the terminal server
    if access == 'telnet':
        spawn = Spawn('telnet {} {}'.format(host, '23'))
        d1 = Dialog([
            ["Connected to.*Escape character is '\^\]'\.", 'sendline()', None, True, False],
            ['.*Username:'******'sendline({})'.format(user), None, True, False],
            ['(p|P)assword:', 'sendline({})'.format(pwd), None, True, True],
            [prompt, 'sendline()', None, False, False],
            ['>', 'sendline()', None, False, False],
        ])

    elif access == 'ssh':
        spawn = Spawn('ssh -o UserKnownHostsFile=/dev/null -o StrictHostKeyChecking=no '
                      '-l {} -p {} {}'.format(user, '22', host))
        d1 = Dialog([
            ['continue connecting (yes/no)?', 'sendline(yes)', None, True, False],
            ['(p|P)assword:', 'sendline({})'.format(pwd), None, False, False],
        ])

    else:
        LOGGER.error('Unknown protocol: Telnet or ssh supported only')

    try:
        LOGGER.info('Trying to connect to {}'.format(host))
        d1.process(spawn, timeout=timeout)
        try:
            spawn.expect("Password OK.*")
        except TimeoutError:
            LOGGER.info("'Password OK' message didn't appear")
            pass
        spawn.sendline()
    except TimeoutError:
        LOGGER.error('Failed to connect to terminal server')
        raise Exception('Failed to connect to terminal server')

    # clear port section
    try:
        spawn.expect('#')
    except:
        # expect >
        spawn.sendline('en')
        try:
            spawn.expect('Password:'******'detected line number for clearing: {} from port {}'.
                    format(line_id, port))
        if line_id:
            spawn.sendline('clear line {}'.format(line_id))
            spawn.expect('[confirm]')
            spawn.sendline('')
            spawn.expect('[OK]')
            LOGGER.info('line: {} was cleared'.format(port))
        spawn.close()
    except TimeoutError:
        spawn.close()
        LOGGER.error('Line: {} was not cleared'.format(port))
        raise Exception('Line {} was NOT cleared'.format(port))
from unicon.eal.dialogs import Statement, Dialog
from unicon.eal.dialog_processor import DialogProcessor
from inspect import getfullargspec as spec
from unicon.eal.expect import Spawn
from unicon.utils import AttributeDict

start1 = 'ls'
start2 = 'ps'

s1 = Spawn(start1)
# s2 = Spawn(start2)

pattern = '^pattern$'

def cb1():
    print('cb with no args')

def cb2(spawn, context):
    print('spawn=%s; context=%s' % (spawn, context))


def cb3(spawn, context, session, name):
    session.check = 'yes it works'
    session.num = 10
    print('spawn=%s; context=%s, session=%s; name=%s' % (spawn, context, session, name))


def cb4(spawn, city='bangalore'):
    print('spawn=%s; city=%s' % (spawn, city))

示例#13
0
import os
from unicon.eal.expect import Spawn
from time import sleep
sec = 0.1
print('spawning processes .....')
s1 = Spawn("telnet 10.64.70.24 2020")
s2 = Spawn("telnet 10.64.70.24 2019")


def waitpid():
    print('\ns1> waitpid for s1')
    ret = os.waitpid(s1.pid, os.WNOHANG)
    print(ret)

    print('s2> waitpid for s2')
    ret = os.waitpid(s2.pid, os.WNOHANG)
    print(ret)


def process():
    print('\ns1> ps command output')
    os.system("ps -eaf | grep -i %s| grep -v grep" % s1.pid)
    print('s2> ps command output')
    os.system("ps -eaf | grep -i %s| grep -v grep" % s2.pid)


print('sleeping for %s seconds ....' % sec)
sleep(sec)

print('\ns1> expect output ....')
s1.expect(r'.*')
示例#14
0
import os
from unicon.eal.expect import Spawn, TimeoutError
router_command = os.path.join(os.getcwd(), 'router.sh')
prompt = 'sim-router'
enable_prompt = prompt + '#'
disable_prompt = prompt + '>'
s = Spawn(router_command)
try:
    s.sendline()
    s.expect([r'username:\s?$', r'login:\s?$'], timeout=5)
    s.sendline('admin')
    s.expect([r'password:\s?$'], timeout=5)
    s.sendline('lab')
    s.expect([disable_prompt])
    s.sendline('enable')
    s.expect([r'password:\s?$'], timeout=5)
    s.sendline('lablab')
    s.expect([enable_prompt])
    s.sendline('show clock')
    s.expect([enable_prompt])
except TimeoutError as err:
    print('errored becuase of timeout')