# Copyright (c) 2012 The Chromium OS Authors. All rights reserved.
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.

import ctypes
import datetime
import logging
import multiprocessing
import os
import pexpect
import Queue
import re
import threading
import time

from config import rpm_config
import dli_urllib
import rpm_logging_config

import common
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib.cros import retry

RPM_CALL_TIMEOUT_MINS = rpm_config.getint('RPM_INFRASTRUCTURE',
                                          'call_timeout_mins')
SET_POWER_STATE_TIMEOUT_SECONDS = rpm_config.getint(
        'RPM_INFRASTRUCTURE', 'set_power_state_timeout_seconds')
PROCESS_TIMEOUT_BUFFER = 30


class RPMController(object):
    """
    This abstract class implements RPM request queueing and
    processes queued requests.

    The actual interaction with the RPM device will be implemented
    by the RPM specific subclasses.

    It assumes that you know the RPM hostname and that the device is on
    the specified RPM.

    This class also allows support for RPM devices that can be accessed
    directly or through a hydra serial concentrator device.

    Implementation details:
    This is an abstract class, subclasses must implement the methods
    listed here. You must not instantiate this class but should
    instantiate one of those leaf subclasses. Subclasses should
    also set TYPE class attribute to indicate device type.

    @var behind_hydra: boolean value to represent whether or not this RPM is
                        behind a hydra device.
    @var hostname: hostname for this rpm device.
    @var is_running_lock: lock used to control access to _running.
    @var request_queue: queue used to store requested outlet state changes.
    @var queue_lock: lock used to control access to request_queue.
    @var _running: boolean value to represent if this controller is currently
                   looping over queued requests.
    """


    SSH_LOGIN_CMD = ('ssh -l %s -o StrictHostKeyChecking=no '
                     '-o ConnectTimeout=90 -o UserKnownHostsFile=/dev/null %s')
    USERNAME_PROMPT = 'Username:'
    HYRDA_RETRY_SLEEP_SECS = 10
    HYDRA_MAX_CONNECT_RETRIES = 3
    LOGOUT_CMD = 'logout'
    CLI_CMD = 'CLI'
    CLI_HELD = 'The administrator \[root\] has an active .* session.'
    CLI_KILL_PREVIOUS = 'cancel'
    CLI_PROMPT = 'cli>'
    HYDRA_PROMPT = '#'
    PORT_STATUS_CMD = 'portStatus'
    QUIT_CMD = 'quit'
    SESSION_KILL_CMD_FORMAT = 'administration sessions kill %s'
    HYDRA_CONN_HELD_MSG_FORMAT = 'is being used'
    CYCLE_SLEEP_TIME = 5

    # Global Variables that will likely be changed by subclasses.
    DEVICE_PROMPT = '$'
    PASSWORD_PROMPT = 'Password:'
    # The state change command can be any string format but must accept 2 vars:
    # state followed by device/Plug name.
    SET_STATE_CMD = '%s %s'
    SUCCESS_MSG = None # Some RPM's may not return a success msg.

    NEW_STATE_ON = 'ON'
    NEW_STATE_OFF = 'OFF'
    NEW_STATE_CYCLE = 'CYCLE'
    TYPE = 'Should set TYPE in subclass.'


    def __init__(self, rpm_hostname, hydra_hostname=None):
        """
        RPMController Constructor.
        To be called by subclasses.

        @param rpm_hostname: hostname of rpm device to be controlled.
        """
        self._dns_zone = rpm_config.get('CROS', 'dns_zone')
        self.hostname = rpm_hostname
        self.request_queue = Queue.Queue()
        self._running = False
        self.is_running_lock = threading.Lock()
        # If a hydra name is provided by the subclass then we know we are
        # talking to an rpm behind a hydra device.
        self.hydra_hostname = hydra_hostname if hydra_hostname else None
        self.behind_hydra = hydra_hostname is not None


    def _start_processing_requests(self):
        """
        Check if there is a thread processing requests.
        If not start one.
        """
        with self.is_running_lock:
            if not self._running:
                self._running = True
                self._running_thread = threading.Thread(target=self._run)
                self._running_thread.start()


    def _stop_processing_requests(self):
        """
        Called if the request request_queue is empty.
        Set running status to false.
        """
        with self.is_running_lock:
            logging.debug('Request queue is empty. RPM Controller for %s'
                          ' is terminating.', self.hostname)
            self._running = False
        if not self.request_queue.empty():
            # This can occur if an item was pushed into the queue after we
            # exited the while-check and before the _stop_processing_requests
            # call was made. Therefore we need to start processing again.
            self._start_processing_requests()


    def _run(self):
        """
        Processes all queued up requests for this RPM Controller.
        Callers should first request_queue up atleast one request and if this
        RPM Controller is not running then call run.

        Caller can either simply call run but then they will be blocked or
        can instantiate a new thread to process all queued up requests.
        For example:
          threading.Thread(target=rpm_controller.run).start()

        Requests are in the format of:
          [powerunit_info, new_state, condition_var, result]
        Run will set the result with the correct value.
        """
        while not self.request_queue.empty():
            try:
                result = multiprocessing.Value(ctypes.c_bool, False)
                request = self.request_queue.get()
                device_hostname = request['powerunit_info'].device_hostname
                if (datetime.datetime.utcnow() > (request['start_time'] +
                        datetime.timedelta(minutes=RPM_CALL_TIMEOUT_MINS))):
                    logging.error('The request was waited for too long to be '
                                  "processed. It is timed out and won't be "
                                  'processed.')
                    request['result_queue'].put(False)
                    continue

                is_timeout = multiprocessing.Value(ctypes.c_bool, False)
                process = multiprocessing.Process(target=self._process_request,
                                                  args=(request, result,
                                                        is_timeout))
                process.start()
                process.join(SET_POWER_STATE_TIMEOUT_SECONDS +
                             PROCESS_TIMEOUT_BUFFER)
                if process.is_alive():
                    logging.debug('%s: process (%s) still running, will be '
                                  'terminated!', device_hostname, process.pid)
                    process.terminate()
                    is_timeout.value = True

                if is_timeout.value:
                    raise error.TimeoutException(
                            'Attempt to set power state is timed out after %s '
                            'seconds.' % SET_POWER_STATE_TIMEOUT_SECONDS)
                if not result.value:
                    logging.error('Request to change %s to state %s failed.',
                                  device_hostname, request['new_state'])
            except Exception as e:
                logging.error('Request to change %s to state %s failed: '
                              'Raised exception: %s', device_hostname,
                              request['new_state'], e)
                result.value = False

            # Put result inside the result Queue to allow the caller to resume.
            request['result_queue'].put(result.value)
        self._stop_processing_requests()


    def _process_request(self, request, result, is_timeout):
        """Process the request to change a device's outlet state.

        The call of set_power_state is made in a new running process. If it
        takes longer than SET_POWER_STATE_TIMEOUT_SECONDS, the request will be
        timed out.

        @param request: A request to change a device's outlet state.
        @param result: A Value object passed to the new process for the caller
                       thread to retrieve the result.
        @param is_timeout: A Value object passed to the new process for the
                           caller thread to retrieve the information about if
                           the set_power_state call timed out.
        """
        try:
            logging.getLogger().handlers = []
            is_timeout_value, result_value = retry.timeout(
                     rpm_logging_config.set_up_logging_to_server,
                     timeout_sec=10)
            if is_timeout_value:
                raise Exception('Setup local log server handler timed out.')
        except Exception as e:
            # Fail over to log to a new file.
            LOG_FILENAME_FORMAT = rpm_config.get('GENERAL',
                                                 'dispatcher_logname_format')
            log_filename_format = LOG_FILENAME_FORMAT.replace(
                    'dispatcher', 'controller_%d' % os.getpid())
            logging.getLogger().handlers = []
            rpm_logging_config.set_up_logging_to_file(
                    log_dir='./logs',
                    log_filename_format=log_filename_format,
                    use_log_server=False)
            logging.info('Failed to set up logging through log server: %s', e)
        kwargs = {'powerunit_info':request['powerunit_info'],
                  'new_state':request['new_state']}
        try:
            is_timeout_value, result_value = retry.timeout(
                    self.set_power_state,
                    args=(),
                    kwargs=kwargs,
                    timeout_sec=SET_POWER_STATE_TIMEOUT_SECONDS)
            result.value = result_value
            is_timeout.value = is_timeout_value
        except Exception as e:
            # This method runs in a subprocess. Must log the exception,
            # otherwise exceptions raised in set_power_state just get lost.
            # Need to convert e to a str type, because our logging server
            # code doesn't handle the conversion very well.
            logging.error('Request to change %s to state %s failed: '
                          'Raised exception: %s',
                          request['powerunit_info'].device_hostname,
                          request['new_state'], str(e))
            raise e


    def queue_request(self, powerunit_info, new_state):
        """
        Queues up a requested state change for a device's outlet.

        Requests are in the format of:
          [powerunit_info, new_state, condition_var, result]
        Run will set the result with the correct value.

        @param powerunit_info: And PowerUnitInfo instance.
        @param new_state: ON/OFF/CYCLE - state or action we want to perform on
                          the outlet.
        """
        request = {}
        request['powerunit_info'] = powerunit_info
        request['new_state'] = new_state
        request['start_time'] = datetime.datetime.utcnow()
        # Reserve a spot for the result to be stored.
        request['result_queue'] = Queue.Queue()
        # Place in request_queue
        self.request_queue.put(request)
        self._start_processing_requests()
        # Block until the request is processed.
        result = request['result_queue'].get(block=True)
        return result


    def _kill_previous_connection(self):
        """
        In case the port to the RPM through the hydra serial concentrator is in
        use, terminate the previous connection so we can log into the RPM.

        It logs into the hydra serial concentrator over ssh, launches the CLI
        command, gets the port number and then kills the current session.
        """
        ssh = self._authenticate_with_hydra(admin_override=True)
        if not ssh:
            return
        ssh.expect(RPMController.PASSWORD_PROMPT, timeout=60)
        ssh.sendline(rpm_config.get('HYDRA', 'admin_password'))
        ssh.expect(RPMController.HYDRA_PROMPT)
        ssh.sendline(RPMController.CLI_CMD)
        cli_prompt_re = re.compile(RPMController.CLI_PROMPT)
        cli_held_re = re.compile(RPMController.CLI_HELD)
        response = ssh.expect_list([cli_prompt_re, cli_held_re], timeout=60)
        if response == 1:
            # Need to kill the previous adminstator's session.
            logging.error("Need to disconnect previous administrator's CLI "
                          "session to release the connection to RPM device %s.",
                          self.hostname)
            ssh.sendline(RPMController.CLI_KILL_PREVIOUS)
            ssh.expect(RPMController.CLI_PROMPT)
        ssh.sendline(RPMController.PORT_STATUS_CMD)
        ssh.expect(': %s' % self.hostname)
        ports_status = ssh.before
        port_number = ports_status.split(' ')[-1]
        ssh.expect(RPMController.CLI_PROMPT)
        ssh.sendline(RPMController.SESSION_KILL_CMD_FORMAT % port_number)
        ssh.expect(RPMController.CLI_PROMPT)
        self._logout(ssh, admin_logout=True)


    def _hydra_login(self, ssh):
        """
        Perform the extra steps required to log into a hydra serial
        concentrator.

        @param ssh: pexpect.spawn object used to communicate with the hydra
                    serial concentrator.

        @return: True if the login procedure is successful. False if an error
                 occurred. The most common case would be if another user is
                 logged into the device.
        """
        try:
            response = ssh.expect_list(
                    [re.compile(RPMController.PASSWORD_PROMPT),
                     re.compile(RPMController.HYDRA_CONN_HELD_MSG_FORMAT)],
                    timeout=15)
        except pexpect.TIMEOUT:
            # If there was a timeout, this ssh tunnel could be set up to
            # not require the hydra password.
            ssh.sendline('')
            try:
                ssh.expect(re.compile(RPMController.USERNAME_PROMPT))
                logging.debug('Connected to rpm through hydra. Logging in.')
                return True
            except pexpect.ExceptionPexpect:
                return False
        if response == 0:
            try:
                ssh.sendline(rpm_config.get('HYDRA','password'))
                ssh.sendline('')
                response = ssh.expect_list(
                        [re.compile(RPMController.USERNAME_PROMPT),
                         re.compile(RPMController.HYDRA_CONN_HELD_MSG_FORMAT)],
                        timeout=60)
            except pexpect.EOF:
                # Did not receive any of the expect responses, retry.
                return False
            except pexpect.TIMEOUT:
                logging.debug('Timeout occurred logging in to hydra.')
                return False
        # Send the username that the subclass will have set in its
        # construction.
        if response == 1:
            logging.debug('SSH Terminal most likely serving another'
                          ' connection, retrying.')
            # Kill the connection for the next connection attempt.
            try:
                self._kill_previous_connection()
            except pexpect.ExceptionPexpect:
                logging.error('Failed to disconnect previous connection, '
                              'retrying.')
                raise
            return False
        logging.debug('Connected to rpm through hydra. Logging in.')
        return True


    def _authenticate_with_hydra(self, admin_override=False):
        """
        Some RPM's are behind a hydra serial concentrator and require their ssh
        connection to be tunneled through this device. This can fail if another
        user is logged in; therefore this will retry multiple times.

        This function also allows us to authenticate directly to the
        administrator interface of the hydra device.

        @param admin_override: Set to True if we are trying to access the
                               administrator interface rather than tunnel
                               through to the RPM.

        @return: The connected pexpect.spawn instance if the login procedure is
                 successful. None if an error occurred. The most common case
                 would be if another user is logged into the device.
        """
        if admin_override:
            username = rpm_config.get('HYDRA', 'admin_username')
        else:
            username = '%s:%s' % (rpm_config.get('HYDRA','username'),
                                  self.hostname)
        cmd = RPMController.SSH_LOGIN_CMD % (username, self.hydra_hostname)
        num_attempts = 0
        while num_attempts < RPMController.HYDRA_MAX_CONNECT_RETRIES:
            try:
                ssh = pexpect.spawn(cmd)
            except pexpect.ExceptionPexpect:
                return None
            if admin_override:
                return ssh
            if self._hydra_login(ssh):
                return ssh
            # Authenticating with hydra failed. Sleep then retry.
            time.sleep(RPMController.HYRDA_RETRY_SLEEP_SECS)
            num_attempts += 1
        logging.error('Failed to connect to the hydra serial concentrator after'
                      ' %d attempts.', RPMController.HYDRA_MAX_CONNECT_RETRIES)
        return None


    def _login(self):
        """
        Log in into the RPM Device.

        The login process should be able to connect to the device whether or not
        it is behind a hydra serial concentrator.

        @return: ssh - a pexpect.spawn instance if the connection was successful
                 or None if it was not.
        """
        if self.behind_hydra:
            # Tunnel the connection through the hydra.
            ssh = self._authenticate_with_hydra()
            if not ssh:
                return None
            ssh.sendline(self._username)
        else:
            # Connect directly to the RPM over SSH.
            hostname = '%s.%s' % (self.hostname, self._dns_zone)
            cmd = RPMController.SSH_LOGIN_CMD % (self._username, hostname)
            try:
                ssh = pexpect.spawn(cmd)
            except pexpect.ExceptionPexpect:
                return None
        # Wait for the password prompt
        try:
            ssh.expect(self.PASSWORD_PROMPT, timeout=60)
            ssh.sendline(self._password)
            ssh.expect(self.DEVICE_PROMPT, timeout=60)
        except pexpect.ExceptionPexpect:
            return None
        return ssh


    def _logout(self, ssh, admin_logout=False):
        """
        Log out of the RPM device.

        Send the device specific logout command and if the connection is through
        a hydra serial concentrator, kill the ssh connection.

        @param admin_logout: Set to True if we are trying to logout of the
                             administrator interface of a hydra serial
                             concentrator, rather than an RPM.
        @param ssh: pexpect.spawn instance to use to send the logout command.
        """
        if admin_logout:
            ssh.sendline(RPMController.QUIT_CMD)
            ssh.expect(RPMController.HYDRA_PROMPT)
        ssh.sendline(self.LOGOUT_CMD)
        if self.behind_hydra and not admin_logout:
            # Terminate the hydra session.
            ssh.sendline('~.')
            # Wait a bit so hydra disconnects completely. Launching another
            # request immediately can cause a timeout.
            time.sleep(5)


    def set_power_state(self, powerunit_info, new_state):
        """
        Set the state of the dut's outlet on this RPM.

        For ssh based devices, this will create the connection either directly
        or through a hydra tunnel and call the underlying _change_state function
        to be implemented by the subclass device.

        For non-ssh based devices, this method should be overloaded with the
        proper connection and state change code. And the subclass will handle
        accessing the RPM devices.

        @param powerunit_info: An instance of PowerUnitInfo.
        @param new_state: ON/OFF/CYCLE - state or action we want to perform on
                          the outlet.

        @return: True if the attempt to change power state was successful,
                 False otherwise.
        """
        ssh = self._login()
        if not ssh:
            return False
        if new_state == self.NEW_STATE_CYCLE:
            logging.debug('Beginning Power Cycle for device: %s',
                          powerunit_info.device_hostname)
            result = self._change_state(powerunit_info, self.NEW_STATE_OFF, ssh)
            if not result:
                return result
            time.sleep(RPMController.CYCLE_SLEEP_TIME)
            result = self._change_state(powerunit_info, self.NEW_STATE_ON, ssh)
        else:
            # Try to change the state of the device's power outlet.
            result = self._change_state(powerunit_info, new_state, ssh)

        # Terminate hydra connection if necessary.
        self._logout(ssh)
        ssh.close(force=True)
        return result


    def _change_state(self, powerunit_info, new_state, ssh):
        """
        Perform the actual state change operation.

        Once we have established communication with the RPM this method is
        responsible for changing the state of the RPM outlet.

        @param powerunit_info: An instance of PowerUnitInfo.
        @param new_state: ON/OFF - state or action we want to perform on
                          the outlet.
        @param ssh: The ssh connection used to execute the state change commands
                    on the RPM device.

        @return: True if the attempt to change power state was successful,
                 False otherwise.
        """
        outlet = powerunit_info.outlet
        device_hostname = powerunit_info.device_hostname
        if not outlet:
            logging.error('Request to change outlet for device: %s to new '
                          'state %s failed: outlet is unknown, please '
                          'make sure POWERUNIT_OUTLET exist in the host\'s '
                          'attributes in afe.', device_hostname, new_state)
        ssh.sendline(self.SET_STATE_CMD % (new_state, outlet))
        if self.SUCCESS_MSG:
            # If this RPM device returns a success message check for it before
            # continuing.
            try:
                ssh.expect(self.SUCCESS_MSG, timeout=60)
            except pexpect.ExceptionPexpect:
                logging.error('Request to change outlet for device: %s to new '
                              'state %s failed.', device_hostname, new_state)
                return False
        logging.debug('Outlet for device: %s set to %s', device_hostname,
                      new_state)
        return True


    def type(self):
        """
        Get the type of RPM device we are interacting with.
        Class attribute TYPE should be set by the subclasses.

        @return: string representation of RPM device type.
        """
        return self.TYPE


