blob: 42ab51e9ce1bae3d6c722ace82f34fad567e4643 [file] [log] [blame]
Craig Harrison2b6c6fc2011-06-23 10:34:02 -07001# Copyright (c) 2011 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#
5# Expects to be run in an environment with sudo and no interactive password
6# prompt, such as within the Chromium OS development chroot.
7
Jon Salzc88e5b62011-11-30 14:38:54 +08008import logging, os, subprocess, time, xmlrpclib
9from autotest_lib.client.bin import utils as client_utils
10from autotest_lib.server import utils
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070011
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070012class Servo:
13 """Manages control of a Servo board.
14
15 Servo is a board developed by hardware group to aide in the debug and
16 control of various partner devices. Servo's features include the simulation
17 of pressing the power button, closing the lid, and pressing Ctrl-d. This
18 class manages setting up and communicating with a servo demon (servod)
19 process. It provides both high-level functions for common servo tasks and
20 low-level functions for directly setting and reading gpios.
21 """
22
23 _server = None
24 _servod = None
25
Chrome Bot9a1137d2011-07-19 14:35:00 -070026 # Power button press delays in seconds.
27 LONG_DELAY = 8
28 SHORT_DELAY = 0.1
29 NORMAL_TRANSITION_DELAY = 1.2
Todd Broch31c82502011-08-29 08:14:39 -070030 # Maximum number of times to re-read power button on release.
31 RELEASE_RETRY_MAX = 5
Chrome Bot9a1137d2011-07-19 14:35:00 -070032
33 # Delays to deal with computer transitions.
34 SLEEP_DELAY = 6
35 BOOT_DELAY = 10
Jon Salzc88e5b62011-11-30 14:38:54 +080036 RECOVERY_BOOT_DELAY = 30
37 RECOVERY_INSTALL_DELAY = 180
Chrome Bot9a1137d2011-07-19 14:35:00 -070038
39 # Servo-specific delays.
40 MAX_SERVO_STARTUP_DELAY = 10
41 SERVO_SEND_SIGNAL_DELAY = 0.5
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070042
Jon Salzc88e5b62011-11-30 14:38:54 +080043 # Time between an usb disk plugged-in and detected in the system.
44 USB_DETECTION_DELAY = 10
45
Tom Wai-Hong Tam5fc2c792011-11-03 13:05:39 +080046 def __init__(self, servo_host=None, servo_port=None,
47 xml_config=['servo.xml'], servo_vid=None, servo_pid=None,
48 servo_serial=None, cold_reset=False):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070049 """Sets up the servo communication infrastructure.
50
51 Args:
Todd Brochf24d2782011-08-19 10:55:41 -070052 servo_host: Host the servod process should listen on.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070053 servo_port: Port the servod process should listen on.
Tom Wai-Hong Tam5fc2c792011-11-03 13:05:39 +080054 xml_config: A list of configuration XML files for servod.
Todd Broch5fd6bc02011-07-20 15:53:37 -070055 servo_vid: USB vendor id of servo.
56 servo_pid: USB product id of servo.
57 servo_serial: USB serial id in device descriptor to host to
58 distinguish and control multiple servos. Note servo's EEPROM must
59 be programmed to use this feature.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070060 cold_reset: If True, cold reset device and boot during init,
61 otherwise perform init with device running.
62 """
63 # launch servod
Todd Brochf24d2782011-08-19 10:55:41 -070064 self._servod = None
Todd Broch5fd6bc02011-07-20 15:53:37 -070065
Todd Broch96d83aa2011-08-29 14:37:38 -070066 if not servo_port:
67 servo_port = 9999
68 # TODO(tbroch) In case where servo h/w is not connected to the host
69 # running the autotest server, servod will need to be launched by
70 # another means (udev likely). For now we can assume servo_host ==
71 # localhost as one hueristic way of determining this.
72 if not servo_host or servo_host == 'localhost':
73 servo_host = 'localhost'
74 self._launch_servod(servo_host, servo_port, xml_config, servo_vid,
75 servo_pid, servo_serial)
76 else:
77 logging.info('servod should already be running on host = %s',
78 servo_host)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070079
Chrome Bot9a1137d2011-07-19 14:35:00 -070080 self._do_cold_reset = cold_reset
Todd Brochf24d2782011-08-19 10:55:41 -070081 self._connect_servod(servo_host, servo_port)
Chrome Bot9a1137d2011-07-19 14:35:00 -070082
83
84 def initialize_dut(self):
85 """Initializes a dut for testing purposes."""
86 if self._do_cold_reset:
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070087 self._init_seq_cold_reset_devmode()
88 else:
89 self._init_seq()
90
91
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070092 def power_long_press(self):
Chrome Bot9a1137d2011-07-19 14:35:00 -070093 """Simulate a long power button press."""
94 self.power_key(Servo.LONG_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -070095
96
97 def power_normal_press(self):
Chrome Bot9a1137d2011-07-19 14:35:00 -070098 """Simulate a normal power button press."""
99 self.power_key()
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700100
101
102 def power_short_press(self):
Chrome Bot9a1137d2011-07-19 14:35:00 -0700103 """Simulate a short power button press."""
104 self.power_key(Servo.SHORT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700105
106
Chrome Bot9a1137d2011-07-19 14:35:00 -0700107 def power_key(self, secs=NORMAL_TRANSITION_DELAY):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700108 """Simulate a power button press.
109
110 Args:
111 secs: Time in seconds to simulate the keypress.
112 """
Craig Harrison6b36b122011-06-28 17:58:43 -0700113 self.set_nocheck('pwr_button', 'press')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700114 time.sleep(secs)
Todd Broch31c82502011-08-29 08:14:39 -0700115 self.set_nocheck('pwr_button', 'release')
116 # TODO(tbroch) Different systems have different release times on the
117 # power button that this loop addresses. Longer term we may want to
118 # make this delay platform specific.
119 retry = 1
120 while True:
121 value = self.get('pwr_button')
122 if value == 'release' or retry > Servo.RELEASE_RETRY_MAX:
123 break
124 logging.info('Waiting for pwr_button to release, retry %d.' % retry)
125 retry += 1
126 time.sleep(Servo.SHORT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700127
128
129 def lid_open(self):
130 """Simulate opening the lid."""
Craig Harrison48997262011-06-27 14:31:10 -0700131 self.set_nocheck('lid_open', 'yes')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700132
133
134 def lid_close(self):
Craig Harrison48997262011-06-27 14:31:10 -0700135 """Simulate closing the lid.
136
137 Waits 6 seconds to ensure the device is fully asleep before returning.
138 """
139 self.set_nocheck('lid_open', 'no')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700140 time.sleep(Servo.SLEEP_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700141
142
Todd Broch9dfc3a82011-11-01 08:09:28 -0700143 def _press_and_release_keys(self, m1, m2, press_secs=None):
144 """Simulate button presses."""
145 if press_secs is None:
146 press_secs = Servo.SERVO_SEND_SIGNAL_DELAY
147
148 self.set_nocheck('kbd_en', 'on')
149 self.set_nocheck('kbd_m1', m1)
150 self.set_nocheck('kbd_m2', m2)
151 time.sleep(press_secs)
152 self.set_nocheck('kbd_en', 'off')
153
154
Chrome Bot9a1137d2011-07-19 14:35:00 -0700155 def ctrl_d(self):
156 """Simulate Ctrl-d simultaneous button presses."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700157 self._press_and_release_keys('d', 'ctrl')
158
159
160 def d_key(self):
161 """Simulate Enter key button press."""
162 self._press_and_release_keys('d', 'none')
163
164
165 def ctrl_key(self):
166 """Simulate Enter key button press."""
167 self._press_and_release_keys('none', 'ctrl')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700168
169
Chrome Bot9a1137d2011-07-19 14:35:00 -0700170 def enter_key(self):
171 """Simulate Enter key button press."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700172 self._press_and_release_keys('enter', 'none')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700173
174
Chrome Bot9a1137d2011-07-19 14:35:00 -0700175 def refresh_key(self):
176 """Simulate Refresh key (F3) button press."""
Todd Broch9dfc3a82011-11-01 08:09:28 -0700177 self._press_and_release_keys('none', 'refresh')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700178
179
Chrome Bot9a1137d2011-07-19 14:35:00 -0700180 def imaginary_key(self):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700181 """Simulate imaginary key button press.
182
183 Maps to a key that doesn't physically exist.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700184 """
Todd Broch9dfc3a82011-11-01 08:09:28 -0700185 self._press_and_release_keys('none', 'unused')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700186
187
Craig Harrison6b36b122011-06-28 17:58:43 -0700188 def enable_recovery_mode(self):
189 """Enable recovery mode on device."""
190 self.set('rec_mode', 'on')
191
192
193 def disable_recovery_mode(self):
194 """Disable recovery mode on device."""
195 self.set('rec_mode', 'off')
196
197
198 def enable_development_mode(self):
199 """Enable development mode on device."""
200 self.set('dev_mode', 'on')
201
202
203 def disable_development_mode(self):
204 """Disable development mode on device."""
205 self.set('dev_mode', 'off')
206
Chris Sosa8ee1d592011-08-14 16:50:31 -0700207 def enable_usb_hub(self, host=False):
Craig Harrison86b1a572011-08-12 11:26:52 -0700208 """Enable Servo's USB/ethernet hub.
209
Chris Sosa8ee1d592011-08-14 16:50:31 -0700210 This is equivalent to plugging in the USB devices attached to Servo to
211 the host (if |host| is True) or dut (if |host| is False).
212 For host=False, requires that the USB out on the servo board is
213 connected to a USB in port on the target device. Servo's USB ports are
214 labeled DUT_HUB_USB1 and DUT_HUB_USB2. Servo's ethernet port is also
215 connected to this hub. Servo's USB port DUT_HUB_IN is the output of the
216 hub.
Craig Harrison86b1a572011-08-12 11:26:52 -0700217 """
218 self.set('dut_hub_pwren', 'on')
Chris Sosa8ee1d592011-08-14 16:50:31 -0700219 if host:
220 self.set('usb_mux_oe1', 'on')
221 self.set('usb_mux_sel1', 'servo_sees_usbkey')
222 else:
223 self.set('dut_hub_sel', 'dut_sees_hub')
224
Craig Harrison86b1a572011-08-12 11:26:52 -0700225 self.set('dut_hub_on', 'yes')
226
227
228 def disable_usb_hub(self):
229 """Disable Servo's USB/ethernet hub.
230
231 This is equivalent to unplugging the USB devices attached to Servo.
232 """
233 self.set('dut_hub_on', 'no')
234
235
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700236 def boot_devmode(self):
237 """Boot a dev-mode device that is powered off."""
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700238 self.power_normal_press()
Craig Harrison48997262011-06-27 14:31:10 -0700239 self.pass_devmode()
240
241
242 def pass_devmode(self):
243 """Pass through boot screens in dev-mode."""
Chrome Bot9a1137d2011-07-19 14:35:00 -0700244 time.sleep(Servo.BOOT_DELAY)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700245 self.ctrl_d()
Chrome Bot9a1137d2011-07-19 14:35:00 -0700246 time.sleep(Servo.BOOT_DELAY)
Craig Harrison48997262011-06-27 14:31:10 -0700247
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700248
Craig Harrison6b36b122011-06-28 17:58:43 -0700249 def cold_reset(self):
250 """Perform a cold reset of the EC.
251
Chris Sosa8ee1d592011-08-14 16:50:31 -0700252 Has the side effect of shutting off the device. Device is guaranteed
253 to be off at the end of this call.
Craig Harrison6b36b122011-06-28 17:58:43 -0700254 """
255 self.set('cold_reset', 'on')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700256 time.sleep(Servo.SERVO_SEND_SIGNAL_DELAY)
Craig Harrison6b36b122011-06-28 17:58:43 -0700257
258
259 def warm_reset(self):
260 """Perform a warm reset of the device.
261
262 Has the side effect of restarting the device.
263 """
264 self.set('warm_reset', 'on')
Chrome Bot9a1137d2011-07-19 14:35:00 -0700265 time.sleep(Servo.SERVO_SEND_SIGNAL_DELAY)
Craig Harrison6b36b122011-06-28 17:58:43 -0700266 self.set('warm_reset', 'off')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700267
268
269 def get(self, gpio_name):
270 """Get the value of a gpio from Servod."""
271 assert gpio_name
272 return self._server.get(gpio_name)
273
274
275 def set(self, gpio_name, gpio_value):
276 """Set and check the value of a gpio using Servod."""
Chrome Bot9a1137d2011-07-19 14:35:00 -0700277 self.set_nocheck(gpio_name, gpio_value)
278 assert gpio_value == self.get(gpio_name), \
279 'Servo failed to set %s to %s' % (gpio_name, gpio_value)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700280
281
282 def set_nocheck(self, gpio_name, gpio_value):
283 """Set the value of a gpio using Servod."""
284 assert gpio_name and gpio_value
Chrome Bot9a1137d2011-07-19 14:35:00 -0700285 logging.info('Setting %s to %s' % (gpio_name, gpio_value))
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700286 self._server.set(gpio_name, gpio_value)
287
288
Jon Salzc88e5b62011-11-30 14:38:54 +0800289 # TODO(waihong) It may fail if multiple servo's are connected to the same
290 # host. Should look for a better way, like the USB serial name, to identify
291 # the USB device.
292 def probe_host_usb_dev(self):
293 """Probe the USB disk device plugged-in the servo from the host side.
294
295 It tries to switch the USB mux to make the host unable to see the
296 USB disk and compares the result difference.
297
298 This only works if the servo is attached to the local host.
299
300 Returns:
301 A string of USB disk path, like '/dev/sdb', or None if not existed.
302 """
303 cmd = 'ls /dev/sd[a-z]'
304 original_value = self.get('usb_mux_sel1')
305
306 # Make the host unable to see the USB disk.
307 if original_value != 'dut_sees_usbkey':
308 self.set('usb_mux_sel1', 'dut_sees_usbkey')
309 time.sleep(self.USB_DETECTION_DELAY)
310 no_usb_set = set(utils.system_output(cmd, ignore_status=True).split())
311
312 # Make the host able to see the USB disk.
313 self.set('usb_mux_sel1', 'servo_sees_usbkey')
314 time.sleep(self.USB_DETECTION_DELAY)
315 has_usb_set = set(utils.system_output(cmd, ignore_status=True).split())
316
317 # Back to its original value.
318 if original_value != 'servo_sees_usbkey':
319 self.set('usb_mux_sel1', original_value)
320 time.sleep(self.USB_DETECTION_DELAY)
321
322 diff_set = has_usb_set - no_usb_set
323 if len(diff_set) == 1:
324 return diff_set.pop()
325 else:
326 return None
327
328
Tom Wai-Hong Tama07115e2012-01-09 12:27:01 +0800329 def install_recovery_image(self, image_path=None, usb_dev=None,
Jon Salzc88e5b62011-11-30 14:38:54 +0800330 wait_for_completion=True):
331 """Install the recovery image specied by the path onto the DUT.
332
333 This method uses google recovery mode to install a recovery image
334 onto a DUT through the use of a USB stick that is mounted on a servo
Tom Wai-Hong Tama07115e2012-01-09 12:27:01 +0800335 board specified by the usb_dev. If no image path is specified
Jon Salzc88e5b62011-11-30 14:38:54 +0800336 we use the recovery image already on the usb image.
337
338 Args:
339 image_path: Path on the host to the recovery image.
Tom Wai-Hong Tama07115e2012-01-09 12:27:01 +0800340 usb_dev: When servo_sees_usbkey is enabled, which dev
341 e.g. /dev/sdb will the usb key show up as.
342 If None, detects it automatically.
Jon Salzc88e5b62011-11-30 14:38:54 +0800343 wait_for_completion: Whether to wait for completion of the
344 factory install and disable the USB hub
345 before returning. Currently this is just
346 a hardcoded wait of RECOVERY_INSTALL_DELAY
347 (for the recovery process to complete).
348 """
349 # Set up Servo's usb mux.
350 self.set('prtctl4_pwren', 'on')
351 self.enable_usb_hub(host=True)
Tom Wai-Hong Tama07115e2012-01-09 12:27:01 +0800352 if image_path:
353 if not usb_dev:
354 usb_dev = self.probe_host_usb_dev()
355 logging.info('Installing image onto usb stick. '
356 'This takes a while...')
357 client_utils.poll_for_condition(
358 lambda: os.path.exists(usb_dev),
359 timeout=Servo.USB_DETECTION_DELAY,
360 desc="%s exists" % usb_dev)
361 utils.system(' '.join(
362 ['sudo', 'dd', 'if=%s' % image_path,
363 'of=%s' % usb_dev, 'bs=4M']))
Jon Salzc88e5b62011-11-30 14:38:54 +0800364
365 # Turn the device off.
366 self.power_normal_press()
367 time.sleep(Servo.SLEEP_DELAY)
368
369 # Boot in recovery mode.
370 try:
Jon Salzc88e5b62011-11-30 14:38:54 +0800371 self.enable_recovery_mode()
372 self.power_normal_press()
373 time.sleep(Servo.RECOVERY_BOOT_DELAY)
Tom Wai-Hong Tam922ed052012-01-09 12:27:52 +0800374 self.set('usb_mux_sel1', 'dut_sees_usbkey')
Jon Salzc88e5b62011-11-30 14:38:54 +0800375 self.disable_recovery_mode()
376
377 if wait_for_completion:
378 # Enable recovery installation.
379 logging.info('Running the recovery process on the DUT. '
380 'Waiting %d seconds for recovery to complete ...',
381 Servo.RECOVERY_INSTALL_DELAY)
382 time.sleep(Servo.RECOVERY_INSTALL_DELAY)
383
384 # Go back into normal mode and reboot.
385 # Machine automatically reboots after the usb key is removed.
386 logging.info('Removing the usb key from the DUT.')
387 self.disable_usb_hub()
388 time.sleep(Servo.BOOT_DELAY)
389 except:
390 # In case anything went wrong we want to make sure to do a clean
391 # reset.
392 self.disable_recovery_mode()
393 self.warm_reset()
394 raise
395
396
Craig Harrison6b36b122011-06-28 17:58:43 -0700397 def _init_seq_cold_reset_devmode(self):
398 """Cold reset, init device, and boot in dev-mode."""
399 self.cold_reset()
400 self._init_seq()
401 self.set('dev_mode', 'on')
402 self.boot_devmode()
403
404
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700405 def __del__(self):
406 """Kill the Servod process."""
Todd Brochf24d2782011-08-19 10:55:41 -0700407 if not self._servod:
408 return
409
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700410 # kill servod one way or another
411 try:
412 # won't work without superuser privileges
413 self._servod.terminate()
414 except:
415 # should work without superuser privileges
416 assert subprocess.call(['sudo', 'kill', str(self._servod.pid)])
417
418
Todd Brochf24d2782011-08-19 10:55:41 -0700419 def _launch_servod(self, servo_host, servo_port, xml_config, servo_vid,
420 servo_pid, servo_serial):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700421 """Launch the servod process.
422
423 Args:
Todd Brochf24d2782011-08-19 10:55:41 -0700424 servo_host: Host to start servod listening on.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700425 servo_port: Port to start servod listening on.
Tom Wai-Hong Tam5fc2c792011-11-03 13:05:39 +0800426 xml_config: A list of XML configuration files for servod.
Todd Broch5fd6bc02011-07-20 15:53:37 -0700427 servo_vid: USB vendor id of servo.
428 servo_pid: USB product id of servo.
429 servo_serial: USB serial id in device descriptor to host to
430 distinguish and control multiple servos. Note servo's EEPROM must
431 be programmed to use this feature.
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700432 """
Tom Wai-Hong Tam5fc2c792011-11-03 13:05:39 +0800433 cmdlist = ['sudo', 'servod']
434 for config in xml_config:
435 cmdlist += ['-c', str(config)]
Todd Broch96d83aa2011-08-29 14:37:38 -0700436 if servo_host is not None:
437 cmdlist.append('--host=%s' % str(servo_host))
438 if servo_port is not None:
439 cmdlist.append('--port=%s' % str(servo_port))
Todd Broch5fd6bc02011-07-20 15:53:37 -0700440 if servo_vid is not None:
Todd Brochf24d2782011-08-19 10:55:41 -0700441 cmdlist.append('--vendor=%s' % str(servo_vid))
Todd Broch5fd6bc02011-07-20 15:53:37 -0700442 if servo_pid is not None:
Todd Brochf24d2782011-08-19 10:55:41 -0700443 cmdlist.append('--product=%s' % str(servo_pid))
Todd Broch5fd6bc02011-07-20 15:53:37 -0700444 if servo_serial is not None:
Todd Brochf24d2782011-08-19 10:55:41 -0700445 cmdlist.append('--serialname=%s' % str(servo_serial))
Todd Broch5fd6bc02011-07-20 15:53:37 -0700446 logging.info('starting servod w/ cmd :: %s' % ' '.join(cmdlist))
447 self._servod = subprocess.Popen(cmdlist, 0, None, None, None,
448 subprocess.PIPE)
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700449 # wait for servod to initialize
Chrome Bot9a1137d2011-07-19 14:35:00 -0700450 timeout = Servo.MAX_SERVO_STARTUP_DELAY
451 while ('Listening' not in self._servod.stderr.readline() and
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700452 self._servod.returncode is None and timeout > 0):
453 time.sleep(1)
454 timeout -= 1
455 assert self._servod.returncode is None and timeout
456
457
458 def _init_seq(self):
459 """Initiate starting state for servo."""
460 self.set('tx_dir', 'input')
Todd Broch6ec29432011-12-19 14:32:02 -0800461 # TODO(tbroch) Investigate method to determine DUT's type so we can
462 # conditionally set lid if applicable
463 self.set_nocheck('lid_open', 'yes')
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700464 self.set('rec_mode', 'off')
465
466
Todd Brochf24d2782011-08-19 10:55:41 -0700467 def _connect_servod(self, servo_host, servo_port):
Craig Harrison2b6c6fc2011-06-23 10:34:02 -0700468 """Connect to the Servod process with XMLRPC.
469
470 Args:
471 servo_port: Port the Servod process is listening on.
472 """
Todd Brochf24d2782011-08-19 10:55:41 -0700473 remote = 'http://%s:%s' % (servo_host, servo_port)
Todd Broch96d83aa2011-08-29 14:37:38 -0700474 self._server = xmlrpclib.ServerProxy(remote)
Todd Brochf24d2782011-08-19 10:55:41 -0700475 try:
476 self._server.echo("ping-test")
Todd Broch96d83aa2011-08-29 14:37:38 -0700477 except:
478 logging.error('Connection to servod failed')
Todd Brochf24d2782011-08-19 10:55:41 -0700479 raise