blob: 7b6a14209918af93a4b729401908a74aba4ece3e [file] [log] [blame]
# Copyright 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.
import dbus
import dbus.mainloop.glib
import time
from autotest_lib.client.common_lib import error
from autotest_lib.client.common_lib import utils
# DBus constants for use with peerd.
SERVICE_NAME = 'org.chromium.peerd'
DBUS_PATH_MANAGER = '/org/chromium/peerd/Manager'
DBUS_INTERFACE_MANAGER = 'org.chromium.peerd.Manager'
# Possible technologies for use with PeerdHelper.start_monitoring().
TECHNOLOGY_MDNS = 'm_dns'
TECHNOLOGY_WIFI_SSID = 'wifi_ssid'
TECHNOLOGY_BT_LE = 'bt_le'
TECHNOLOGY_BT = 'bt_classic'
TECHNOLOGY_ALL = 'all'
def make_helper(bus=None, start_instance=False, timeout_seconds=10,
verbosity_level=0):
"""Wait for peerd to come up, then return a PeerdHelper for it.
@param bus: DBus bus to use, or specify None to create one internally.
@param start_instance: bool True if we should start a peerd instance.
@param timeout_seconds: number of seconds to wait for peerd to come up.
@param verbosity_level: int level of log verbosity from peerd (e.g. 0
will log INFO level, 3 is verbosity level 3).
@return PeerdHelper instance if peerd comes up, None otherwise.
"""
pid_to_kill = None
if start_instance:
result = utils.run('peerd --v=%d & echo $!' % verbosity_level)
pid_to_kill = int(result.stdout)
else:
# TODO(wiley) Add a verbosity switch to peerd, call it here.
pass
if bus is None:
dbus.mainloop.glib.DBusGMainLoop(set_as_default=True)
bus = dbus.SystemBus()
end_time = time.time() + timeout_seconds
connection = None
while time.time() < end_time:
if not bus.name_has_owner(SERVICE_NAME):
time.sleep(0.2)
return PeerdHelper(bus, pid_to_kill)
raise error.TestFail('peerd did not start in a timely manner.')
class PeerdHelper(object):
"""Container for convenience methods related to peerd."""
def __init__(self, bus, peerd_pid_to_kill):
"""Construct a PeerdHelper.
@param bus: DBus bus to use, or specify None and this object will
create a mainloop and bus.
@param peerd_pid_to_kill: pid to kill on close() or None.
"""
self._bus = bus
self._pid = peerd_pid_to_kill
self._manager = dbus.Interface(
self._bus.get_object(SERVICE_NAME, DBUS_PATH_MANAGER),
DBUS_INTERFACE_MANAGER)
def close(self):
"""Clean up peerd state related to this helper.
Removes related services and monitoring requests.
Optionally kills the peerd instance if we created this instance.
"""
if self._pid is not None:
utils.run('kill %d' % self._pid)
self._pid = None
def start_monitoring(self, technologies):
"""Monitor the specified technologies.
Note that peerd will watch bus connections and stop monitoring a
technology if this bus connection goes away.A
@param technologies: iterable container of TECHNOLOGY_* defined above.
@return string monitoring_token for use with stop_monitoring().
"""
return self._manager.StartMonitoring(technologies)
def expose_service(self, service_id, service_info):
"""Expose a service via peerd.
Note that peerd should watch DBus connections and remove this service
if our bus connection ever goes down.
@param service_id: string id of service. See peerd documentation
for limitations on this string.
@param service_info: dict of string, string entries. See peerd
documentation for relevant restrictions.
@return string service token for use with remove_service().
"""
return self._manager.ExposeService(service_id, service_info)
def remove_service(self, service_token):
"""Remove a service previously added via expose_service().
@param service_token: string token returned by expose_service().
"""
self._manager.RemoveExposedService(service_token)