Beispiel #1
0
class MamboConsole():
    '''
    A 'connection' to the Mambo Console involves *launching* Mambo.
    Closing a connection will *terminate* the Mambo process.
    '''
    def __init__(self,
                 mambo_binary=None,
                 mambo_initial_run_script=None,
                 mambo_autorun=None,
                 skiboot=None,
                 prompt=None,
                 kernel=None,
                 initramfs=None,
                 block_setup_term=None,
                 delaybeforesend=None,
                 timeout_factor=1,
                 logfile=sys.stdout):
        self.mambo_binary = mambo_binary
        self.mambo_initial_run_script = mambo_initial_run_script
        self.mambo_autorun = mambo_autorun
        self.skiboot = skiboot
        self.kernel = kernel
        self.initramfs = initramfs
        self.state = ConsoleState.DISCONNECTED
        self.logfile = logfile
        self.delaybeforesend = delaybeforesend
        self.system = None
        # OpTestUtil instance is NOT conf's
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.pty = None
        self.block_setup_term = block_setup_term  # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0  # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0  # flags the object to abandon setup_term operations, like when system off
        self.timeout_factor = timeout_factor  # functional simulators are notoriously slow, so multiply all default timeouts by this factor

        # state tracking, reset on boot and state changes
        # console tracking done on System object for the system console
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        try:
            rc_child = self.pty.close()
            exitCode = signalstatus = None
            if self.pty.status != -1:  # leaving for debug
                if os.WIFEXITED(self.pty.status):
                    exitCode = os.WEXITSTATUS(self.pty.status)
                else:
                    signalstatus = os.WTERMSIG(self.pty.status)
            self.state = ConsoleState.DISCONNECTED
        except pexpect.ExceptionPexpect as e:
            self.state = ConsoleState.DISCONNECTED
            raise "Mambo Console: failed to close console"
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            pass
        log.debug("Mambo close -> TERMINATE")

    def connect(self):
        if self.state == ConsoleState.CONNECTED:
            return self.pty
        else:
            self.util.clear_state(self)  # clear when coming in DISCONNECTED

        log.debug("#Mambo Console CONNECT")

        if not os.access(self.mambo_initial_run_script, os.R_OK | os.W_OK):
            raise ParameterCheck(
                message="Check that the file exists with"
                " R/W permissions mambo-initial-run-script={}".format(
                    self.mambo_initial_run_script))

        cmd = ("%s" % (self.mambo_binary) + " -e" +
               " -f {}".format(self.mambo_initial_run_script))

        spawn_env = os.environ
        if self.skiboot:
            spawn_env['SKIBOOT'] = self.skiboot
        if self.kernel:
            spawn_env['SKIBOOT_ZIMAGE'] = self.kernel
        if self.initramfs:
            if not os.access(self.initramfs, os.R_OK | os.W_OK):
                raise ParameterCheck(message="Check that the file exists with"
                                     " R/W permissions flash-initramfs={}".
                                     format(self.initramfs))
            spawn_env['SKIBOOT_INITRD'] = self.initramfs
        if self.mambo_autorun:
            spawn_env['SKIBOOT_AUTORUN'] = str(self.mambo_autorun)
        log.debug("OpTestMambo cmd={} mambo spawn_env={}".format(
            cmd, spawn_env))
        try:
            self.pty = OPexpect.spawn(cmd, logfile=self.logfile, env=spawn_env)
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            raise CommandFailed(
                'OPexpect.spawn',
                'OPexpect.spawn encountered a problem: ' + str(e), -1)

        self.state = ConsoleState.CONNECTED
        self.pty.setwinsize(1000, 1000)
        if self.delaybeforesend:
            self.pty.delaybeforesend = self.delaybeforesend

        if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
            self.util.setup_term(self.system, self.pty, None,
                                 self.system.block_setup_term)

        time.sleep(0.2)
        if not self.pty.isalive():
            raise CommandFailed(cmd, self.pty.read(), self.pty.status)
        return self.pty

    def get_console(self):
        if self.state == ConsoleState.DISCONNECTED:
            self.util.clear_state(self)
            self.connect()
        else:
            if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
                self.util.setup_term(self.system, self.pty, None,
                                     self.system.block_setup_term)

        return self.pty

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command,
                                     timeout * self.timeout_factor, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command,
                                                 timeout * self.timeout_factor,
                                                 retry)

    def mambo_run_command(self, command, timeout=60, retry=0):
        return self.util.mambo_run_command(self, command,
                                           timeout * self.timeout_factor,
                                           retry)

    def mambo_exit(self):
        return self.util.mambo_exit(self)

    def mambo_enter(self):
        return self.util.mambo_enter(self)
