예제 #1
0
 def reconnect(self, steps, device):
     with steps.start("Reconnect to device {} after TFTP boot". \
                              format(device.name)) as step:
                              
         if hasattr(device, 'chassis_type') and device.chassis_type.lower() == 'stack':
             log.info("Sleep for 90 seconds in order to sync ")
             time.sleep(90)
         if not _disconnect_reconnect(device):
             # If that still doesnt work, Thats all we got
             step.failed("Cannot reconnect to the device {d} after TFTP boot".
                         format(d=device.name), )
         else:
             log.info("Success - Have recovered and reconnected to device '{}'". \
                      format(device.name))
예제 #2
0
def tftp_boot(section,
              steps,
              device,
              ip_address,
              subnet_mask,
              gateway,
              tftp_server,
              image,
              recovery_password=None,
              save_system_config=True,
              timeout=600,
              config_reg_timeout=30):
    """ This stage boots a new image onto your device using the tftp booting
    method.

    Stage Schema
    ------------
    tftp_boot:
        image (list): Image to boot with

        ip_address (list): Management ip address to configure to reach to the
            tftp server

        subnet_mask (str): Management subnet mask

        gateway (str): Management gateway

        tftp_server (str): Tftp server that is reachable with management interface

        recovery_password (str, optional): Enable password for device
            required after bootup. Defaults to None.

        save_system_config (bool, optional): Whether or not to save the
            system config if it was modified. Defaults to True.

        timeout (int, optional): Max time during which tftp boot must
            complete. Defaults to 600.

        config_reg_timeout (int, optional): Max time to set config-register.
            Defaults to 30.

    Example
    -------
    tftp_boot:
        image:
          - /auto/some-location/that-this/image/stay-isr-image.bin
        ip_address: [10.1.7.126, 10.1.7.127]
        gateway: 10.1.7.1
        subnet_mask: 255.255.255.0
        tftp_server: 11.1.7.251
        recovery_password: nbv_12345
        save_system_config: False
        timeout: 600
        config_reg_timeout: 10

    There is more than one ip address, one for each supervisor.

    """

    log.info("Section steps:"
             "\n1- Set config-register to 0x0"
             "\n2- Bring device down to rommon> prompt prior to TFTP boot"
             "\n3- Begin TFTP boot"
             "\n4- Reconnect to device after TFTP boot"
             "\n5- Reset config-register to 0x2101"
             "\n6- Execute 'write memory'")

    # Set config-register to 0x0
    with steps.start("Set config-register to 0x0 on {}".format(
            device.name)) as step:
        try:
            device.api.execute_set_config_register(config_register='0x0',
                                                   timeout=config_reg_timeout)
        except Exception as e:
            step.failed(
                "Unable to set config-register to 0x0 prior to TFTP"
                " boot on {}".format(device.name), )

    # Bring the device down to rommon> prompt prior to TFTP boot
    with steps.start("Bring device {} down to rommon> prompt prior to TFTP boot".\
                        format(device.name)) as step:

        reload_dialog = Dialog([
            Statement(
                pattern=
                r".*System configuration has been modified\. Save\? \[yes\/no\].*",
                action='sendline(yes)'
                if save_system_config else 'sendline(no)',
                loop_continue=True,
                continue_timer=False),
            Statement(pattern=r".*Proceed with reload\? \[confirm\].*",
                      action='sendline()',
                      loop_continue=False,
                      continue_timer=False),
        ])

        # Using sendline, as we dont want unicon boot to kick in and send "boot"
        # to the device. Cannot use device.reload() directly as in case of HA,
        # we need both sup to do the commands
        device.sendline('reload')
        reload_dialog.process(device.spawn)

        if device.is_ha:

            def reload_check(device, target):
                device.expect(['.*Initializing Hardware.*'],
                              target=target,
                              timeout=60)

            pcall(reload_check,
                  ckwargs={'device': device},
                  ikwargs=[{
                      'target': 'active'
                  }, {
                      'target': 'standby'
                  }])
        else:
            device.expect(['.*Initializing Hardware.*'], timeout=60)

        log.info("Device is reloading")
        device.destroy_all()

    # Begin TFTP boot of device
    with steps.start("Begin TFTP boot of device {}".format(
            device.name)) as step:

        # Need to instantiate to get the device.start
        # The device.start only works because of a|b
        device.instantiate(connection_timeout=timeout)

        tftp_boot = {
            'ip_address': ip_address,
            'subnet_mask': subnet_mask,
            'gateway': gateway,
            'tftp_server': tftp_server,
            'image': image
        }
        try:
            abstract = Lookup.from_device(device, packages={'clean': clean})
            # Item is needed to be able to know in which parallel child

            # device.start only gets filled with single rp devices
            # for multiple rp devices we need to use subconnections
            if device.is_ha and hasattr(device, 'subconnections'):
                start = [i.start[0] for i in device.subconnections]
            else:
                start = device.start

            result = pcall(abstract.clean.recovery.recovery.recovery_worker,
                           start=start,
                           ikwargs = [{'item': i} for i, _ in enumerate(start)],
                           ckwargs = \
                                {'device': device,
                                 'timeout': timeout,
                                 'tftp_boot': tftp_boot,
                                 'break_count': 0,
                                 # Irrelevant as we will not use this pattern anyway
                                 # But needed for the recovery
                                 'console_activity_pattern': '\\.\\.\\.\\.',
                                 'golden_image': None,
                                 'recovery_password': recovery_password})
        except Exception as e:
            log.error(str(e))
            step.failed("Failed to TFTP boot the device '{}'".\
                           format(device.name), )
        else:
            log.info("Successfully performed TFTP boot on device '{}'".\
                     format(device.name))

    # Disconnect and reconnect to the device
    with steps.start("Reconnect to device {} after TFTP boot".\
                        format(device.name)) as step:
        if not _disconnect_reconnect(device):
            # If that still doesnt work, Thats all we got
            step.failed(
                "Cannot reconnect to the device {d} after TFTP boot".format(
                    d=device.name), )
        else:
            log.info("Success - Have recovered and reconnected to device '{}'".\
                     format(device.name))

    # Reset config-register to 0x2101
    with steps.start("Reset config-register to 0x2101 on {}".\
                        format(device.name)) as step:
        try:
            device.api.execute_set_config_register(config_register='0x2102',
                                                   timeout=config_reg_timeout)
        except Exception as e:
            log.error(str(e))
            step.failed(
                "Unable to reset config-register to 0x2101 after TFTP"
                " boot on {}".format(device.name), )

    # Execute 'write memory'
    with steps.start("Execute 'write memory' on {}".format(
            device.name)) as step:
        try:
            device.api.execute_write_memory()
        except Exception as e:
            log.error(str(e))
            step.failed(
                "Unable to execute 'write memory' after TFTP boot "
                "on {}".format(device.name), )
        else:
            section.passed("Successfully performed TFTP boot on device {}".\
                            format(device.name))