class SentryRPMController(RPMController):
    """
    This class implements power control for Sentry Switched CDU
    http://www.servertech.com/products/switched-pdus/

    Example usage:
      rpm = SentrySwitchedCDU('chromeos-rack1-rpm1')
      rpm.queue_request('chromeos-rack1-host1', 'ON')

    @var _username: username used to access device.
    @var _password: password used to access device.
    """


    DEVICE_PROMPT = 'Switched CDU:'
    SET_STATE_CMD = '%s %s'
    SUCCESS_MSG = 'Command successful'
    NUM_OF_OUTLETS = 17
    TYPE = 'Sentry'


    def __init__(self, hostname, hydra_hostname=None):
        super(SentryRPMController, self).__init__(hostname, hydra_hostname)
        self._username = rpm_config.get('SENTRY', 'username')
        self._password = rpm_config.get('SENTRY', 'password')


    def _setup_test_user(self, ssh):
        """Configure the test user for the RPM

        @param ssh: Pexpect object to use to configure the RPM.
        """
        # Create and configure the testing user profile.
        testing_user = rpm_config.get('SENTRY','testing_user')
        testing_password = rpm_config.get('SENTRY','testing_password')
        ssh.sendline('create user %s' % testing_user)
        response = ssh.expect_list([re.compile('not unique'),
                                    re.compile(self.PASSWORD_PROMPT)])
        if not response:
            return
        # Testing user is not set up yet.
        ssh.sendline(testing_password)
        ssh.expect('Verify Password:')
        ssh.sendline(testing_password)
        ssh.expect(self.SUCCESS_MSG)
        ssh.expect(self.DEVICE_PROMPT)
        ssh.sendline('add outlettouser all %s' % testing_user)
        ssh.expect(self.SUCCESS_MSG)
        ssh.expect(self.DEVICE_PROMPT)


    def _clear_outlet_names(self, ssh):
        """
        Before setting the outlet names, we need to clear out all the old
        names so there are no conflicts. For example trying to assign outlet
        2 a name already assigned to outlet 9.
        """
        for outlet in range(1, self.NUM_OF_OUTLETS):
            outlet_name = 'Outlet_%d' % outlet
            ssh.sendline(self.SET_OUTLET_NAME_CMD % (outlet, outlet_name))
            ssh.expect(self.SUCCESS_MSG)
            ssh.expect(self.DEVICE_PROMPT)


    def setup(self, outlet_naming_map):
        """
        Configure the RPM by adding the test user and setting up the outlet
        names.

        Note the rpm infrastructure does not rely on the outlet name to map a
        device to its outlet any more. We keep this method in case there is
        a need to label outlets for other reasons. We may deprecate
        this method if it has been proved the outlet names will not be used
        in any scenario.

        @param outlet_naming_map: Dictionary used to map the outlet numbers to
                                  host names. Keys must be ints. And names are
                                  in the format of 'hostX'.

        @return: True if setup completed successfully, False otherwise.
        """
        ssh = self._login()
        if not ssh:
            logging.error('Could not connect to %s.', self.hostname)
            return False
        try:
            self._setup_test_user(ssh)
            # Set up the outlet names.
            # Hosts have the same name format as the RPM hostname except they
            # end in hostX instead of rpmX.
            dut_name_format = re.sub('-rpm[0-9]*', '', self.hostname)
            if self.behind_hydra:
                # Remove "chromeosX" from DUTs behind the hydra due to a length
                # constraint on the names we can store inside the RPM.
                dut_name_format = re.sub('chromeos[0-9]*-', '', dut_name_format)
            dut_name_format = dut_name_format + '-%s'
            self._clear_outlet_names(ssh)
            for outlet, name in outlet_naming_map.items():
                dut_name = dut_name_format % name
                ssh.sendline(self.SET_OUTLET_NAME_CMD % (outlet, dut_name))
                ssh.expect(self.SUCCESS_MSG)
                ssh.expect(self.DEVICE_PROMPT)
        except pexpect.ExceptionPexpect as e:
            logging.error('Setup failed. %s', e)
            return False
        finally:
            self._logout(ssh)
        return True