class QemuConsole():
    """
    A 'connection' to the Qemu Console involves *launching* qemu.
    Closing a connection will *terminate* the qemu process.
    """
    def __init__(self, qemu_binary=None, pnor=None, skiboot=None,
            prompt=None, kernel=None, initramfs=None,
            block_setup_term=None, delaybeforesend=None,
            logfile=sys.stdout, hda=None, cdrom=None):
        self.qemu_binary = qemu_binary
        self.pnor = pnor
        self.skiboot = skiboot
        self.kernel = kernel
        self.initramfs = initramfs
        self.hda = hda
        self.state = ConsoleState.DISCONNECTED
        self.logfile = logfile
        self.delaybeforesend = delaybeforesend
        self.system = None
        self.cdrom = cdrom
        # OpTestUtil instance is NOT conf's
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.pty = None
        self.block_setup_term = block_setup_term # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0 # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0 # flags the object to abandon setup_term operations, like when system off

        # state tracking, reset on boot and state changes
        # console tracking done on System object for the system console
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        try:
            rc_child = self.pty.close()
            exitCode = signalstatus = None
            if self.pty.status != -1: # leaving for debug
              if os.WIFEXITED(self.pty.status):
                exitCode = os.WEXITSTATUS(self.pty.status)
              else:
                signalstatus = os.WTERMSIG(self.pty.status)
            self.state = ConsoleState.DISCONNECTED
        except pexpect.ExceptionPexpect as e:
            self.state = ConsoleState.DISCONNECTED
            raise "Qemu Console: failed to close console"
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            pass
        log.debug("Qemu close -> TERMINATE")

    def connect(self):
        if self.state == ConsoleState.CONNECTED:
            return self.pty
        else:
            self.util.clear_state(self) # clear when coming in DISCONNECTED

        log.debug("#Qemu Console CONNECT")

        cmd = ("%s" % (self.qemu_binary)
               + " -machine powernv -m 4G"
               + " -nographic -nodefaults"
           )
        if self.pnor:
            cmd = cmd + " -drive file={},format=raw,if=mtd".format(self.pnor)
        if self.skiboot:
            cmd = cmd + " -bios %s" % (self.skiboot)
        if self.kernel:
            cmd = cmd + " -kernel %s" % (self.kernel)
            if self.initramfs is not None:
                cmd = cmd + " -initrd %s" % (self.initramfs)

        if self.hda is not None:
            # Put the disk on the first PHB
            cmd = (cmd
                    + " -drive file={},id=disk01,if=none".format(self.hda)
                    + " -device virtio-blk-pci,drive=disk01,id=virtio01,bus=pcie.0,addr=0"
                )
        if self.cdrom is not None:
            # Put the CDROM on the second PHB
            cmd = (cmd
                    + " -drive file={},id=cdrom01,if=none,media=cdrom".format(self.cdrom)
                    + " -device virtio-blk-pci,drive=cdrom01,id=virtio02,bus=pcie.1,addr=0"
                )
        # typical host ip=10.0.2.2 and typical skiroot 10.0.2.15
        # use skiroot as the source, no sshd in skiroot
        cmd = cmd + " -nic user,model=virtio-net-pci"
        cmd = cmd + " -device ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10"
        cmd = cmd + " -serial none -device isa-serial,chardev=s1 -chardev stdio,id=s1,signal=off"
        print(cmd)
        try:
          self.pty = OPexpect.spawn(cmd,logfile=self.logfile)
        except Exception as e:
          self.state = ConsoleState.DISCONNECTED
          raise CommandFailed('OPexpect.spawn',
                  'OPexpect.spawn encountered a problem: ' + str(e), -1)

        self.state = ConsoleState.CONNECTED
        self.pty.setwinsize(1000,1000)
        if self.delaybeforesend:
          self.pty.delaybeforesend = self.delaybeforesend

        if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
          self.util.setup_term(self.system, self.pty, None, self.system.block_setup_term)

        # Wait a moment for isalive() to read a correct value and then check
        # if the command has already exited. If it has then QEMU has most
        # likely encountered an error and there's no point proceeding.
        time.sleep(0.2)
        if not self.pty.isalive():
            raise CommandFailed(cmd, self.pty.read(), self.pty.status)
        return self.pty

    def get_console(self):
        if self.state == ConsoleState.DISCONNECTED:
            self.util.clear_state(self)
            self.connect()
        else:
            if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
                self.util.setup_term(self.system, self.pty, None, self.system.block_setup_term)

        return self.pty

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)
class IPMIConsole():
    def __init__(self,
                 ipmitool=None,
                 logfile=sys.stdout,
                 prompt=None,
                 block_setup_term=None,
                 delaybeforesend=None):
        self.logfile = logfile
        self.ipmitool = ipmitool
        self.state = IPMIConsoleState.DISCONNECTED
        self.delaybeforesend = delaybeforesend
        self.system = None
        # OpTestUtil instance is NOT conf's
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.pty = None
        self.delaybeforesend = delaybeforesend
        self.block_setup_term = block_setup_term  # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0  # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0  # flags the object to abandon setup_term operations, like when system off

        # FUTURE - System Console currently tracked in System Object
        # state tracking, reset on boot and state changes
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        if self.state == IPMIConsoleState.DISCONNECTED:
            return
        try:
            self.pty.send("\r")
            self.pty.send('~.')
            close_rc = self.pty.expect(
                ['[terminated ipmitool]', pexpect.TIMEOUT, pexpect.EOF],
                timeout=10)
            log.debug("CLOSE Expect Buffer ID={}".format(hex(id(self.pty))))
            rc_child = self.pty.close()
            self.state = IPMIConsoleState.DISCONNECTED
            exitCode = signalstatus = None
            if self.pty.status != -1:  # leaving for future debug
                if os.WIFEXITED(self.pty.status):
                    exitCode = os.WEXITSTATUS(self.pty.status)
                else:
                    signalstatus = os.WTERMSIG(self.pty.status)
        except pexpect.ExceptionPexpect:
            self.state = IPMIConsoleState.DISCONNECTED
            raise OpTestError("IPMI: failed to close ipmi console")
        except Exception as e:
            self.state = IPMIConsoleState.DISCONNECTED
            pass

    def connect(self, logger=None):
        if self.state == IPMIConsoleState.CONNECTED:
            rc_child = self.close()
        else:
            self.util.clear_state(self)

        try:
            self.ipmitool.run('sol deactivate')
        except OpTestError:
            log.info('SOL already deactivated')

        cmd = self.ipmitool.binary_name() + self.ipmitool.arguments(
        ) + ' sol activate'
        try:
            self.pty = OPexpect.spawn(
                cmd,
                logfile=self.logfile,
                failure_callback=set_system_to_UNKNOWN_BAD,
                failure_callback_data=self.system)
        except Exception as e:
            self.state = IPMIConsoleState.DISCONNECTED
            raise CommandFailed(
                'OPexpect.spawn',
                "OPexpect.spawn encountered a problem, command was '{}'".
                format(cmd), -1)

        log.debug("#IPMI SOL CONNECT")
        self.state = IPMIConsoleState.CONNECTED
        self.pty.setwinsize(1000, 1000)

        if logger:
            self.pty.logfile_read = OpTestLogger.FileLikeLogger(logger)
        else:
            self.pty.logfile_read = OpTestLogger.FileLikeLogger(log)

        if self.delaybeforesend:
            self.pty.delaybeforesend = self.delaybeforesend
        rc = self.pty.expect_exact([
            '[SOL Session operational.  Use ~? for help]', pexpect.TIMEOUT,
            pexpect.EOF
        ],
                                   timeout=10)
        log.debug("rc={}".format(rc))
        if rc == 0:
            if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
                self.util.setup_term(self.system, self.pty, None,
                                     self.system.block_setup_term)
            time.sleep(0.2)
            log.debug("CONNECT starts Expect Buffer ID={}".format(
                hex(id(self.pty))))
            return self.pty
        if rc == 1:
            self.pty.close()
            time.sleep(60)  # give things a minute to clear
            raise CommandFailed(
                'sol activate',
                "IPMI: pexpect.TIMEOUT while trying to establish"
                " connection, command was '{}'".format(cmd), -1)
        if rc == 2:
            self.pty.close()
            time.sleep(60)  # give things a minute to clear
            raise CommandFailed(
                'sol activate',
                "IPMI: insufficient resources for session, unable"
                " to establish IPMI v2 / RMCP+ session, command was '{}'".
                format(cmd), -1)

    def get_console(self, logger=None):
        if self.state == IPMIConsoleState.DISCONNECTED:
            self.connect(logger)

        count = 0
        while (not self.pty.isalive()):
            log.warning('# Reconnecting')
            if (count > 0):
                time.sleep(BMC_CONST.IPMI_SOL_ACTIVATE_TIME)
            self.connect()
            count += 1
            if count > 120:
                raise "IPMI: not able to get sol console"
        if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
            self.util.setup_term(self.system, self.pty, None,
                                 self.system.block_setup_term)

        return self.pty

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)
Beispiel #4
0
class OpTestSSH():
    def __init__(self,
                 host,
                 username,
                 password,
                 logfile=sys.stdout,
                 port=22,
                 prompt=None,
                 check_ssh_keys=False,
                 known_hosts_file=None,
                 block_setup_term=None,
                 delaybeforesend=None,
                 use_parent_logger=True):
        self.state = ConsoleState.DISCONNECTED
        self.host = host
        self.username = username
        self.password = password
        self.port = port
        self.logfile = logfile
        self.check_ssh_keys = check_ssh_keys
        self.known_hosts_file = known_hosts_file
        self.delaybeforesend = delaybeforesend
        self.system = None
        # OpTestUtil instance is NOT conf's
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.pty = None
        self.block_setup_term = block_setup_term  # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0  # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0  # flags the object to abandon setup_term operations, like when system off

        # ssh state tracking, reset on boot and state changes
        # ssh port 2200 console tracking not done on SSH object, its done on System object for the system console
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1
        self.use_parent_logger = use_parent_logger

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        if self.state == ConsoleState.DISCONNECTED:
            return
        try:
            self.pty.send("\r")
            self.pty.send('~.')
            close_rc = self.pty.expect([pexpect.TIMEOUT, pexpect.EOF],
                                       timeout=10)
            log.debug("CLOSE Expect Buffer ID={}".format(hex(id(self.pty))))
            rc_child = self.pty.close()
            exitCode = signalstatus = None
            if self.pty.status != -1:  # leaving here for debug
                if os.WIFEXITED(self.pty.status):
                    exitCode = os.WEXITSTATUS(self.pty.status)
                else:
                    signalstatus = os.WTERMSIG(self.pty.status)
            self.state = ConsoleState.DISCONNECTED
        except pexpect.ExceptionPexpect as e:
            self.state = ConsoleState.DISCONNECTED
            raise "SSH Console: failed to close ssh console"
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            pass

    def connect(self, logger=None):
        if self.state == ConsoleState.CONNECTED:
            rc_child = self.close()
            self.state = ConsoleState.DISCONNECTED
        else:
            self.util.clear_state(self)  # clear when coming in DISCONNECTED

        cmd = ("sshpass -p %s " % (self.password) + " ssh" +
               " -p %s" % str(self.port) + " -l %s %s" %
               (self.username, self.host) +
               " -o PubkeyAuthentication=no -o afstokenpassing=no")

        if not self.check_ssh_keys:
            cmd = (cmd + " -q" + " -o 'UserKnownHostsFile=/dev/null' " +
                   " -o 'StrictHostKeyChecking=no'")
        elif self.known_hosts_file:
            cmd = (cmd + " -o UserKnownHostsFile=" + self.known_hosts_file)

        # For multi threades SSH sessions use individual logger and file handlers per session.
        if logger:
            self.log = logger
        elif self.use_parent_logger:
            self.log = log
        else:
            self.log = OpTestLogger.optest_logger_glob.get_custom_logger(
                __name__)

        self.log.debug(cmd)

        try:
            self.pty = OPexpect.spawn(
                cmd,
                logfile=self.logfile,
                failure_callback=set_system_to_UNKNOWN_BAD,
                failure_callback_data=self.system)
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            raise CommandFailed("OPexepct.spawn encountered a problem", e, -1)

        self.state = ConsoleState.CONNECTED
        # set for bash, otherwise it takes the 24x80 default
        self.pty.setwinsize(1000, 1000)
        if self.delaybeforesend:
            self.pty.delaybeforesend = self.delaybeforesend
        self.pty.logfile_read = OpTestLogger.FileLikeLogger(self.log)
        time.sleep(
            2
        )  # delay here in case messages like afstokenpassing unsupported show up which mess up setup_term
        self.check_set_term()
        log.debug("CONNECT starts Expect Buffer ID={}".format(hex(id(
            self.pty))))
        return self.pty

    def check_set_term(self):
        if self.block_setup_term is not None:
            setup_term_flag = self.block_setup_term  # caller control
        else:
            setup_term_flag = self.system.block_setup_term  # system defined control
        if self.port == 2200:
            if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
                self.util.setup_term(self.system, self.pty, None,
                                     setup_term_flag)
        else:
            if self.SUDO_set != 1 or self.LOGIN_set != 1 or self.PS1_set != 1:
                self.util.setup_term(self.system, self.pty, self,
                                     setup_term_flag)

    def get_console(self, logger=None):
        if self.state == ConsoleState.DISCONNECTED:
            self.connect(logger)
            if self.pty.isalive():
                # connect() will have already setup term
                return self.pty

        count = 0
        while (not self.pty.isalive()):
            self.log.info('# Reconnecting')
            if (count > 0):
                time.sleep(1)
            self.connect()
            count += 1
            if count > 120:
                raise "SSH: not able to get console"

        self.check_set_term()

        return self.pty

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)
class OpTestSSH():
    def __init__(self, host, username, password, logfile=sys.stdout, port=22,
            prompt=None, check_ssh_keys=False, known_hosts_file=None,
            block_setup_term=None, delaybeforesend=None, use_parent_logger=True):
        self.state = ConsoleState.DISCONNECTED
        self.host = host
        self.username = username
        self.password = password
        self.port = port
        self.logfile = logfile
        self.check_ssh_keys=check_ssh_keys
        self.known_hosts_file=known_hosts_file
        self.delaybeforesend = delaybeforesend
        self.system = None
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.pty = None
        self.block_setup_term = block_setup_term # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0 # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0 # flags the object to abandon setup_term operations, like when system off

        # ssh state tracking, reset on boot and state changes
        # ssh port 2200 console tracking not done on SSH object, its done on System object for the system console
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1
        self.use_parent_logger = use_parent_logger

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        if self.state == ConsoleState.DISCONNECTED:
            return
        try:
            self.pty.send("\r")
            self.pty.send('~.')
            close_rc = self.pty.expect([pexpect.TIMEOUT, pexpect.EOF], timeout=10)
            rc_child = self.pty.close()
            exitCode = signalstatus = None
            if self.pty.status != -1: # leaving here for debug
              if os.WIFEXITED(self.pty.status):
                exitCode = os.WEXITSTATUS(self.pty.status)
              else:
                signalstatus = os.WTERMSIG(self.pty.status)
            self.state = ConsoleState.DISCONNECTED
        except pexpect.ExceptionPexpect as e:
            self.state = ConsoleState.DISCONNECTED
            raise "SSH Console: failed to close ssh console"
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            pass

    def connect(self):
        if self.state == ConsoleState.CONNECTED:
            rc_child = self.close()
            self.state = ConsoleState.DISCONNECTED
        else:
            self.util.clear_state(self) # clear when coming in DISCONNECTED

        cmd = ("sshpass -p %s " % (self.password)
               + " ssh"
               + " -p %s" % str(self.port)
               + " -l %s %s" % (self.username, self.host)
               + " -o PubkeyAuthentication=no -o afstokenpassing=no"
               )

        if not self.check_ssh_keys:
            cmd = (cmd
                    + " -q"
                    + " -o 'UserKnownHostsFile=/dev/null' "
                    + " -o 'StrictHostKeyChecking=no'"
                    )
        elif self.known_hosts_file:
            cmd = (cmd + " -o UserKnownHostsFile=" + self.known_hosts_file)

        # For multi threades SSH sessions use individual logger and file handlers per session.
        if self.use_parent_logger:
            self.log = log
        else:
            self.log = OpTestLogger.optest_logger_glob.get_custom_logger(__name__)

        self.log.debug(cmd)

        try:
          self.pty = OPexpect.spawn(cmd,
                                    logfile=self.logfile,
                failure_callback=set_system_to_UNKNOWN_BAD,
                failure_callback_data=self.system)
        except Exception as e:
          self.state = ConsoleState.DISCONNECTED
          raise CommandFailed('OPexepct.spawn encountered a problem', -1)

        self.state = ConsoleState.CONNECTED
        # set for bash, otherwise it takes the 24x80 default
        self.pty.setwinsize(1000,1000)
        if self.delaybeforesend:
          self.pty.delaybeforesend = self.delaybeforesend
        self.pty.logfile_read = OpTestLogger.FileLikeLogger(log)
        time.sleep(2) # delay here in case messages like afstokenpassing unsupported show up which mess up setup_term
        self.check_set_term()
        return self.pty

    def check_set_term(self):
        if self.block_setup_term is not None:
          setup_term_flag = self.block_setup_term # caller control
        else:
          setup_term_flag = self.system.block_setup_term # system defined control
        if self.port == 2200:
          if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set !=1:
            self.util.setup_term(self.system, self.pty, None, setup_term_flag)
        else:
          if self.SUDO_set != 1 or self.LOGIN_set != 1 or self.PS1_set !=1:
            self.util.setup_term(self.system, self.pty, self, setup_term_flag)

    def get_console(self):
        if self.state == ConsoleState.DISCONNECTED:
          self.connect()

        count = 0
        while (not self.pty.isalive()):
            self.log.info('# Reconnecting')
            if (count > 0):
                time.sleep(1)
            self.connect()
            count += 1
            if count > 120:
                raise "SSH: not able to get console"

        self.check_set_term()

        return self.pty

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)
class IPMIConsole():
    def __init__(self, ipmitool=None, logfile=sys.stdout, prompt=None,
            block_setup_term=None, delaybeforesend=None):
        self.ipmitool = ipmitool
        self.state = IPMIConsoleState.DISCONNECTED
        self.delaybeforesend = delaybeforesend
        self.system = None
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.pty = None
        self.delaybeforesend = delaybeforesend
        self.block_setup_term = block_setup_term # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0 # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0 # flags the object to abandon setup_term operations, like when system off

        # FUTURE - System Console currently tracked in System Object
        # state tracking, reset on boot and state changes
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        if self.state == IPMIConsoleState.DISCONNECTED:
            return
        try:
            self.pty.send("\r")
            self.pty.send('~.')
            close_rc = self.pty.expect(['[terminated ipmitool]', pexpect.TIMEOUT, pexpect.EOF], timeout=10)
            rc_child = self.pty.close()
            self.state = IPMIConsoleState.DISCONNECTED
            exitCode = signalstatus = None
            if self.pty.status != -1: # leaving for future debug
              if os.WIFEXITED(self.pty.status):
                exitCode = os.WEXITSTATUS(self.pty.status)
              else:
                signalstatus = os.WTERMSIG(self.pty.status)
        except pexpect.ExceptionPexpect:
            self.state = IPMIConsoleState.DISCONNECTED
            raise OpTestError("IPMI: failed to close ipmi console")
        except Exception as e:
            self.state = IPMIConsoleState.DISCONNECTED
            pass

    def connect(self):
        if self.state == IPMIConsoleState.CONNECTED:
          rc_child = self.close()
        else:
          self.util.clear_state(self)

        try:
            self.ipmitool.run('sol deactivate')
        except OpTestError:
            log.info('SOL already deactivated')

        cmd = self.ipmitool.binary_name() + self.ipmitool.arguments() + ' sol activate'
        try:
          self.pty = OPexpect.spawn(cmd,
                                  failure_callback=set_system_to_UNKNOWN_BAD,
                                  failure_callback_data=self.system)
        except Exception as e:
          self.state = IPMIConsoleState.DISCONNECTED
          raise CommandFailed('OPexpect.spawn', "OPexpect.spawn encountered a problem, command was '{}'".format(cmd), -1)

        log.debug("#IPMI SOL CONNECT")
        self.state = IPMIConsoleState.CONNECTED
        self.pty.setwinsize(1000,1000)
        self.pty.logfile_read = OpTestLogger.FileLikeLogger(log)
        if self.delaybeforesend:
	    self.pty.delaybeforesend = self.delaybeforesend
        rc = self.pty.expect_exact(['[SOL Session operational.  Use ~? for help]', pexpect.TIMEOUT, pexpect.EOF], timeout=10)
        if rc == 0:
          if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set !=1:
            self.util.setup_term(self.system, self.pty, None, self.system.block_setup_term)
          time.sleep(0.2)
          return self.pty
        if rc == 1:
          self.pty.close()
          time.sleep(60) # give things a minute to clear
          raise CommandFailed('sol activate',
            "IPMI: pexpect.TIMEOUT while trying to establish"
            " connection, command was '{}'"
            .format(cmd), -1)
        if rc == 2:
          self.pty.close()
          time.sleep(60) # give things a minute to clear
          raise CommandFailed('sol activate',
            "IPMI: insufficient resources for session, unable"
            " to establish IPMI v2 / RMCP+ session, command was '{}'"
            .format(cmd), -1)

    def get_console(self):
        if self.state == IPMIConsoleState.DISCONNECTED:
            self.connect()

        count = 0
        while (not self.pty.isalive()):
            log.warning('# Reconnecting')
            if (count > 0):
                time.sleep(BMC_CONST.IPMI_SOL_ACTIVATE_TIME)
            self.connect()
            count += 1
            if count > 120:
                raise "IPMI: not able to get sol console"
        if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set !=1:
          self.util.setup_term(self.system, self.pty, None, self.system.block_setup_term)

        return self.pty

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)
Beispiel #7
0
class QemuConsole():
    """
    A 'connection' to the Qemu Console involves *launching* qemu.
    Closing a connection will *terminate* the qemu process.
    """
    def __init__(self,
                 qemu_binary=None,
                 skiboot=None,
                 prompt=None,
                 kernel=None,
                 initramfs=None,
                 block_setup_term=None,
                 delaybeforesend=None,
                 logfile=sys.stdout,
                 hda=None,
                 cdrom=None):
        self.qemu_binary = qemu_binary
        self.skiboot = skiboot
        self.kernel = kernel
        self.initramfs = initramfs
        self.hda = hda
        self.state = ConsoleState.DISCONNECTED
        self.logfile = logfile
        self.delaybeforesend = delaybeforesend
        self.system = None
        self.cdrom = cdrom
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.sol = None
        self.console = None
        self.block_setup_term = block_setup_term  # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0  # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0  # flags the object to abandon setup_term operations, like when system off

        # state tracking, reset on boot and state changes
        # console tracking done on System object for the system console
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        try:
            rc_child = self.sol.close()
            exitCode = signalstatus = None
            if self.sol.status != -1:  # leaving for debug
                if os.WIFEXITED(self.sol.status):
                    exitCode = os.WEXITSTATUS(self.sol.status)
                else:
                    signalstatus = os.WTERMSIG(self.sol.status)
            self.state = ConsoleState.DISCONNECTED
        except pexpect.ExceptionPexpect as e:
            self.state = ConsoleState.DISCONNECTED
            raise "Qemu Console: failed to close console"
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            pass
        print "Qemu close -> TERMINATE"

    def connect(self):
        if self.state == ConsoleState.CONNECTED:
            return self.sol
        else:
            self.util.clear_state(self)  # clear when coming in DISCONNECTED

        print "#Qemu Console CONNECT"

        cmd = ("%s" % (self.qemu_binary) + " -machine powernv -m 4G" +
               " -nographic -nodefaults" + " -bios %s" % (self.skiboot) +
               " -kernel %s" % (self.kernel))
        if self.initramfs is not None:
            cmd = cmd + " -initrd %s" % (self.initramfs)
        if self.hda is not None:
            cmd = cmd + " -hda %s" % (self.hda)
        if self.cdrom is not None:
            cmd = cmd + " -cdrom %s" % (self.cdrom)
        # typical host ip=10.0.2.2 and typical skiroot 10.0.2.15
        # use skiroot as the source, no sshd in skiroot
        cmd = cmd + " -nic user,model=virtio-net-pci"
        cmd = cmd + " -device ipmi-bmc-sim,id=bmc0 -device isa-ipmi-bt,bmc=bmc0,irq=10"
        cmd = cmd + " -serial none -device isa-serial,chardev=s1 -chardev stdio,id=s1,signal=off"
        print cmd
        try:
            solChild = OPexpect.spawn(cmd, logfile=self.logfile)
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            raise CommandFailed('OPexpect.spawn',
                                'OPexpect.spawn encountered a problem', -1)

        self.state = ConsoleState.CONNECTED
        solChild.setwinsize(1000, 1000)
        self.sol = solChild
        self.console = solChild
        if self.delaybeforesend:
            self.sol.delaybeforesend = self.delaybeforesend

        if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
            self.util.setup_term(self.system, self.sol, None,
                                 self.system.block_setup_term)

        time.sleep(0.2)
        return solChild

    def get_console(self):
        if self.state == ConsoleState.DISCONNECTED:
            self.util.clear_state(self)
            self.connect()

        count = 0
        while (not self.sol.isalive()):
            print '# Reconnecting'
            if (count > 0):
                time.sleep(20)
            self.connect()
            time.sleep(
                120
            )  # not sure on timing of this yet or how to validate qemu is up
            count += 1
            if count > 120:
                raise "IPMI: not able to get sol console"

        if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
            self.util.setup_term(self.system, self.sol, None,
                                 self.system.block_setup_term)

        return self.sol

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)
class MamboConsole():
    '''
    A 'connection' to the Mambo Console involves *launching* Mambo.
    Closing a connection will *terminate* the Mambo process.
    '''
    def __init__(self, mambo_binary=None,
            mambo_initial_run_script=None,
            mambo_autorun=None,
            skiboot=None,
            prompt=None,
            kernel=None,
            initramfs=None,
            block_setup_term=None,
            delaybeforesend=None,
            logfile=sys.stdout):
        self.mambo_binary = mambo_binary
        self.mambo_initial_run_script = mambo_initial_run_script
        self.mambo_autorun = mambo_autorun
        self.skiboot = skiboot
        self.kernel = kernel
        self.initramfs = initramfs
        self.state = ConsoleState.DISCONNECTED
        self.logfile = logfile
        self.delaybeforesend = delaybeforesend
        self.system = None
        # OpTestUtil instance is NOT conf's
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.pty = None
        self.block_setup_term = block_setup_term # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0 # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0 # flags the object to abandon setup_term operations, like when system off

        # state tracking, reset on boot and state changes
        # console tracking done on System object for the system console
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        try:
            rc_child = self.pty.close()
            exitCode = signalstatus = None
            if self.pty.status != -1: # leaving for debug
              if os.WIFEXITED(self.pty.status):
                exitCode = os.WEXITSTATUS(self.pty.status)
              else:
                signalstatus = os.WTERMSIG(self.pty.status)
            self.state = ConsoleState.DISCONNECTED
        except pexpect.ExceptionPexpect as e:
            self.state = ConsoleState.DISCONNECTED
            raise "Mambo Console: failed to close console"
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            pass
        log.debug("Mambo close -> TERMINATE")

    def connect(self):
        if self.state == ConsoleState.CONNECTED:
            return self.pty
        else:
            self.util.clear_state(self) # clear when coming in DISCONNECTED

        log.debug("#Mambo Console CONNECT")

        if not os.access(self.mambo_initial_run_script, os.R_OK|os.W_OK):
            raise ParameterCheck(message="Check that the file exists with"
                " R/W permissions mambo-initial-run-script={}"
                .format(self.mambo_initial_run_script))

        cmd = ("%s" % (self.mambo_binary)
               + " -e"
               + " -f {}".format(self.mambo_initial_run_script)
           )

        spawn_env = {}
        if self.skiboot:
            spawn_env['SKIBOOT'] = self.skiboot
        if self.kernel:
            spawn_env['SKIBOOT_ZIMAGE'] = self.kernel
        if self.initramfs:
            if not os.access(self.initramfs, os.R_OK|os.W_OK):
                raise ParameterCheck(message="Check that the file exists with"
                    " R/W permissions flash-initramfs={}"
                    .format(self.initramfs))
            spawn_env['SKIBOOT_INITRD'] = self.initramfs
        if self.mambo_autorun:
            spawn_env['SKIBOOT_AUTORUN'] = str(self.mambo_autorun)
        log.debug("OpTestMambo cmd={} mambo spawn_env={}".format(cmd, spawn_env))
        try:
          self.pty = OPexpect.spawn(cmd,
              logfile=self.logfile,
              env=spawn_env)
        except Exception as e:
          self.state = ConsoleState.DISCONNECTED
          raise CommandFailed('OPexpect.spawn',
                  'OPexpect.spawn encountered a problem: ' + str(e), -1)

        self.state = ConsoleState.CONNECTED
        self.pty.setwinsize(1000,1000)
        if self.delaybeforesend:
          self.pty.delaybeforesend = self.delaybeforesend

        if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
          self.util.setup_term(self.system, self.pty, None, self.system.block_setup_term)

        time.sleep(0.2)
        if not self.pty.isalive():
            raise CommandFailed(cmd, self.pty.read(), self.pty.status)
        return self.pty

    def get_console(self):
        if self.state == ConsoleState.DISCONNECTED:
            self.util.clear_state(self)
            self.connect()
        else:
            if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
                self.util.setup_term(self.system, self.pty, None, self.system.block_setup_term)

        return self.pty

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)

    def mambo_run_command(self, command, timeout=60, retry=0):
        return self.util.mambo_run_command(self, command, timeout, retry)

    def mambo_exit(self):
        return self.util.mambo_exit(self)

    def mambo_enter(self):
        return self.util.mambo_enter(self)