예제 #3
0
    def tftp_boot(self, device, ip_address, subnet_mask, gateway, tftp_server,
                  image, timeout, reconnect_delay=RECONNECT_DELAY,
                  reboot_delay=REBOOT_DELAY):
        device.api.execute_write_erase_boot()
        # Using sendline, as we dont want unicon boot to kick in and send "boot" to
        # the device
        # Cannot use .reload as in case of HA, we need both sup to do the commands
        device.sendline('reload')
        device.sendline('y')
        device.sendline()
        log.info('** Rebooting the device **')

        # We now want to overwrite the statemachine
        device.destroy_all()
        # Sleep to make sure the device is reloading
        time.sleep(reboot_delay)

        # Need to instantiate to get the device.start
        # The device.start only works because of a|b
        device.instantiate(connection_timeout=timeout)

        tftp_boot = {'ip_address': ip_address,
                     'subnet_mask': subnet_mask,
                     'gateway': gateway,
                     'tftp_server': tftp_server,
                     'image': image}
        try:
            abstract = Lookup.from_device(device, packages={'clean': clean})
            # Item is needed to be able to know in which parallel child
            # we are

            # device.start only gets filled with single rp devices
            # for multiple rp devices we need to use subconnections
            if device.is_ha and hasattr(device, 'subconnections'):
                start = [i.start[0] for i in device.subconnections]
            else:
                start = device.start

            result = pcall(abstract.clean.recovery.recovery.recovery_worker,
                           start=start,
                           ikwargs = [{'item': i} for i, _ in enumerate(start)],
                           ckwargs = \
                                {'device': device,
                                 'timeout': timeout,
                                 'tftp_boot': tftp_boot,
                                 # Irrelevant as we will not use this pattern anyway
                                 # But needed for the recovery
                                 'break_count': 0,
                                 'console_activity_pattern': '\\.\\.\\.\\.',
                                 'golden_image': None,
                                 'recovery_password': None})
        except Exception as e:
            log.error(str(e))
            self.failed("Failed to recover the device '{}'".\
                            format(device.name))
        else:
            log.info("Successfully recovered the device '{}'".\
                     format(device.name))

        log.info('Sleeping for {r} before reconnection'.format(r=reconnect_delay))
        time.sleep(reconnect_delay)

        # Disconnect and reconnect to the device
        if not _disconnect_reconnect(device):
            # If that still doesnt work, Thats all we got
            self.failed("Cannot reconnect to the device {d}".
                            format(d=device.name))
        else:
            log.info("Success - Have recovered and reconnected to device '{}'".\
                     format(device.name))

        log.info('Set the boot variables')
        output = device.api.get_running_image()
        if not output:
            self.failed('Could not retrieved the running image')
        image = output[0].rsplit('/', 1)[1]
        device.api.execute_change_boot_variable(system='bootflash:/{image}'
                                                      .format(image=image))
        device.api.execute_copy_run_to_start()
