示例#1
0
    def _generate_concert_alias(self, gateway_name):
        '''
        Generate a friendly concert alias for this client given the (usually) uuid suffixed gateway name.

        :param str gateway_name: the uuid'd gateway name (e.g. kobuki95fbd06982344cfc9b013ef7b184e420)
        :return: the concert alias
        :rtype: str
        '''
        gateway_basename = rocon_gateway_utils.gateway_basename(gateway_name)
        # remove the 16 byte hex hash from the name
        same_name_count = 0
        human_friendly_indices = set([])
        for concert_client in self._flat_client_dict.values():
            if gateway_basename == rocon_gateway_utils.gateway_basename(
                    concert_client.gateway_name):
                index = concert_client.concert_alias.replace(
                    gateway_basename, "")
                if index == "":
                    human_friendly_indices.add("0")
                else:
                    human_friendly_indices.add(index)
                same_name_count += 1

        human_friendly_index = -1
        while True:
            human_friendly_index += 1
            if not str(human_friendly_index) in human_friendly_indices:
                break
        concert_name = gateway_basename if human_friendly_index == 0 else gateway_basename + str(
            human_friendly_index)
        return concert_name
示例#2
0
    def __init__(self, ip, port, whitelist=[], blacklist=[]):
        '''
          @param remote_gateway_request_callbacks : to handle redis responses
          @type list of function pointers (back to GatewaySync class

          @param ip : redis server ip
          @param port : redis server port

          @raise HubNameNotFoundError, HubNotFoundError
        '''
        # variables
        self.ip = ip
        self.port = port
        self.uri = str(ip) + ":" + str(port)
        self._redis_keys = {}
        self._redis_channels = {}

        # This is a temporary try-except block just to ping and see if the address we have here is
        # actually resolvable or it times out. Ideally we want to use socket_timeouts throughout,
        # but that will need modification of the way we handle the RedisListenerThread in
        # gateway_hub.py
        try:
            unused_ping = redis.Redis(host=ip, socket_timeout=0.5, port=port).ping()
            # should check ping result? Typically it just throws the timeout error
        except redis.exceptions.ConnectionError:
            self._redis_server = None
            raise HubNotFoundError("couldn't connect to the redis server")
        try:
            self.pool = redis.ConnectionPool(host=ip, port=port, db=0)
            self._redis_server = redis.Redis(connection_pool=self.pool)
            self._redis_pubsub_server = self._redis_server.pubsub()
            hub_key_name = self._redis_server.get("rocon:hub:name")
            # Be careful, hub_name is None, it means the redis server is
            # found but hub_name not yet set or not set at all.
            if not hub_key_name:
                self._redis_server = None
                raise HubNameNotFoundError("couldn't resolve hub name on the redis server [%s:%s]" % (ip, port))
            else:
                self.name = hub_api.key_base_name(hub_key_name)  # perhaps should store all key names somewhere central
                rospy.logdebug("Gateway : resolved hub name [%s].", self.name)
        except redis.exceptions.ConnectionError:
            self._redis_server = None
            raise HubNotFoundError("couldn't connect to the redis server")

        # whitelists, blacklists - check against uri's hash names and non-uuid names
        uri_blacklist = [urlparse(x).hostname + ':' + str(urlparse(x).port) for x in blacklist if urlparse(x).hostname is not None]
        uri_whitelist = [urlparse(x).hostname + ':' + str(urlparse(x).port) for x in whitelist if urlparse(x).hostname is not None]
        nonuuid_blacklist = [rocon_gateway_utils.gateway_basename(x) for x in blacklist if urlparse(x) is None and rocon_gateway_utils.gateway_basename(x)]
        nonuuid_whitelist = [rocon_gateway_utils.gateway_basename(x) for x in whitelist if urlparse(x) is None and rocon_gateway_utils.gateway_basename(x)]
        if self.uri in uri_blacklist or self.name in blacklist or self.name in nonuuid_blacklist:
            raise HubConnectionBlacklistedError("ignoring blacklisted hub [%s]" % self.uri)
        if self.name in blacklist or self.name in nonuuid_whitelist:
            raise HubConnectionBlacklistedError("ignoring blacklisted hub [%s]" % self.uri)
        if not ((len(whitelist) == 0) or (self.uri in uri_whitelist) or (self.name in whitelist)):
            raise HubConnectionNotWhitelistedError("hub/ip not in non-empty whitelist [%s, %s][%s]" % (self.name, self.uri, whitelist))
