# Copyright 2015 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 logging
import random
import string
from autotest_lib.client.common_lib import utils
from autotest_lib.client.common_lib.cros.fake_device_server import oauth
from autotest_lib.client.common_lib.cros.fake_device_server import server
TEST_CONFIG_PATH = '/tmp/buffet.fake.conf'
TEST_STATE_PATH = '/tmp/buffet.fake.state'
LOCAL_SERVER_PORT = server.PORT
LOCAL_OAUTH_URL = 'http://localhost:%d/%s/' % (LOCAL_SERVER_PORT,
oauth.OAUTH_PATH)
LOCAL_SERVICE_URL = 'http://localhost:%d/' % LOCAL_SERVER_PORT
TEST_API_KEY = oauth.TEST_API_KEY
def build_unique_device_name():
"""@return a test-unique name for a device."""
RAND_CHARS = string.ascii_lowercase + string.digits
NUM_RAND_CHARS = 16
rand_token = ''.join([random.choice(RAND_CHARS)
for _ in range(NUM_RAND_CHARS)])
name = 'CrOS_%s' % rand_token
logging.debug('Generated unique device name %s', name)
return name
TEST_CONFIG = {
'client_id': 'this_is_my_client_id',
'client_secret': 'this_is_my_client_secret',
'api_key': TEST_API_KEY,
'oauth_url': LOCAL_OAUTH_URL,
'service_url': LOCAL_SERVICE_URL,
'model_id': 'AATST',
'wifi_auto_setup_enabled': 'false',
'name': build_unique_device_name()
}
def bool_to_flag(value):
"""Converts boolean value into lowercase string
@param value: Boolean value.
@return lower case string: 'true' or 'false'.
"""
return ('%s' % value).lower()
def format_options(options, separator):
"""Format dictionary as key1=value1{separator}key2=value2{separator}..
@param options: Dictionary with options.
@param separator: String to be used as separator between key=value strings.
@return formated string.
"""
return separator.join(['%s=%s' % (k, v) for (k, v) in options.iteritems()])
def naive_restart(host=None):
"""Restart Buffet without configuring it in any way.
@param host: Host object if we're interested in a remote host.
"""
run = utils.run if host is None else host.run
run('stop buffet', ignore_status=True)
run('start buffet')
class BuffetConfig(object):
"""An object that knows how to restart buffet in various configurations."""
def __init__(self,
log_verbosity=None,
test_definitions_dir=None,
enable_xmpp=False,
enable_ping=True,
disable_pairing_security=False,
device_whitelist=None,
options=None):
self.enable_xmpp = enable_xmpp
self.log_verbosity = log_verbosity
self.test_definitions_dir = test_definitions_dir
self.enable_ping = enable_ping
self.disable_pairing_security = disable_pairing_security
self.device_whitelist = device_whitelist
self.options = TEST_CONFIG.copy()
if options:
self.options.update(options)
def restart_with_config(self,
host=None,
clean_state=True):
"""Restart Buffet with this configuration.
@param host: Host object if we're interested in a remote host.
@param clean_state: boolean True to remove all existing state.
"""
run = utils.run if host is None else host.run
run('stop buffet', ignore_status=True)
flags = {
'BUFFET_ENABLE_XMPP': 'true' if self.enable_xmpp else 'false',
'BUFFET_CONFIG_PATH': TEST_CONFIG_PATH,
'BUFFET_STATE_PATH': TEST_STATE_PATH,
'BUFFET_ENABLE_PING': bool_to_flag(self.enable_ping),
'BUFFET_DISABLE_SECURITY':
bool_to_flag(self.disable_pairing_security),
}
if self.log_verbosity:
flags['BUFFET_LOG_LEVEL'] = self.log_verbosity
# Go through this convoluted shell magic here because we need to
# create this file on both remote and local hosts (see how run() is
# defined).
run('cat <<EOF >%s\n%s\nEOF\n' % (TEST_CONFIG_PATH,
format_options(self.options, '\n')))
if clean_state:
run('echo > %s' % TEST_STATE_PATH)
run('chown buffet:buffet %s' % TEST_STATE_PATH)
if self.test_definitions_dir:
flags['BUFFET_TEST_DEFINITIONS_PATH'] = self.test_definitions_dir
if self.device_whitelist:
flags['BUFFET_DEVICE_WHITELIST'] = ','.join(self.device_whitelist)
run('start buffet %s' % format_options(flags, ' '))