예제 #4
0
def tftp_boot(section, steps, device, ip_address, subnet_mask, gateway,
    tftp_server, image, timeout=600, config_reg_timeout=30,
    device_reload_sleep=20, recovery_username=None, recovery_password=None):
    """ This stage boots a new image onto your device using the tftp booting
    method.

    Stage Schema
    ------------
    tftp_boot:
        image: <Image to boot with `list`> (Mandatory)
        ip_address: <Management ip address to configure to reach to the TFTP server `str`> (Mandatory)
        subnet_mask: <Management subnet mask `str`> (Mandatory)
        gateway: <Management gateway `str`> (Mandatory)
        tftp_server: <tftp server is reachable with management interface `str`> (Mandatory)
        timeout: <Maximum time during which TFTP boot process must complete `int`> (Optional, Default 600 seconds)
        config_reg_timeout: <Time to wait after setting config-register `int`> (Optional, Default 30 seconds)
        device_reload_sleep: <Time to wait after reloading device `int`> (Optional, Default 20 seconds)
        recovery_username: <Enable username for device required after bootup `str`> (Optional, Default None)
        recovery_password: <Enable password for device required after bootup `str`> (Optional, Default None)

    Example
    -------
    tftp_boot:
        image:
            - /auto/some-location/that-this/image/asr9k-mini-px.vm
        ip_address: [10.1.7.126, 10.1.7.127]
        gateway: 10.1.7.1
        subnet_mask: 255.255.255.0
        tftp_server: 11.1.7.251
        timeout: 1200
        config_reg_timeout: 60
        device_reload_sleep: 300
        recovery_username: admin
        recovery_password: nbv_12345

    Note: There is more than one ip address, one for each supervisor.

    """

    log.info("Section steps:"
             "\n1- Set config-register to 0x1820"
             "\n2- Bring device down to rommon> prompt prior to TFTP boot"
             "\n3- Begin TFTP boot"
             "\n4- Reconnect to device after TFTP boot"
             "\n5- Reset config-register to 0x1922")

    # Set config-register to 0x1820
    with steps.start("Set config-register to 0x1820 on {}".\
                    format(device.name)) as step:
        try:
            device.api.execute_set_config_register(config_register='0x1820',
                                                   timeout=config_reg_timeout)
        except Exception as e:
            step.failed("Unable to set config-register to 0x1820 prior to TFTP"
                           " boot on {}".format(device.name))

    # Bring the device down to rommon > prompt prior to TFTP boot
    with steps.start("Bring device {} down to rommon > prompt prior to TFTP boot".\
                        format(device.name)) as step:

        # Reload device
        try:
            device.admin_execute("reload location all")
        except Exception as e:
            # We now want to overwrite the statemachine
            device.destroy_all()

            # Sleep to make sure the device is reloading
            time.sleep(device_reload_sleep)
        else:
            step.failed("Unable to bring the device down to rommon> prompt")


    # Begin TFTP boot of device
    with steps.start("Begin TFTP boot of device {}".format(device.name)) as step:

        # Need to instantiate to get the device.start
        # The device.start only works because of a|b
        device.instantiate(connection_timeout=timeout)

        tftp_boot = {'ip_address': ip_address,
                     'subnet_mask': subnet_mask,
                     'gateway': gateway,
                     'tftp_server': tftp_server,
                     'image': image}
        try:
            abstract = Lookup.from_device(device, packages={'clean': clean})
            # Item is needed to be able to know in which parallel child
            # we are

            # device.start only gets filled with single rp devices
            # for multiple rp devices we need to use subconnections
            if device.is_ha and hasattr(device, 'subconnections'):
                start = [i.start[0] for i in device.subconnections]
            else:
                start = device.start

            result = pcall(abstract.clean.recovery.recovery.recovery_worker,
                           start=start,
                           ikwargs = [{'item': i} for i, _ in enumerate(start)],
                           ckwargs = \
                                {'device': device,
                                 'timeout': timeout,
                                 'tftp_boot': tftp_boot,
                                 'break_count': 0,
                                 # Irrelevant as we will not use this pattern anyway
                                 # But needed for the recovery
                                 'console_activity_pattern': '\\.\\.\\.\\.',
                                 'golden_image': None,
                                 'recovery_username': recovery_username,
                                 'recovery_password': recovery_password})
        except Exception as e:
            log.error(str(e))
            step.failed("Failed to TFTP boot the device '{}'".\
                           format(device.name))
        else:
            log.info("Successfully performed TFTP boot on device '{}'".\
                     format(device.name))

    # Disconnect and reconnect to the device
    with steps.start("Reconnect to device {} after TFTP boot".\
                        format(device.name)) as step:
        if not _disconnect_reconnect(device):
            # If that still doesnt work, Thats all we got
            step.failed("Cannot reconnect to the device {d} after TFTP boot".
                            format(d=device.name))
        else:
            log.info("Success - Have recovered and reconnected to device '{}'".\
                     format(device.name))

    # Reset config-register to 0x1922
    with steps.start("Reset config-register to 0x1922 on {}".\
                        format(device.name)) as step:
        try:
            device.api.execute_set_config_register(config_register='0x1922',
                                                   timeout=config_reg_timeout)
        except Exception as e:
            log.error(str(e))
            step.failed("Unable to reset config-register to 0x1922 after TFTP"
                           " boot on {}".format(device.name))