示例#3
0
def wait_for_remote_gateway(remote_gateway_name,
                            ns=_gateway_namespace,
                            timeout=rospy.Duration(5.0)):
    '''
      Slowly loop (and block) until remote the gateway is visible on our hub.
    '''
    rospy.wait_for_service(ns + '/remote_gateway_info')
    remote_gateway_info_service = rospy.ServiceProxy(
        ns + '/remote_gateway_info', gateway_srvs.RemoteGatewayInfo)
    req = gateway_srvs.RemoteGatewayInfoRequest()
    start_time = rospy.Time.now()
    while not rospy.is_shutdown():
        req = gateway_srvs.RemoteGatewayInfoRequest()
        req.gateways = []
        resp = remote_gateway_info_service(req)
        matched = False
        if rospy.Time.now() - start_time > timeout:
            raise GatewaySampleRuntimeError(
                "timed out waiting for a remote gateway to appear")
        for gateway in resp.gateways:
            if remote_gateway_name == gateway.name:
                matched = True
                break
            remote_gateway_basename = rocon_gateway_utils.gateway_basename(
                gateway.name)
            print("Samples: gateway comparison [%s][%s]" %
                  (remote_gateway_basename, remote_gateway_name))
            if remote_gateway_name == remote_gateway_basename:
                matched = True
                break
        if matched:
            break
示例#4
0
    def test_graph(self):
        flips = None
        while not flips:
            printtest("Waiting for flips")
            self.graph.update()
            flips = self.graph._local_gateway.flip_watchlist
            rospy.rostime.wallsleep(0.2)
        printtest("********************************************************************")
        printtest("* Local Gateway")
        printtest("********************************************************************")
        printtest("%s" % self.graph._local_gateway)
        self.assertEquals("5", str(len(flips)))
        # TODO: this is currently returning the base name, is should be returning the hash name

        self.assertEquals(len([flip for flip in flips if flip.gateway == "remote_gateway" and flip.rule.name == "/add_two_ints" and flip.rule.type == "service"]), 1)
        self.assertEquals(len([flip for flip in flips if flip.gateway == "remote_gateway" and flip.rule.name == "/chatter" and flip.rule.type == "publisher"]), 1)
        self.assertEquals(len([flip for flip in flips if flip.gateway == "remote_gateway" and flip.rule.name == "/chatter" and flip.rule.type == "subscriber"]), 1)
        self.assertEquals(len([flip for flip in flips if flip.gateway == "remote_gateway" and flip.rule.name == "/fibonacci" and flip.rule.type == "action_server"]), 1)
        self.assertEquals(len([flip for flip in flips if flip.gateway == "remote_gateway" and flip.rule.name == "/fibonacci" and flip.rule.type == "action_client"]), 1)
        
        printtest("********************************************************************")
        printtest("* Remote Gateway")
        printtest("********************************************************************")
        printtest("%s" % self.graph._remote_gateways)
        for remote_gateway in self.graph._remote_gateways:
            self.assertEquals("remote_gateway", rocon_gateway_utils.gateway_basename(remote_gateway.name))
示例#5
0
 def _add_node(self, node, rosgraphinst, dotcode_factory, dotgraph):
     if node in rosgraphinst.bad_nodes:
         bn = rosgraphinst.bad_nodes[node]
         if bn.type == rosgraph.impl.graph.BadNode.DEAD:
             dotcode_factory.add_node_to_graph(dotgraph,
                                               nodename=node,
                                               shape="doublecircle",
                                               url=node,
                                               color="red")
         else:
             dotcode_factory.add_node_to_graph(dotgraph,
                                               nodename=node,
                                               shape="doublecircle",
                                               url=node,
                                               color="orange")
     else:
         dotcode_factory.add_node_to_graph(
             dotgraph,
             nodename=node,
             #nodename=rocon_gateway_utils.gateway_basename(node),
             #nodelabel=rocon_gateway_utils.gateway_basename(node),
             shape='ellipse',
             url=rocon_gateway_utils.gateway_basename(node),
             #url=node
         )