class QemuConsole():
    """
    A 'connection' to the Qemu Console involves *launching* qemu.
    Closing a connection will *terminate* the qemu process.
    """
    def __init__(self, qemu_binary=None, pnor=None, skiboot=None,
            prompt=None, kernel=None, initramfs=None,
            block_setup_term=None, delaybeforesend=None,
            logfile=sys.stdout, hda=None, cdrom=None):
        self.qemu_binary = qemu_binary
        self.pnor = pnor
        self.skiboot = skiboot
        self.kernel = kernel
        self.initramfs = initramfs
        self.hda = hda
        self.state = ConsoleState.DISCONNECTED
        self.logfile = logfile
        self.delaybeforesend = delaybeforesend
        self.system = None
        self.cdrom = cdrom
        # OpTestUtil instance is NOT conf's
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.pty = None
        self.block_setup_term = block_setup_term # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0 # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0 # flags the object to abandon setup_term operations, like when system off

        # state tracking, reset on boot and state changes
        # console tracking done on System object for the system console
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        try:
            rc_child = self.pty.close()
            exitCode = signalstatus = None
            if self.pty.status != -1: # leaving for debug
              if os.WIFEXITED(self.pty.status):
                exitCode = os.WEXITSTATUS(self.pty.status)
              else:
                signalstatus = os.WTERMSIG(self.pty.status)
            self.state = ConsoleState.DISCONNECTED
        except pexpect.ExceptionPexpect as e:
            self.state = ConsoleState.DISCONNECTED
            raise "Qemu Console: failed to close console"
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            pass
        log.debug("Qemu close -> TERMINATE")

    def connect(self):
        if self.state == ConsoleState.CONNECTED:
            return self.pty
        else:
            self.util.clear_state(self) # clear when coming in DISCONNECTED

        log.debug("#Qemu Console CONNECT")

        cmd = ("%s" % (self.qemu_binary)
               + " -machine powernv -m 4G"
               + " -nographic -nodefaults"
           )
        if self.pnor:
            cmd = cmd + " -drive file={},format=raw,if=mtd".format(self.pnor)
        if self.skiboot:
            cmd = cmd + " -bios %s" % (self.skiboot)
        if self.kernel:
            cmd = cmd + " -kernel %s" % (self.kernel)
            if self.initramfs is not None:
                cmd = cmd + " -initrd %s" % (self.initramfs)

        if self.hda is not None:
            # Put the disk on the first PHB
            cmd = (cmd
                    + " -drive file={},id=disk01,if=none".format(self.hda)
                    + " -device virtio-blk-pci,drive=disk01,id=virtio01,bus=pcie.0,addr=0"
                )
        if self.cdrom is not None:
            # Put the CDROM on the second PHB
            cmd = (cmd
                    + " -drive file={},id=cdrom01,if=none,media=cdrom".format(self.cdrom)
                    + " -device virtio-blk-pci,drive=cdrom01,id=virtio02,bus=pcie.1,addr=0"
                )
        # typical host ip=10.0.2.2 and typical skiroot 10.0.2.15
        # use skiroot as the source, no sshd in skiroot
        fru_path = os.path.join(OpTestConfiguration.conf.basedir, "test_binaries", "qemu_fru")
        cmd = cmd + " -nic user,model=virtio-net-pci"
        cmd = cmd + " -device ipmi-bmc-sim,id=bmc0,frudatafile=" + fru_path + " -device isa-ipmi-bt,bmc=bmc0,irq=10"
        cmd = cmd + " -serial none -device isa-serial,chardev=s1 -chardev stdio,id=s1,signal=off"
        print(cmd)
        try:
          self.pty = OPexpect.spawn(cmd,logfile=self.logfile)
        except Exception as e:
          self.state = ConsoleState.DISCONNECTED
          raise CommandFailed('OPexpect.spawn',
                  'OPexpect.spawn encountered a problem: ' + str(e), -1)

        self.state = ConsoleState.CONNECTED
        self.pty.setwinsize(1000,1000)
        if self.delaybeforesend:
          self.pty.delaybeforesend = self.delaybeforesend

        if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
          self.util.setup_term(self.system, self.pty, None, self.system.block_setup_term)

        # Wait a moment for isalive() to read a correct value and then check
        # if the command has already exited. If it has then QEMU has most
        # likely encountered an error and there's no point proceeding.
        time.sleep(0.2)
        if not self.pty.isalive():
            raise CommandFailed(cmd, self.pty.read(), self.pty.status)
        return self.pty

    def get_console(self):
        if self.state == ConsoleState.DISCONNECTED:
            self.util.clear_state(self)
            self.connect()
        else:
            if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
                self.util.setup_term(self.system, self.pty, None, self.system.block_setup_term)

        return self.pty

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)
Beispiel #10
0
class OpTestSSH():
    def __init__(self,
                 host,
                 username,
                 password,
                 logfile=sys.stdout,
                 port=22,
                 prompt=None,
                 check_ssh_keys=False,
                 known_hosts_file=None,
                 block_setup_term=None,
                 delaybeforesend=None):
        self.state = ConsoleState.DISCONNECTED
        self.host = host
        self.username = username
        self.password = password
        self.port = port
        self.logfile = logfile
        self.check_ssh_keys = check_ssh_keys
        self.known_hosts_file = known_hosts_file
        self.delaybeforesend = delaybeforesend
        self.system = None
        self.util = OpTestUtil()
        self.prompt = prompt
        self.expect_prompt = self.util.build_prompt(prompt) + "$"
        self.console = None
        self.block_setup_term = block_setup_term  # allows caller specific control of when to block setup_term
        self.setup_term_quiet = 0  # tells setup_term to not throw exceptions, like when system off
        self.setup_term_disable = 0  # flags the object to abandon setup_term operations, like when system off

        # ssh state tracking, reset on boot and state changes
        # ssh port 2200 console tracking not done on SSH object, its done on System object for the system console
        self.PS1_set = -1
        self.LOGIN_set = -1
        self.SUDO_set = -1

    def set_system(self, system):
        self.system = system

    def set_system_setup_term(self, flag):
        self.system.block_setup_term = flag

    def get_system_setup_term(self):
        return self.system.block_setup_term

    def set_block_setup_term(self, flag):
        self.block_setup_term = flag

    def get_block_setup_term(self):
        return self.block_setup_term

    def enable_setup_term_quiet(self):
        self.setup_term_quiet = 1
        self.setup_term_disable = 0

    def disable_setup_term_quiet(self):
        self.setup_term_quiet = 0
        self.setup_term_disable = 0

    def close(self):
        self.util.clear_state(self)
        if self.state == ConsoleState.DISCONNECTED:
            return
        try:
            self.console.send("\r")
            self.console.send('~.')
            close_rc = self.console.expect([pexpect.TIMEOUT, pexpect.EOF],
                                           timeout=10)
            rc_child = self.console.close()
            exitCode = signalstatus = None
            if self.console.status != -1:  # leaving here for debug
                if os.WIFEXITED(self.console.status):
                    exitCode = os.WEXITSTATUS(self.console.status)
                else:
                    signalstatus = os.WTERMSIG(self.console.status)
            self.state = ConsoleState.DISCONNECTED
        except pexpect.ExceptionPexpect as e:
            self.state = ConsoleState.DISCONNECTED
            raise "SSH Console: failed to close ssh console"
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            pass

    def connect(self):
        if self.state == ConsoleState.CONNECTED:
            rc_child = self.close()
            self.state = ConsoleState.DISCONNECTED
        else:
            self.util.clear_state(self)  # clear when coming in DISCONNECTED

        cmd = ("sshpass -p %s " % (self.password) + " ssh" +
               " -p %s" % str(self.port) + " -l %s %s" %
               (self.username, self.host) +
               " -o PubkeyAuthentication=no -o afstokenpassing=no")

        if not self.check_ssh_keys:
            cmd = (cmd + " -q" + " -o 'UserKnownHostsFile=/dev/null' " +
                   " -o 'StrictHostKeyChecking=no'")
        elif self.known_hosts_file:
            cmd = (cmd + " -o UserKnownHostsFile=" + self.known_hosts_file)

        print cmd

        try:
            consoleChild = OPexpect.spawn(
                cmd,
                failure_callback=set_system_to_UNKNOWN_BAD,
                failure_callback_data=self.system)
        except Exception as e:
            self.state = ConsoleState.DISCONNECTED
            raise CommandFailed('OPexepct.spawn encountered a problem', -1)

        self.state = ConsoleState.CONNECTED
        # set for bash, otherwise it takes the 24x80 default
        consoleChild.setwinsize(1000, 1000)
        self.console = consoleChild
        if self.delaybeforesend:
            self.console.delaybeforesend = self.delaybeforesend
        # Users expecting "Host IPMI" will reference console.sol so make it available
        self.sol = self.console
        consoleChild.logfile_read = self.logfile
        time.sleep(
            2
        )  # delay here in case messages like afstokenpassing unsupported show up which mess up setup_term
        self.check_set_term()
        return consoleChild

    def check_set_term(self):
        if self.block_setup_term is not None:
            setup_term_flag = self.block_setup_term  # caller control
        else:
            setup_term_flag = self.system.block_setup_term  # system defined control
        if self.port == 2200:
            if self.system.SUDO_set != 1 or self.system.LOGIN_set != 1 or self.system.PS1_set != 1:
                self.util.setup_term(self.system, self.console, None,
                                     setup_term_flag)
        else:
            if self.SUDO_set != 1 or self.LOGIN_set != 1 or self.PS1_set != 1:
                self.util.setup_term(self.system, self.console, self,
                                     setup_term_flag)

    def get_console(self):
        if self.state == ConsoleState.DISCONNECTED:
            self.connect()

        count = 0
        while (not self.console.isalive()):
            print '# Reconnecting'
            if (count > 0):
                time.sleep(1)
            self.connect()
            count += 1
            if count > 120:
                raise "SSH: not able to get console"

        self.check_set_term()

        return self.console

    def run_command(self, command, timeout=60, retry=0):
        return self.util.run_command(self, command, timeout, retry)

    def run_command_ignore_fail(self, command, timeout=60, retry=0):
        return self.util.run_command_ignore_fail(self, command, timeout, retry)