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 dbus.service 7import logging 8import time 9 10from autotest_lib.client.cros.tendo import peerd_dbus_helper 11from autotest_lib.client.cros.tendo.n_faced_peerd import dbus_property_exposer 12from autotest_lib.client.cros.tendo.n_faced_peerd import service 13 14 15class Peer(dbus_property_exposer.DBusPropertyExposer): 16 """Represents local and remote peers.""" 17 18 def __init__(self, bus, path, peer_id, object_manager, is_self=False): 19 """Construct a org.chromium.peerd.Peer DBus object. 20 21 @param bus: dbus.Bus object to export this object on. 22 @param path: string object path to export this object at. 23 @param peer_id: string peerd peer ID; a UUID. 24 @param is_self: True iff this object will servce as a self peer. 25 @param object_manager: an instance of ObjectManager. 26 27 """ 28 super(Peer, self).__init__( 29 bus, path, peerd_dbus_helper.DBUS_INTERFACE_PEER) 30 # Fill in the initial values for our properties. 31 self.uuid = peer_id 32 self._is_self = is_self 33 self._update_last_seen() 34 # Register properties with the property exposer. 35 self.register_property(peerd_dbus_helper.PEER_PROPERTY_ID, 36 self._get_dbus_id) 37 self.register_property(peerd_dbus_helper.PEER_PROPERTY_LAST_SEEN, 38 self._get_dbus_last_seen) 39 # Claim our interace with the object manager. 40 self._object_manager = object_manager 41 self._path = path 42 self._object_manager.claim_interface( 43 path, peerd_dbus_helper.DBUS_INTERFACE_PEER, 44 self.property_getter) 45 # We need to keep a good bit of stuff around because we're responsible 46 # for creating child service objects. 47 self._bus = bus 48 self.services = dict() 49 self._services_counter = 0 50 51 52 def _get_dbus_id(self): 53 """Getter for PEER_PROPERTY_ID. 54 55 @return dbus.String containing our peer ID. 56 57 """ 58 return dbus.String(self.uuid) 59 60 61 def _get_dbus_last_seen(self): 62 """Getter for PEER_PROPERTY_LAST_SEEN. 63 64 @return dbus.UInt64 containing the last time this peer was seen 65 in milliseconds since the Unix epoc. 66 67 """ 68 return dbus.UInt64(int(1000 * self._last_seen_seconds)) 69 70 71 def _update_last_seen(self): 72 """Updates our last seen value. 73 74 This would be a simple call to time.time(), except that peerd 75 has to report a last seen time of 0 for the peer object representing 76 itself. 77 78 """ 79 if self._is_self: 80 self._last_seen_seconds = 0 81 else: 82 self._last_seen_seconds = time.time() 83 84 85 def close(self): 86 """Releases interfaces claimed over DBus.""" 87 # TODO(wiley) call close on child services. 88 raise NotImplementedError('Peer.close() does not work properly') 89 90 91 def update_service(self, service_id, service_info, ip_info): 92 """Update a service associated with this peer. 93 94 @param service_id: string peerd service ID. 95 @param service_info: dictionary of string,string items comprising 96 the metadata for the service. 97 @param ip_info: an instance of IpInfo defined in service.py. 98 99 """ 100 if service_id in self.services: 101 self.services[service_id].update(service_info, ip_info) 102 else: 103 self._services_counter += 1 104 service_path = '%s/services/%d' % (self._path, 105 self._services_counter) 106 self.services[service_id] = service.Service( 107 self._bus, service_path, self.uuid, service_id, 108 service_info, ip_info, self._object_manager) 109 logging.info('service=%s has info %r.', service_id, service_info) 110 self._update_last_seen() 111 self.on_property_changed(peerd_dbus_helper.PEER_PROPERTY_LAST_SEEN) 112 113 114 def remove_service(self, service_id): 115 """Remove a service associated with this peer. 116 117 @param service_id: string peerd service ID. 118 119 """ 120 removed_service = self.services.pop(service_id, None) 121 if removed_service is not None: 122 removed_service.close() 123 self._update_last_seen() 124 self.on_property_changed(peerd_dbus_helper.PEER_PROPERTY_LAST_SEEN) 125