示例#6
0
    def test_graph(self):
        flips = None
        while not flips:
            printtest("Waiting for flips")
            self.graph.update()
            flips = self.graph._local_gateway.flip_watchlist
            rospy.rostime.wallsleep(0.2)
        printtest(
            "********************************************************************"
        )
        printtest("* Local Gateway")
        printtest(
            "********************************************************************"
        )
        printtest("%s" % self.graph._local_gateway)
        self.assertEquals("1", str(len(flips)))
        # TODO: this is currently returning the base name, is should be returning the hash name
        self.assertEquals("remote_gateway", flips[0].gateway)
        self.assertEquals("publisher", flips[0].rule.type)
        self.assertEquals("/chatter", flips[0].rule.name)

        printtest(
            "********************************************************************"
        )
        printtest("* Remote Gateway")
        printtest(
            "********************************************************************"
        )
        printtest("%s" % self.graph._remote_gateways)
        for remote_gateway in self.graph._remote_gateways:
            self.assertEquals(
                "remote_gateway",
                rocon_gateway_utils.gateway_basename(remote_gateway.name))
示例#7
0
    def _add_node(self, node, dotcode_factory, dotgraph):
        '''
        A node here is a concert client. We basically add nodes and classify according
        to their state in the dotgraph.

        :param node .concert_client.ConcertClient: the concert client to show on the dotgraph
        '''
        # colour strings defined as per http://qt-project.org/doc/qt-4.8/qcolor.html#setNamedColor
        # and http://www.w3.org/TR/SVG/types.html#ColorKeywords
        if node.state == concert_msgs.ConcertClientState.PENDING:
            node_colour = "magenta"
        elif node.state == concert_msgs.ConcertClientState.AVAILABLE:
            node_colour = "blue"
        elif node.state == concert_msgs.ConcertClientState.MISSING:
            node_colour = "powderblue"
        elif node.state == concert_msgs.ConcertClientState.GONE:
            node_colour = "black"
        elif node.state == concert_msgs.ConcertClientState.BAD:
            node_colour = "red"
        dotcode_factory.add_node_to_graph(dotgraph,
                                          nodename=node.concert_alias,
                                          # nodename=rocon_gateway_utils.gateway_basename(node),
                                          # nodelabel=rocon_gateway_utils.gateway_basename(node),
                                          shape='ellipse',
                                          url=rocon_gateway_utils.gateway_basename(node.gateway_name),
                                          # url=node,
                                          color=node_colour
                                          )