class WebPoweredRPMController(RPMController):
    """
    This class implements RPMController for the Web Powered units
    produced by Digital Loggers Inc.

    @var _rpm: dli_urllib.Powerswitch instance used to interact with RPM.
    """


    TYPE = 'Webpowered'


    def __init__(self, hostname, powerswitch=None):
        username = rpm_config.get('WEBPOWERED', 'username')
        password = rpm_config.get('WEBPOWERED', 'password')
        # Call the constructor in RPMController. However since this is a web
        # accessible device, there should not be a need to tunnel through a
        # hydra serial concentrator.
        super(WebPoweredRPMController, self).__init__(hostname)
        self.hostname = '%s.%s' % (self.hostname, self._dns_zone)
        if not powerswitch:
            self._rpm = dli_urllib.Powerswitch(hostname=self.hostname,
                                               userid=username,
                                               password=password)
        else:
            # Should only be used in unit_testing
            self._rpm = powerswitch


    def _get_outlet_state(self, outlet):
        """
        Look up the state for a given outlet on the RPM.

        @param outlet: the outlet to look up.

        @return state: the outlet's current state.
        """
        status_list = self._rpm.statuslist()
        for outlet_name, hostname, state in status_list:
            if outlet_name == outlet:
                return state
        return None


    def set_power_state(self, powerunit_info, new_state):
        """
        Since this does not utilize SSH in any manner, this will overload the
        set_power_state in RPMController and completes all steps of changing
        the device's outlet state.
        """
        device_hostname = powerunit_info.device_hostname
        outlet = powerunit_info.outlet
        if not outlet:
            logging.error('Request to change outlet for device %s to '
                          'new state %s failed: outlet is unknown. Make sure '
                          'POWERUNIT_OUTLET exists in the host\'s '
                          'attributes in afe' , device_hostname, new_state)
            return False
        state = self._get_outlet_state(outlet)
        expected_state = new_state
        if new_state == self.NEW_STATE_CYCLE:
            logging.debug('Beginning Power Cycle for device: %s',
                          device_hostname)
            self._rpm.off(outlet)
            logging.debug('Outlet for device: %s set to OFF', device_hostname)
            # Pause for 5 seconds before restoring power.
            time.sleep(RPMController.CYCLE_SLEEP_TIME)
            self._rpm.on(outlet)
            logging.debug('Outlet for device: %s set to ON', device_hostname)
            expected_state = self.NEW_STATE_ON
        if new_state == self.NEW_STATE_OFF:
            self._rpm.off(outlet)
            logging.debug('Outlet for device: %s set to OFF', device_hostname)
        if new_state == self.NEW_STATE_ON:
            self._rpm.on(outlet)
            logging.debug('Outlet for device: %s set to ON', device_hostname)
        # Lookup the final state of the outlet
        return self._is_plug_state(powerunit_info, expected_state)


    def _is_plug_state(self, powerunit_info, expected_state):
        state = self._get_outlet_state(powerunit_info.outlet)
        if expected_state not in state:
            logging.error('Outlet for device: %s did not change to new state'
                          ' %s', powerunit_info.device_hostname, expected_state)
            return False
        return True


