def testEdefIOTypes(self): """ Tests the writing and parsing of an EndpointDescription bean with "complex" properties """ properties = { # Strings whitespaces are not well kept in XML "string": "some string just to see...", "int": 12, "float": 12.0, "tuple_str": ("a", "b", "c"), "tuple_int": (1, 2, 3), "tuple_float": (1.0, 2.0, 3.0), "list_str": ["a", "b", "c"], "list_int": [1, 2, 3], "list_float": [1.0, 2.0, 3.0], "set_str": set(["a", "b", "c"]), "set_int": set([1, 2, 3]), "set_float": set([1.0, 2.0, 3.0])} all_props = properties.copy() all_props[pelix.remote.PROP_ENDPOINT_ID] = 'toto' all_props[pelix.remote.PROP_IMPORTED_CONFIGS] = ['titi'] # Prepare an endpoint description with different property values endpoint = beans.EndpointDescription(self.svc_ref, all_props) # Write it & parse it xml_string = EDEFWriter().to_string([endpoint]) parsed = EDEFReader().parse(xml_string)[0] parsed_properties = parsed.get_properties() # Check values self.assertDictContainsSubset(endpoint.get_properties(), parsed_properties)
def testEdefStringReload(self): """ Tries to convert an EndpointDescription to its XML format (EDEF) and to reload this string """ original = beans.EndpointDescription( self.svc_ref, { pelix.remote.PROP_ENDPOINT_ID: "toto", pelix.remote.PROP_IMPORTED_CONFIGS: ['titi'], pelix.constants.OBJECTCLASS: "spec" }) # Write the endpoint to an XML string writer = EDEFWriter() xml_string = writer.to_string([original]) # Parse the XML reader = EDEFReader() endpoints = reader.parse(xml_string) # Ensure we have a valid result self.assertEqual(len(endpoints), 1, "Parsed more than one endpoint") endpoint = endpoints[0] # Ensure equality self.assertIsNot(original, endpoint, "Same exact endpoint object returned") self.assertEqual(original, endpoint, "Parsed endpoint is different") self.assertEqual(endpoint, original, "Parsed endpoint is different") # Ensure properties equality self.assertDictEqual(original.get_properties(), endpoint.get_properties(), "Endpoint properties changed")
def __read_endpoint(self, path): # type: (str) -> beans.EndpointDescription """ Reads the description of an endpoint at the given Z-Node path. Also set the endpoint event listener on the node. :param path: Path to the Z-Node describing the endpoint :return: An EndpointDescription bean """ return EDEFReader().parse( to_str(self._zk.get(path, self._on_endpoint_event)[0]))[0]
def _handle_set(self, endpoint_key): """ An endpoint has been set or updated in Redis :param endpoint_key: Name of the Redis key describing the endpoint :return: True if an endpoint was added, False if it was a pending endpoint and None if it was an echo """ fw_uid, _ = self._extract_uids(endpoint_key) if fw_uid == self._fw_uid: # Got an echo return False # Not an echo: handle the event # 1. Get the framework hostname try: # Find in cache hostname = self._frameworks_hosts[fw_uid] except KeyError: # Get it from Redis hostname = self._redis.get( PATTERN_FRAMEWORK_KEY.format(fw_uid=fw_uid)) if not hostname: # Endpoint's framework has been removed: ignore # (happens when two frameworks clear traces of an old one) logging.debug( "Framework of endpoint key %s, doesn't have a hostname", endpoint_key, ) return False else: # Valid hostname found, convert it to a string hostname = self._frameworks_hosts[fw_uid] = hostname.decode( "utf-8") # 2. Read the EDEF content content = self._redis.get(endpoint_key) if not content: logging.debug("Endpoint description removed while handling it") return False content = content.decode("utf-8") for endpoint in EDEFReader().parse(content): # Convert to a Pelix ImportEndpoint, and set the server hostname endpoint = endpoint.to_import() endpoint.server = hostname if self._registry.contains(endpoint): # Update endpoint self._registry.update(endpoint.uid, endpoint.properties) else: # New endpoint self._registry.add(endpoint) return True
def testEdefStringReload(self): """ Tries to convert an EndpointDescription to its XML format (EDEF) and to reload this string """ original = beans.EndpointDescription( self.svc_ref, {pelix.remote.PROP_ENDPOINT_ID: "toto", pelix.remote.PROP_IMPORTED_CONFIGS: ['titi'], pelix.constants.OBJECTCLASS: "spec"}) # Write the endpoint to an XML string writer = EDEFWriter() xml_string = writer.to_string([original]) # Parse the XML reader = EDEFReader() endpoints = reader.parse(xml_string) # Ensure we have a valid result self.assertEqual(len(endpoints), 1, "Parsed more than one endpoint") endpoint = endpoints[0] # Ensure equality self.assertIsNot(original, endpoint, "Same exact endpoint object returned") self.assertEqual(original, endpoint, "Parsed endpoint is different") self.assertEqual(endpoint, original, "Parsed endpoint is different") # Ensure properties equality self.assertDictEqual(original.get_properties(), endpoint.get_properties(), "Endpoint properties changed")
def __on_message(self, client, msg): """ A message has been received from a server :param client: Client that received the message :param msg: A MQTTMessage bean """ # Get the topic topic = msg.topic # Extract the event event = topic.rsplit("/", 1)[1] try: if event in ENDPOINT_EVENTS: # Parse the endpoints (from EDEF XML to ImportEndpoint) endpoints_descr = EDEFReader().parse(msg.payload) endpoints = [ endpoint.to_import() for endpoint in endpoints_descr ] if not endpoints: # No enpoints to read return if endpoints[0].framework == self._framework_uid: # Loopback message return # Give the list of endpoints to the handler parameter = endpoints else: # Give the payload as is to other event handlers parameter = msg.payload try: getattr(self, "_handle_{0}".format(event))(parameter) except AttributeError: _logger.error("Unhandled MQTT event: %s", event) except Exception as ex: _logger.exception("Error handling an MQTT message '%s': %s", topic, ex)