示例#8
0
    def _generate_pulls(self, connection_type, name, node, gateway,
                        unique_name):
        '''
          Checks if a local rule (obtained from master.get_system_state)
          is a suitable association with any of the rules or patterns. This can
          return multiple matches, since the same local rule
          properties can be multiply pulled to different remote gateways.

          Used in the update() call above that is run in the watcher thread.

          Note, don't need to lock here as the update() function takes care of it.

          @param connection_type : rule type
          @type str : string constant from gateway_msgs.Rule

          @param name : fully qualified topic, service or action name
          @type str

          @param node : ros node name (coming from master.get_system_state)
          @type str

          @param gateway : remote gateway hash name.
          @type str

          @return all the pull rules that match this local rule
          @return list of RemoteRule objects updated with node names from self.watchlist
        '''
        matched_pull_rules = []
        for rule in self.watchlist[connection_type]:
            # check for regular expression or perfect match
            gateway_match_result = re.match(rule.gateway, gateway)
            matched = False
            if gateway_match_result and gateway_match_result.group(
            ) == gateway:
                matched = True
            elif rule.gateway == rocon_gateway_utils.gateway_basename(gateway):
                matched = True
            if not matched:
                continue

            # Check names
            rule_name = rule.rule.name
            matched = self.is_matched(rule, rule_name, name, node)
            if not matched:
                rule_name = '/' + unique_name + '/' + rule.rule.name
                matched = self.is_matched(rule, rule_name, name, node)

            if not matched:
                rule_name = '/' + rule.rule.name
                matched = self.is_matched(rule, rule_name, name, node)

            if matched:
                matched_pull = copy.deepcopy(rule)
                matched_pull.gateway = gateway  # just in case we used a regex or matched basename
                matched_pull.rule.name = name  # just in case we used a regex
                matched_pull.rule.node = node  # just in case we used a regex
                matched_pull_rules.append(matched_pull)
        return matched_pull_rules
    def _generate_pulls(self, connection_type, name, node, gateway, unique_name):
        '''
          Checks if a local rule (obtained from master.get_system_state)
          is a suitable association with any of the rules or patterns. This can
          return multiple matches, since the same local rule
          properties can be multiply pulled to different remote gateways.

          Used in the update() call above that is run in the watcher thread.

          Note, don't need to lock here as the update() function takes care of it.

          @param connection_type : rule type
          @type str : string constant from gateway_msgs.Rule

          @param name : fully qualified topic, service or action name
          @type str

          @param node : ros node name (coming from master.get_system_state)
          @type str

          @param gateway : remote gateway hash name.
          @type str

          @return all the pull rules that match this local rule
          @return list of RemoteRule objects updated with node names from self.watchlist
        '''
        matched_pull_rules = []
        for rule in self.watchlist[connection_type]:
            # check for regular expression or perfect match
            gateway_match_result = re.match(rule.gateway, gateway)
            matched = False
            if gateway_match_result and gateway_match_result.group() == gateway:
                matched = True
            elif rule.gateway == rocon_gateway_utils.gateway_basename(gateway):
                matched = True
            if not matched:
                continue

            # Check names
            rule_name = rule.rule.name
            matched = self.is_matched(rule, rule_name, name, node)
            if not matched:
                rule_name = '/' + unique_name + '/' + rule.rule.name
                matched = self.is_matched(rule, rule_name, name, node)

            if not matched:
                rule_name = '/' + rule.rule.name
                matched = self.is_matched(rule, rule_name, name, node)

            if matched:
                matched_pull = copy.deepcopy(rule)
                matched_pull.gateway = gateway  # just in case we used a regex or matched basename
                matched_pull.rule.name = name   # just in case we used a regex
                matched_pull.rule.node = node   # just in case we used a regex
                matched_pull_rules.append(matched_pull)
        return matched_pull_rules
示例#10
0
 def _get_matched_gateways(self, flip_rule, remote_gateways):
     matched_gateways = []
     for gateway in remote_gateways:
         # check for regular expression or perfect match
         gateway_match_result = re.match(flip_rule.gateway, gateway)
         if gateway_match_result and gateway_match_result.group() == gateway:
             matched_gateways.append(gateway)
         elif flip_rule.gateway == rocon_gateway_utils.gateway_basename(gateway):
             matched_gateways.append(gateway)
     return matched_gateways
示例#11
0
 def matches_remote_gateway_basename(self, gateway):
     '''
       Use this when gateway can be a regular expression and
       we need to check it off against list_remote_gateway_names()
     '''
     weak_matches = []
     try:
         for remote_gateway in self.list_remote_gateway_names():
             if re.match(gateway, rocon_gateway_utils.gateway_basename(remote_gateway)):
                 weak_matches.append(remote_gateway)
     except HubConnectionLostError:
         raise
     return weak_matches