class CiscoPOEController(RPMController):
    """
    This class implements power control for Cisco POE switch.

    Example usage:
      poe = CiscoPOEController('chromeos1-poe-switch1')
      poe.queue_request('chromeos1-rack5-host12-servo', 'ON')
    """


    SSH_LOGIN_CMD = ('ssh -o StrictHostKeyChecking=no '
                     '-o UserKnownHostsFile=/dev/null %s')
    POE_USERNAME_PROMPT = 'User Name:'
    POE_PROMPT = '%s#'
    EXIT_CMD = 'exit'
    END_CMD = 'end'
    CONFIG = 'configure terminal'
    CONFIG_PROMPT = '%s\(config\)#'
    CONFIG_IF = 'interface %s'
    CONFIG_IF_PROMPT = '%s\(config-if\)#'
    SET_STATE_ON = 'power inline auto'
    SET_STATE_OFF = 'power inline never'
    CHECK_INTERFACE_STATE = 'show interface status %s'
    INTERFACE_STATE_MSG = 'Port\s+.*%s(\s+(\S+)){6,6}'
    CHECK_STATE_TIMEOUT = 60
    CMD_TIMEOUT = 30
    LOGIN_TIMEOUT = 60
    PORT_UP = 'Up'
    PORT_DOWN = 'Down'
    TYPE = 'CiscoPOE'


    def __init__(self, hostname):
        """
        Initialize controller class for a Cisco POE switch.

        @param hostname: the Cisco POE switch host name.
        """
        super(CiscoPOEController, self).__init__(hostname)
        self._username = rpm_config.get('CiscoPOE', 'username')
        self._password = rpm_config.get('CiscoPOE', 'password')
        # For a switch, e.g. 'chromeos2-poe-switch8',
        # the device prompt looks like 'chromeos2-poe-sw8#'.
        short_hostname = self.hostname.replace('switch', 'sw')
        self.poe_prompt = self.POE_PROMPT % short_hostname
        self.config_prompt = self.CONFIG_PROMPT % short_hostname
        self.config_if_prompt = self.CONFIG_IF_PROMPT % short_hostname


    def _login(self):
        """
        Log in into the Cisco POE switch.

        Overload _login in RPMController, as it always prompts for a user name.

        @return: ssh - a pexpect.spawn instance if the connection was successful
                 or None if it was not.
        """
        hostname = '%s.%s' % (self.hostname, self._dns_zone)
        cmd = self.SSH_LOGIN_CMD % (hostname)
        try:
            ssh = pexpect.spawn(cmd)
        except pexpect.ExceptionPexpect:
            logging.error('Could not connect to switch %s', hostname)
            return None
        # Wait for the username and password prompt.
        try:
            ssh.expect(self.POE_USERNAME_PROMPT, timeout=self.LOGIN_TIMEOUT)
            ssh.sendline(self._username)
            ssh.expect(self.PASSWORD_PROMPT, timeout=self.LOGIN_TIMEOUT)
            ssh.sendline(self._password)
            ssh.expect(self.poe_prompt, timeout=self.LOGIN_TIMEOUT)
        except pexpect.ExceptionPexpect:
            logging.error('Could not log into switch %s', hostname)
            return None
        return ssh


    def _enter_configuration_terminal(self, interface, ssh):
        """
        Enter configuration terminal of |interface|.

        This function expects that we've already logged into the switch
        and the ssh is prompting the switch name. The work flow is
            chromeos1-poe-sw1#
            chromeos1-poe-sw1#configure terminal
            chromeos1-poe-sw1(config)#interface fa36
            chromeos1-poe-sw1(config-if)#
        On success, the function exits with 'config-if' prompt.
        On failure, the function exits with device prompt,
        e.g. 'chromeos1-poe-sw1#' in the above case.

        @param interface: the name of the interface.
        @param ssh: pexpect.spawn instance to use.

        @return: True on success otherwise False.
        """
        try:
            # Enter configure terminal.
            ssh.sendline(self.CONFIG)
            ssh.expect(self.config_prompt, timeout=self.CMD_TIMEOUT)
            # Enter configure terminal of the interface.
            ssh.sendline(self.CONFIG_IF % interface)
            ssh.expect(self.config_if_prompt, timeout=self.CMD_TIMEOUT)
            return True
        except pexpect.ExceptionPexpect, e:
            ssh.sendline(self.END_CMD)
            logging.exception(e)
        return False


    def _exit_configuration_terminal(self, ssh):
        """
        Exit interface configuration terminal.

        On success, the function exits with device prompt,
        e.g. 'chromeos1-poe-sw1#' in the above case.
        On failure, the function exists with 'config-if' prompt.

        @param ssh: pexpect.spawn instance to use.

        @return: True on success otherwise False.
        """
        try:
            ssh.sendline(self.END_CMD)
            ssh.expect(self.poe_prompt, timeout=self.CMD_TIMEOUT)
            return True
        except pexpect.ExceptionPexpect, e:
            logging.exception(e)
        return False


    def _verify_state(self, interface, expected_state, ssh):
        """
        Check whehter the current state of |interface| matches expected state.

        This function tries to check the state of |interface| multiple
        times until its state matches the expected state or time is out.

        After the command of changing state has been executed,
        the state of an interface doesn't always change immediately to
        the expected state but requires some time. As such, we need
        a retry logic here.

        @param interface: the name of the interface.
        @param expect_state: the expected state, 'ON' or 'OFF'
        @param ssh: pexpect.spawn instance to use.

        @return: True if the state of |interface| swiches to |expected_state|,
                 otherwise False.
        """
        expected_state = (self.PORT_UP if expected_state == self.NEW_STATE_ON
                          else self.PORT_DOWN)
        try:
            start = time.time()
            while((time.time() - start) < self.CHECK_STATE_TIMEOUT):
                ssh.sendline(self.CHECK_INTERFACE_STATE % interface)
                state_matcher = '.*'.join([self.INTERFACE_STATE_MSG % interface,
                                           self.poe_prompt])
                ssh.expect(state_matcher, timeout=self.CMD_TIMEOUT)
                state = ssh.match.group(2)
                if state == expected_state:
                    return True
        except pexpect.ExceptionPexpect, e:
            logging.exception(e)
        return False


    def _logout(self, ssh, admin_logout=False):
        """
        Log out of the Cisco POE switch after changing state.

        Overload _logout in RPMController.

        @param admin_logout: ignored by this method.
        @param ssh: pexpect.spawn instance to use to send the logout command.
        """
        ssh.sendline(self.EXIT_CMD)


    def _change_state(self, powerunit_info, new_state, ssh):
        """
        Perform the actual state change operation.

        Overload _change_state in RPMController.

        @param powerunit_info: An PowerUnitInfo instance.
        @param new_state: ON/OFF - state or action we want to perform on
                          the outlet.
        @param ssh: The ssh connection used to execute the state change commands
                    on the POE switch.

        @return: True if the attempt to change power state was successful,
                 False otherwise.
        """
        interface = powerunit_info.outlet
        device_hostname = powerunit_info.device_hostname
        if not interface:
            logging.error('Could not change state: the interface on %s for %s '
                          'was not given.', self.hostname, device_hostname)
            return False

        # Enter configuration terminal.
        if not self._enter_configuration_terminal(interface, ssh):
            logging.error('Could not enter configuration terminal for %s',
                          interface)
            return False
        # Change the state.
        if new_state == self.NEW_STATE_ON:
            ssh.sendline(self.SET_STATE_ON)
        elif new_state == self.NEW_STATE_OFF:
            ssh.sendline(self.SET_STATE_OFF)
        else:
            logging.error('Unknown state request: %s', new_state)
            return False
        # Exit configuraiton terminal.
        if not self._exit_configuration_terminal(ssh):
            logging.error('Skipping verifying outlet state for device: %s, '
                          'because could not exit configuration terminal.',
                          device_hostname)
            return False
        # Verify if the state has changed successfully.
        if not self._verify_state(interface, new_state, ssh):
            logging.error('Could not verify state on interface %s', interface)
            return False

        logging.debug('Outlet for device: %s set to %s',
                      device_hostname, new_state)
        return True