예제 #5
0
def tftp_boot(section, steps, device, ip_address, subnet_mask, gateway,
              tftp_server, image, timeout, reconnect_delay=60,
              reboot_delay=20):
    """ This stage boots a new image onto your device using the tftp booting
    method.

    Stage Schema
    ------------
    tftp_boot:
        image: <Image to boot with `str`> (Mandatory)
        ip_address: <Management ip address to configure to reach to the TFTP server `str`> (Mandatory)
        subnet_mask: <Management subnet mask `str`> (Mandatory)
        gateway: <Management gateway `str`> (Mandatory)
        tftp_server: <tftp server is reachable with management interface> (Mandatory)
        timeout: <Maximum time for tftp boot `int`> (Mandatory)
        reboot_delay: <Maximum time for tftp boot `int`> (Optional)
        reconnect_delay: <Once device recovered, delay before final reconnect>, 'int'> (Default: 60)

    Example:
    --------
    tftp_boot:
        image:
          - /auto/some-location/that-this/image/stay-isr-image.bin
        ip_address: [10.1.7.126, 10.1.7.127]
        gateway: 10.1.7.1
        subnet_mask: 255.255.255.0
        tftp_server: 11.1.7.251

    There is more than one ip address, one for each supervisor.

    """

    device.api.execute_write_erase_boot()
    # Using sendline, as we dont want unicon boot to kick in and send "boot" to
    # the device
    # Cannot use .reload as in case of HA, we need both sup to do the commands
    device.sendline('reload')
    device.sendline('y')
    device.sendline()
    log.info('** Rebooting the device **')

    # We now want to overwrite the statemachine
    device.destroy_all()
    # Sleep to make sure the device is reloading
    time.sleep(reboot_delay)

    # Need to instantiate to get the device.start
    # The device.start only works because of a|b
    device.instantiate(connection_timeout=timeout)

    tftp_boot = {'ip_address': ip_address,
                 'subnet_mask': subnet_mask,
                 'gateway': gateway,
                 'tftp_server': tftp_server,
                 'image': image}
    try:
        abstract = Lookup.from_device(device, packages={'clean': clean})
        # Item is needed to be able to know in which parallel child
        # we are

        # device.start only gets filled with single rp devices
        # for multiple rp devices we need to use subconnections
        if device.is_ha and hasattr(device, 'subconnections'):
            start = [i.start[0] for i in device.subconnections]
        else:
            start = device.start

        result = pcall(abstract.clean.recovery.recovery.recovery_worker,
                       start=start,
                       ikwargs = [{'item': i} for i, _ in enumerate(start)],
                       ckwargs = \
                            {'device': device,
                             'timeout': timeout,
                             'tftp_boot': tftp_boot,
                             # Irrelevant as we will not use this pattern anyway
                             # But needed for the recovery
                             'break_count': 0,
                             'console_activity_pattern': '\\.\\.\\.\\.',
                             'golden_image': None,
                             'recovery_password': None})
    except Exception as e:
        log.error(str(e))
        section.failed("Failed to recover the device '{}'".\
                        format(device.name))
    else:
        log.info("Successfully recovered the device '{}'".\
                 format(device.name))

    log.info('Sleeping for {r} before reconnection'.format(r=reconnect_delay))
    time.sleep(reconnect_delay)

    # Disconnect and reconnect to the device
    if not _disconnect_reconnect(device):
        # If that still doesnt work, Thats all we got
        section.failed("Cannot reconnect to the device {d}".
                        format(d=device.name))
    else:
        log.info("Success - Have recovered and reconnected to device '{}'".\
                 format(device.name))

    log.info('Set the boot variables')
    output = device.api.get_running_image()
    if not output:
        section.failed('Could not retrieved the running image')
    image = output[0].rsplit('/', 1)[1]
    device.api.execute_change_boot_variable(system='bootflash:/{image}'
                                                  .format(image=image))
    device.api.execute_copy_run_to_start()