示例#12
0
    def __init__(self, ip, port, whitelist=[], blacklist=[]):
        '''
          @param remote_gateway_request_callbacks : to handle redis responses
          @type list of function pointers (back to GatewaySync class

          @param ip : redis server ip
          @param port : redis server port

          @raise HubNameNotFoundError, HubNotFoundError
        '''
        # variables
        self.ip = ip
        self.port = port
        self.uri = str(ip) + ":" + str(port)
        self._redis_keys = {}
        self._redis_channels = {}

        # This is a temporary try-except block just to ping and see if the address we have here is
        # actually resolvable or it times out. Ideally we want to use socket_timeouts throughout,
        # but that will need modification of the way we handle the RedisListenerThread in
        # gateway_hub.py
        try:
            unused_ping = redis.Redis(host=ip, socket_timeout=5.0, port=port).ping()
            # should check ping result? Typically it just throws the timeout error
        except redis.exceptions.ConnectionError:
            self._redis_server = None
            raise HubNotFoundError("couldn't connect to the redis server")
        try:
            self.pool = redis.ConnectionPool(host=ip, port=port, db=0, socket_timeout=5.0)
            self._redis_server = redis.Redis(connection_pool=self.pool)
            self._redis_pubsub_server = self._redis_server.pubsub()
            hub_key_name = self._redis_server.get("rocon:hub:name")
            # Be careful, hub_name is None, it means the redis server is
            # found but hub_name not yet set or not set at all.

            # retrying for 5 seconds in case we started too fast
            retries = 0
            while self._redis_server and not hub_key_name and retries < 5:
                rospy.logwarn("couldn't resolve hub name on the redis server [%s:%s]. Retrying..." % (ip, port))
                retries += 1
                rospy.rostime.wallsleep(1.0)
                hub_key_name = self._redis_server.get("rocon:hub:name")

            if not hub_key_name:
                self._redis_server = None
                raise HubNameNotFoundError("couldn't resolve hub name on the redis server [%s:%s]" % (ip, port))
            else:
                self.name = hub_api.key_base_name(hub_key_name)  # perhaps should store all key names somewhere central
                rospy.logdebug("Gateway : resolved hub name [%s].", self.name)
        except redis.exceptions.ConnectionError:
            self._redis_server = None
            raise HubNotFoundError("couldn't connect to the redis server")

        # whitelists, blacklists - check against uri's hash names and non-uuid names
        uri_blacklist = [urlparse(x).hostname + ':' + str(urlparse(x).port) for x in blacklist if urlparse(x).hostname is not None]
        uri_whitelist = [urlparse(x).hostname + ':' + str(urlparse(x).port) for x in whitelist if urlparse(x).hostname is not None]
        nonuuid_blacklist = [rocon_gateway_utils.gateway_basename(x) for x in blacklist if urlparse(x) is None and rocon_gateway_utils.gateway_basename(x)]
        nonuuid_whitelist = [rocon_gateway_utils.gateway_basename(x) for x in whitelist if urlparse(x) is None and rocon_gateway_utils.gateway_basename(x)]
        if self.uri in uri_blacklist or self.name in blacklist or self.name in nonuuid_blacklist:
            raise HubConnectionBlacklistedError("ignoring blacklisted hub [%s]" % self.uri)
        if self.name in blacklist or self.name in nonuuid_whitelist:
            raise HubConnectionBlacklistedError("ignoring blacklisted hub [%s]" % self.uri)
        if not ((len(whitelist) == 0) or (self.uri in uri_whitelist) or (self.name in whitelist)):
            raise HubConnectionNotWhitelistedError("hub/ip not in non-empty whitelist [%s, %s][%s]" % (self.name, self.uri, whitelist))
    def _generate_flips(self, connection_type, name, node, remote_gateways, unique_name):
        '''
          Checks if a local rule (obtained from master.get_system_state)
          is a suitable association with any of the rules or patterns. This can
          return multiple matches, since the same local rule
          properties can be multiply flipped to different remote gateways.

          Used in the update() call above that is run in the watcher thread.
          Note, don't need to lock here as the update() function takes care of it.

          @param connection_type : rule type
          @type str : string constant from gateway_msgs.msg.Rule

          @param name : fully qualified topic, service or action name
          @type str

          @param node : ros node name (coming from master.get_system_state)
          @type str

          @param gateways : gateways that are available (registered on the hub)
          @type string

          @return all the flip rules that match this local rule
          @return list of RemoteRule objects updated with node names from self.watchlist
        '''
        matched_flip_rules = []
        for flip_rule in self.watchlist[connection_type]:
            # Check if the flip rule corresponds to an existing gateway
            matched_gateways = []
            for gateway in remote_gateways:
                # check for regular expression or perfect match
                gateway_match_result = re.match(flip_rule.gateway, gateway)
                if gateway_match_result and gateway_match_result.group() == gateway:
                    matched_gateways.append(gateway)
                elif flip_rule.gateway == rocon_gateway_utils.gateway_basename(gateway):
                    matched_gateways.append(gateway)
            if not matched_gateways:
                continue

            # Check names
            rule_name = flip_rule.rule.name
            matched = self.is_matched(flip_rule, rule_name, name, node)

            if not utils.is_all_pattern(flip_rule.rule.name):
                if not matched:
                    rule_name = '/' + unique_name + '/' + flip_rule.rule.name
                    matched = self.is_matched(flip_rule, rule_name, name, node)

                if not matched:
                    rule_name = '/' + flip_rule.rule.name
                    matched = self.is_matched(flip_rule, rule_name, name, node)

            if matched:
                for gateway in matched_gateways:
                    matched_flip = copy.deepcopy(flip_rule)
                    matched_flip.gateway = gateway  # just in case we used a regex or matched basename
                    matched_flip.rule.name = name  # just in case we used a regex
                    matched_flip.rule.node = node  # just in case we used a regex
                    matched_flip_rules.append(matched_flip)

        return matched_flip_rules
    def _generate_flips(self, connection_type, name, node, remote_gateways,
                        unique_name):
        '''
          Checks if a local rule (obtained from master.get_system_state)
          is a suitable association with any of the rules or patterns. This can
          return multiple matches, since the same local rule
          properties can be multiply flipped to different remote gateways.

          Used in the update() call above that is run in the watcher thread.
          Note, don't need to lock here as the update() function takes care of it.

          @param connection_type : rule type
          @type str : string constant from gateway_msgs.msg.Rule

          @param name : fully qualified topic, service or action name
          @type str

          @param node : ros node name (coming from master.get_system_state)
          @type str

          @param gateways : gateways that are available (registered on the hub)
          @type string

          @return all the flip rules that match this local rule
          @return list of RemoteRule objects updated with node names from self.watchlist
        '''
        matched_flip_rules = []
        for flip_rule in self.watchlist[connection_type]:
            # Check if the flip rule corresponds to an existing gateway
            matched_gateways = []
            for gateway in remote_gateways:
                # check for regular expression or perfect match
                gateway_match_result = re.match(flip_rule.gateway, gateway)
                if gateway_match_result and gateway_match_result.group(
                ) == gateway:
                    matched_gateways.append(gateway)
                elif flip_rule.gateway == rocon_gateway_utils.gateway_basename(
                        gateway):
                    matched_gateways.append(gateway)
            if not matched_gateways:
                continue

            # Check names
            rule_name = flip_rule.rule.name
            matched = self.is_matched(flip_rule, rule_name, name, node)

            if not utils.is_all_pattern(flip_rule.rule.name):
                if not matched:
                    rule_name = '/' + unique_name + '/' + flip_rule.rule.name
                    matched = self.is_matched(flip_rule, rule_name, name, node)

                if not matched:
                    rule_name = '/' + flip_rule.rule.name
                    matched = self.is_matched(flip_rule, rule_name, name, node)

            if matched:
                for gateway in matched_gateways:
                    matched_flip = copy.deepcopy(flip_rule)
                    matched_flip.gateway = gateway  # just in case we used a regex or matched basename
                    matched_flip.rule.name = name  # just in case we used a regex
                    matched_flip.rule.node = node  # just in case we used a regex
                    matched_flip_rules.append(matched_flip)

        return matched_flip_rules
示例#15
0
 def test_basename(self):
     self.assertEquals(
         "dude",
         rocon_gateway_utils.gateway_basename(
             'dude1285014a28c74162bf19952d1481197e'))