buffet_config.py revision a2b3d9fee5ae16d22819168daa5d1e2df6e63e0d
1# Copyright 2015 The Chromium OS Authors. All rights reserved. 2# Use of this source code is governed by a BSD-style license that can be 3# found in the LICENSE file. 4 5import dbus 6import logging 7import random 8import string 9import time 10 11from autotest_lib.client.common_lib import error 12from autotest_lib.client.common_lib import utils 13from autotest_lib.client.common_lib.cros import dbus_send 14from autotest_lib.client.common_lib.cros.fake_device_server import oauth 15from autotest_lib.client.common_lib.cros.fake_device_server import server 16 17TEST_CONFIG_PATH = '/tmp/buffet.fake.conf' 18TEST_STATE_PATH = '/tmp/buffet.fake.state' 19 20SERVICE_NAME = 'org.chromium.Buffet' 21 22COMMAND_INTERFACE = 'org.chromium.Buffet.Command' 23MANAGER_INTERFACE = 'org.chromium.Buffet.Manager' 24MANAGER_OBJECT_PATH = '/org/chromium/Buffet/Manager' 25OBJECT_MANAGER_PATH = '/org/chromium/Buffet' 26 27MANAGER_PROPERTY_STATUS = 'Status' 28MANAGER_PROPERTY_DEVICE_ID = 'DeviceId' 29STATUS_UNCONFIGURED = 'unconfigured' 30STATUS_CONNECTING = 'connecting' 31STATUS_CONNECTED = 'connected' 32STATUS_INVALID_CREDENTIALS = 'invalid_credentials' 33 34TEST_MESSAGE = 'Hello world!' 35 36LOCAL_SERVER_PORT = server.PORT 37LOCAL_OAUTH_URL = 'http://localhost:%d/%s/' % (LOCAL_SERVER_PORT, 38 oauth.OAUTH_PATH) 39LOCAL_SERVICE_URL = 'http://localhost:%d/' % LOCAL_SERVER_PORT 40TEST_API_KEY = oauth.TEST_API_KEY 41 42def build_unique_device_name(): 43 """@return a test-unique name for a device.""" 44 RAND_CHARS = string.ascii_lowercase + string.digits 45 NUM_RAND_CHARS = 16 46 rand_token = ''.join([random.choice(RAND_CHARS) 47 for _ in range(NUM_RAND_CHARS)]) 48 name = 'CrOS_%s' % rand_token 49 logging.debug('Generated unique device name %s', name) 50 return name 51 52 53TEST_CONFIG = { 54 'client_id': 'this_is_my_client_id', 55 'client_secret': 'this_is_my_client_secret', 56 'api_key': TEST_API_KEY, 57 'oauth_url': LOCAL_OAUTH_URL, 58 'service_url': LOCAL_SERVICE_URL, 59 'model_id': 'AATST', 60 'wifi_bootstrapping_mode': 'off', 61 'gcd_bootstrapping_mode': 'off', 62 'monitor_timeout_seconds': 120, 63 'connect_timeout_seconds': 60, 64 'bootstrap_timeout_seconds': 300, 65 'name': build_unique_device_name() 66} 67 68 69def bool_to_flag(value): 70 """Converts boolean value into lowercase string 71 72 @param value: Boolean value. 73 @return lower case string: 'true' or 'false'. 74 75 """ 76 return ('%s' % value).lower() 77 78 79def format_options(options, separator): 80 """Format dictionary as key1=value1{separator}key2=value2{separator}.. 81 82 @param options: Dictionary with options. 83 @param separator: String to be used as separator between key=value strings. 84 @return formated string. 85 86 """ 87 return separator.join(['%s=%s' % (k, v) for (k, v) in options.iteritems()]) 88 89 90def naive_restart(host=None): 91 """Restart Buffet without configuring it in any way. 92 93 @param host: Host object if we're interested in a remote host. 94 95 """ 96 run = utils.run if host is None else host.run 97 run('stop buffet', ignore_status=True) 98 run('start buffet') 99 100 101 102class BuffetConfig(object): 103 """An object that knows how to restart buffet in various configurations.""" 104 105 def __init__(self, 106 log_verbosity=None, 107 test_definitions_dir=None, 108 enable_xmpp=False, 109 enable_ping=True, 110 disable_pairing_security=True, 111 device_whitelist=None, 112 options=None): 113 self.enable_xmpp = enable_xmpp 114 self.log_verbosity = log_verbosity 115 self.test_definitions_dir = test_definitions_dir 116 self.enable_ping = enable_ping 117 self.disable_pairing_security = disable_pairing_security 118 self.device_whitelist = device_whitelist 119 self.options = TEST_CONFIG.copy() 120 if options: 121 self.options.update(options) 122 123 124 def restart_with_config(self, 125 host=None, 126 timeout_seconds=10, 127 clean_state=True): 128 """Restart Buffet with this configuration. 129 130 @param host: Host object if we're interested in a remote host. 131 @param timeout_seconds: number of seconds to wait for Buffet to 132 come up. 133 @param clean_state: boolean True to remove all existing state. 134 135 """ 136 run = utils.run if host is None else host.run 137 run('stop buffet', ignore_status=True) 138 flags = { 139 'BUFFET_ENABLE_XMPP': 'true' if self.enable_xmpp else 'false', 140 'BUFFET_CONFIG_PATH': TEST_CONFIG_PATH, 141 'BUFFET_STATE_PATH': TEST_STATE_PATH, 142 'BUFFET_ENABLE_PING': bool_to_flag(self.enable_ping), 143 'BUFFET_DISABLE_SECURITY': 144 bool_to_flag(self.disable_pairing_security), 145 } 146 if self.log_verbosity: 147 flags['BUFFET_LOG_LEVEL'] = self.log_verbosity 148 149 # Go through this convoluted shell magic here because we need to 150 # create this file on both remote and local hosts (see how run() is 151 # defined). 152 run('cat <<EOF >%s\n%s\nEOF\n' % (TEST_CONFIG_PATH, 153 format_options(self.options, '\n'))) 154 155 if clean_state: 156 run('echo > %s' % TEST_STATE_PATH) 157 run('chown buffet:buffet %s' % TEST_STATE_PATH) 158 159 if self.test_definitions_dir: 160 flags['BUFFET_TEST_DEFINITIONS_PATH'] = self.test_definitions_dir 161 162 if self.device_whitelist: 163 flags['BUFFET_DEVICE_WHITELIST'] = ','.join(self.device_whitelist) 164 165 run('start buffet %s' % format_options(flags, ' ')) 166 start_time = time.time() 167 while time.time() - start_time < timeout_seconds: 168 result = dbus_send.dbus_send( 169 SERVICE_NAME, MANAGER_INTERFACE, MANAGER_OBJECT_PATH, 170 'TestMethod', args=[dbus.String(TEST_MESSAGE)], 171 host=host, tolerate_failures=True) 172 if result and result.response == TEST_MESSAGE: 173 return 174 time.sleep(0.5) 175 176 raise error.TestFail('Buffet failed to restart in time.') 177