Пример #1
0
import os
from unicon.eal.expect import Spawn, TimeoutError
from unicon.eal.dialogs import Statement, Dialog

router_command = os.path.join(os.getcwd(), 'router.sh')
prompt = 'sim-router'
enable_prompt = prompt + '#'
disable_prompt = prompt + '>'

# construct the dialog
d = Dialog([
    [r'enter to continue \.\.\.', lambda spawn: spawn.sendline(), None, True, False],
    [r'username:\s?$', lambda spawn: spawn.sendline("admin"), None, True, False],
    [r'password:\s?$', lambda spawn: spawn.sendline("lab"), None, True, False],
    [disable_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()
Пример #2
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)

    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)

    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()
Пример #3
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))
Пример #4
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
Пример #5
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 ('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
    '''

    # 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(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)

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

    dialog = RommonDialog()
    dialog.dialog.process(spawn,
                          context={
                              'kick': golden_image.get('kickstart'),
                              'sys': golden_image.get('system'),
                              'password': recovery_password
                          },
                          timeout=timeout)
    spawn.close()
Пример #6
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)

    # TODO: We need to fix that handlers[1]...
    # Make it stronger.
    # For now, if it doesnt exists, then just get out
    try:
        logfile = log.handlers[1].logfile
    except IndexError as e:
        raise Exception('Could not recover the device')

    spawn = Spawn(start,
                  settings=device.cli.settings,
                  target=target,
                  log=log,
                  logfile=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()
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))

Пример #8
0
def recovery_worker(start,
                    device,
                    console_activity_pattern=None,
                    console_breakboot_char=None,
                    grub_activity_pattern=None,
                    grub_breakboot_char=None,
                    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
            console_breakboot_char (str): Character to send when console_activity_pattern is matched
            grub_activity_pattern (str): Break pattern on the device for grub boot mode
            grub_breakboot_char (str): Character to send when grub_activity_pattern is matched
            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 console_breakboot(spawn, break_count, break_char):
        """ Breaks the booting process on a device

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

            Returns:
                None
        """

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

        for _ in range(break_count):
            log.info(f"Sending {repr(break_char)}")
            spawn.send(break_char)
            time.sleep(1)

    def grub_breakboot(spawn, break_char):
        """ Breaks the booting process on a device

            Args:
                spawn (obj): Spawn connection object
                break_char (str): Char to send

            Returns:
                None
        """

        log.info(f"Found the grub_activity_pattern! Breaking the boot process "
                 f"by sending {repr(break_char)}")

        spawn.send(break_char)

    # 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()
    if console_activity_pattern and console_breakboot_char:
        break_dialog.add_statement(Statement(pattern=console_activity_pattern,
                                             action=console_breakboot,
                                             args={
                                                 'break_count':
                                                 break_count,
                                                 'break_char':
                                                 console_breakboot_char
                                             },
                                             loop_continue=True,
                                             continue_timer=False),
                                   pos=0)

    if grub_activity_pattern and grub_breakboot_char:
        break_dialog.add_statement(Statement(
            pattern=grub_activity_pattern,
            action=grub_breakboot,
            args={'break_char': grub_breakboot_char},
            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()
Пример #9
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'.*')