blob: 6bb0c76661aec10f419ca03ccf31c1818e189e72 [file] [log] [blame]
#!/usr/bin/python -u
# -*- coding: utf-8 -*-
#
# Copyright (c) 2014 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.
"""The main factory flow that runs the presenter-side of factory tests."""
import argparse
import logging
import syslog
import factory_common # pylint: disable=W0611
from cros.factory.goofy import test_environment
from cros.factory.goofy.goofy_base import GoofyBase
from cros.factory.goofy.link_manager import DUTLinkManager
from cros.factory.goofy.ui_app_controller import UIAppController
from cros.factory.test import factory
from cros.factory.utils import jsonrpc_utils
from cros.factory.utils import sys_utils
class GoofyPresenter(GoofyBase):
"""Presenter side of Goofy.
Note that all methods in this class must be invoked from the main
(event) thread. Other threads, such as callbacks and TestInvocation
methods, should instead post events on the run queue.
Properties:
link_manager: The DUTLinkManager for this invocation of Goofy.
ui_app_controller: UIAppController instance used to communicate with
UI presenter app.
dut_ips: The list of DUT ips.
dut_dongle_mac_address: The dictionary maping the ip address of DUT to
the dongle mac address of it.
"""
def __init__(self):
super(GoofyPresenter, self).__init__()
self.args = self.ParseOptions()
self.ui_app_controller = UIAppController(connect_hook=self.UIConnected)
self.dut_ips = []
self.dut_dongle_mac_address = {}
if sys_utils.InCrOSDevice():
self.env = test_environment.DUTEnvironment()
self.env.has_sockets = self.ui_app_controller.HasWebSockets
else:
self.env = test_environment.FakeChrootEnvironment()
self.env.launch_chrome()
self.link_manager = DUTLinkManager(
check_interval=1,
connect_hook=self.DUTConnected,
disconnect_hook=self.DUTDisconnected,
methods={'StartCountdown': self.UIAppCountdown,
'UpdateStatus': self.UpdateStatus},
standalone=self.args.standalone)
def ParseOptions(self):
parser = argparse.ArgumentParser(description='Run Goofy presenter')
parser.add_argument('--standalone', action='store_true',
help=('Assume the controller is running on the same '
'machines.'))
return parser.parse_args()
def RetryShowUI(self):
if not self.dut_ips:
return
dut_ip = self.dut_ips[-1]
if self.ui_app_controller.ShowUI(dut_ip,
self.dut_dongle_mac_address[dut_ip]):
return
# The UI is still not ready. Retry again.
self.run_enqueue(self.RetryShowUI)
def DUTConnected(self, dut_ip, dongle_mac_address):
self.dut_dongle_mac_address[dut_ip] = dongle_mac_address
self.dut_ips.append(dut_ip)
# If the UI web server is ready, show it.
if self.ui_app_controller.ShowUI(dut_ip, dongle_mac_address):
return
# Well, it's probably not. Let's schedule a retry.
self.run_enqueue(self.RetryShowUI)
def DUTDisconnected(self, dut_ip):
dongle_mac_address = self.dut_dongle_mac_address[dut_ip]
self.ui_app_controller.ShowDisconnectedScreen(dongle_mac_address)
self.dut_ips.remove(dut_ip)
del self.dut_dongle_mac_address[dut_ip]
def UIConnected(self):
if self.dut_ips:
dut_ip = self.dut_ips[-1]
self.ui_app_controller.ShowUI(dut_ip, self.dut_dongle_mac_address[dut_ip])
def UIAppCountdown(self, message, timeout_secs, timeout_message,
timeout_message_color):
"""Start countdown on the UI.
Args:
message: The text to show during countdown.
timeout_secs: The timeout for countdown.
timeout_message: The text to show when countdown eneds.
timeout_message_color: The color of the text when countdown ends.
"""
dut_ip = jsonrpc_utils.GetJSONRPCCallerIP()
dongle_mac_address = self.dut_dongle_mac_address[dut_ip]
self.ui_app_controller.StartCountdown(message,
dongle_mac_address,
timeout_secs,
timeout_message,
timeout_message_color)
def UpdateStatus(self, all_pass):
dut_ip = jsonrpc_utils.GetJSONRPCCallerIP()
dongle_mac_address = self.dut_dongle_mac_address[dut_ip]
self.ui_app_controller.UpdateStatus(dongle_mac_address, all_pass)
def main(self):
"""Entry point for goofy_presenter instance."""
syslog.openlog('goofy_presenter')
syslog.syslog('GoofyPresenter (factory test harness) starting')
self.link_manager.Start()
self.run()
def destroy(self):
"""Performs any shutdown tasks. Overrides base class method."""
self.link_manager.Stop()
self.ui_app_controller.Stop()
super(GoofyPresenter, self).destroy()
logging.info('Done destroying GoofyPresenter')
if __name__ == '__main__':
factory.init_logging()
GoofyPresenter.run_main_and_exit()