예제 #1
0
    def update(self, remote_connections, unique_name):
        '''
          Computes a new pulled interface from the incoming connections list
           and returns two dictionaries -
          removed and newly added pulls so the watcher thread can take
          appropriate action ((un)registrations).

          This is run in the watcher thread (warning: take care - other
          additions come from ros service calls in different threads!)

          @param remote_gateway_hub_index : full gateway-hub database index to parse
          @type gateway hash names keyed into a dic with a list of their hubs
        '''
        # SLOW, EASY METHOD
        #   Totally regenerate a new pulled interface, compare with old
        pulled = utils.create_empty_connection_type_dictionary()
        new_pulls = utils.create_empty_connection_type_dictionary()
        removed_pulls = utils.create_empty_connection_type_dictionary()
        diff = lambda l1,l2: [x for x in l1 if x not in l2] # diff of lists
        self._lock.acquire()
        # Totally regenerate a new pulled interface, compare with old
        for remote_gateway in remote_connections.keys():
            connections = remote_connections[remote_gateway]
            for connection_type in connections:
                for connection in connections[connection_type]:
                    pulled[connection_type].extend(self._generate_pulls(connection.rule.type, connection.rule.name, connection.rule.node, remote_gateway, unique_name))
        for connection_type in utils.connection_types:
            new_pulls[connection_type] = diff(pulled[connection_type], self.pulled[connection_type])
            removed_pulls[connection_type] = diff(self.pulled[connection_type], pulled[connection_type])
        self.pulled = copy.deepcopy(pulled)
        self._lock.release()
        return new_pulls, removed_pulls
예제 #2
0
    def __init__(self, default_rule_blacklist, default_rules):
        '''
          Initialises the public interface

          @param default_rule_blacklist : connection type keyed dictionary of rules
          @type str keyed dictionary of gateway_msgs.msg.Rule[]

          @param default_rules : connection type keyed dictionary of rules
          @type str keyed dictionary of gateway_msgs.msg.Rule[]
        '''
        # List of rules to be monitored and (un)advertised  as they
        # become (un)available
        self.watchlist = utils.create_empty_connection_type_dictionary()

        # Default rules that cannot be advertised - used in AdvertiseAll mode
        self._default_blacklist = default_rule_blacklist

        # Default + custom blacklist - used in AdvertiseAll mode
        self.blacklist = self._default_blacklist

        # list of fully qualified connections currently being advertised
        self.public = utils.create_empty_connection_type_dictionary()

        self.advertise_all_enabled = False

        self.lock = threading.Lock()

        # Load up static rules.
        for connection_type in utils.connection_types:
            for rule in default_rules[connection_type]:
                self.add_rule(rule)
예제 #3
0
    def update(self, connections):
        '''
          Checks a list of rules and determines which ones should be
          added/removed to the public interface. Modifies the public interface
          accordingly, and returns the list of rules to the gateway for
          hub operations

          @param rules: the list of rules available locally
          @type dict of lists of Rule objects

          @return: new public connections, as well as connections to be removed
          @rtype: Connection[], Connection[]
        '''
        # SLOW, EASY METHOD
        public = utils.create_empty_connection_type_dictionary()
        new_public = utils.create_empty_connection_type_dictionary()
        removed_public = utils.create_empty_connection_type_dictionary()
        diff = lambda l1, l2: [x for x in l1 if x not in l2]  # diff of lists
        for connection_type in connections:
            for connection in connections[connection_type]:
                if self._allowRule(connection.rule):
                    public[connection_type].append(connection)
            new_public[connection_type] = diff(public[connection_type],
                                               self.public[connection_type])
            removed_public[connection_type] = diff(
                self.public[connection_type], public[connection_type])

        self.lock.acquire()
        self.public = public
        self.lock.release()

        return new_public, removed_public
예제 #4
0
    def __init__(self, default_rule_blacklist, default_rules, all_targets):
        '''
          @param default_rule_blacklist : used when in flip/pull all mode
          @type dictionary of gateway
          @param default_rules : static rules to flip/pull on startup
          @type gateway_msgs.msg.RemoteRule[]
          @param all_targets : static flip/pull all targets to flip/pull to on startup
          @type string[]
        '''
        # Rules that are active, ie have been flipped or pulled from remote gateways
        # keys are connection_types, elements are lists of RemoteRule objects
        # This gets aliased to self.flipped or self.pulled as necessary in
        # the subclasses
        self.active = utils.create_empty_connection_type_dictionary()

        # Default rules used in the xxxAll modes
        self._default_blacklist = default_rule_blacklist  # dictionary of gateway-gateway_msgs.msg.Rule lists, not RemoteRules!

        # keys are connection_types, elements are lists of gateway_msgs.msg.RemoteRule objects
        self.watchlist = utils.create_empty_connection_type_dictionary()    # Specific rules used to determine what local rules to flip

        # keys are connection_types, elements are lists of utils.Registration objects
        self.registrations = utils.create_empty_connection_type_dictionary()  # Flips from remote gateways that have been locally registered

        # Blacklists when doing flip all - different for each gateway, each value is one of our usual rule type dictionaries
        self._blacklist = {}

        self._lock = threading.Lock()

        # Load up static rules.
        for rule in default_rules:
            self.add_rule(rule)
        for gateway in all_targets:
            self.add_all(gateway, [])  # don't add the complexity of extra blacklists yet, maybe later
    def update(self, connections, remote_gateway_hub_index, unique_name):
        '''
          Computes a new flipped interface and returns two dictionaries -
          removed and newly added flips so the watcher thread can take
          appropriate action (inform the remote gateways).

          This is run in the watcher thread (warning: take care - other
          additions come from ros service calls in different threads!)

          @param connections : list of all the system state connections from the local master
          @type connection type keyed dictionary of utils.Connection lists.

          @param remote_gateway_hub_index : full gateway-hub database index to parse
          @type gateway hash names keyed into a dic with a list of their hubs

          @param unique_name : this gateway's unique hash name
          @type string

          @return new_flips, removed_flips (i.e. those that are no longer on the local master)
          @rtype pair of connection type keyed dictionary of gateway_msgs.msg.Rule lists.
        '''
        # SLOW, EASY METHOD

        flipped = utils.create_empty_connection_type_dictionary()
        new_flips = utils.create_empty_connection_type_dictionary()
        removed_flips = utils.create_empty_connection_type_dictionary()
        remote_gateways = remote_gateway_hub_index.keys()
        diff = lambda l1, l2: [x for x in l1 if x not in l2]  # diff of lists
        self._lock.acquire()
        # Prune locally cached flip list for flips that have lost their remotes, keep the rules though
        for connection_type in utils.connection_types:
            # flip.gateway is a hash name, so is the remote_gateways list
            self.flipped[connection_type] = [
                flip for flip in self.flipped[connection_type]
                if flip.gateway in remote_gateways
            ]
        # Totally regenerate a new flipped interface, compare with old
        for connection_type in connections:
            for connection in connections[connection_type]:
                flipped[connection_type].extend(
                    self._generate_flips(connection.rule.type,
                                         connection.rule.name,
                                         connection.rule.node, remote_gateways,
                                         unique_name))
            new_flips[connection_type] = diff(flipped[connection_type],
                                              self.flipped[connection_type])
            removed_flips[connection_type] = diff(
                self.flipped[connection_type], flipped[connection_type])
        self.flipped = copy.deepcopy(flipped)
        self._lock.release()
        return new_flips, removed_flips
예제 #6
0
 def __init__(self, get_system_state):
     self._get_system_state = get_system_state  # function call to the local master
     self._connections = {}
     #        self._system_state = {}
     #        self._system_state[PUBLISHER] = []
     #        self._system_state[SUBSCRIBER] = []
     #        self._system_state[SERVICE] = []
     self._connections = utils.create_empty_connection_type_dictionary()
예제 #7
0
    def update(self, new_system_state=None):
        '''
          Currently completely regenerating the connections dictionary and then taking
          diffs. Could be faster if we took diffs on the system state instead, but that's
          a bit more awkward since each element has a variable list of nodes that we'd have
          to check against to get good diffs. e.g.
            old_publishers = ['/chatter', ['/talker']]
            new_publishers = ['/chatter', ['/talker', '/babbler']]
        '''
        if new_system_state is None:
            publishers, subscribers, services = self._get_system_state()
        else:
            publishers = new_system_state[PUBLISHER]
            subscribers = new_system_state[SUBSCRIBER]
            services = new_system_state[SERVICE]
        action_servers, publishers, subscribers = self._get_action_servers(
            publishers, subscribers)
        action_clients, publishers, subscribers = self._get_action_clients(
            publishers, subscribers)
        connections = utils.create_empty_connection_type_dictionary()
        connections[PUBLISHER] = self._get_connections_from_pub_sub_list(
            publishers, PUBLISHER)
        connections[SUBSCRIBER] = self._get_connections_from_pub_sub_list(
            subscribers, SUBSCRIBER)
        connections[SERVICE] = self._get_connections_from_service_list(
            services, SERVICE)
        connections[ACTION_SERVER] = self._get_connections_from_action_list(
            action_servers, ACTION_SERVER)
        connections[ACTION_CLIENT] = self._get_connections_from_action_list(
            action_clients, ACTION_CLIENT)

        # Will probably need to check not just in, but only name, node equal
        diff = lambda l1, l2: [x for x in l1 if x not in l2]
        new_connections = utils.create_empty_connection_type_dictionary()
        lost_connections = utils.create_empty_connection_type_dictionary()
        for connection_type in utils.connection_types:
            new_connections[connection_type] = diff(
                connections[connection_type],
                self._connections[connection_type])
            lost_connections[connection_type] = diff(
                self._connections[connection_type],
                connections[connection_type])
        self._connections = connections
        return new_connections, lost_connections
예제 #8
0
    def get_local_advertisements(self):
        '''
          Retrieves the local list of advertisements from the hub. This
          gets used to sync across multiple hubs.

          @return dictionary of remote advertisements
          @rtype dictionary of connection type keyed connection values
       '''
        connections = utils.create_empty_connection_type_dictionary()
        key = hub_api.create_rocon_gateway_key(self._unique_gateway_name, 'advertisements')
        public_interface = self._redis_server.smembers(key)
        for connection_str in public_interface:
            connection = utils.deserialize_connection(connection_str)
            connections[connection.rule.type].append(connection)
        return connections
예제 #9
0
    def unadvertise_all(self):
        '''
          Disallow the allow all mode, if enabled. If allow all mode is not
          enabled, remove everything from the public interface
        '''
        rospy.loginfo(
            "Gateway : received a request to remove all advertisements!")
        self.lock.acquire()

        # stop advertising all
        self.advertise_all_enabled = False

        # easy hack for resetting the watchlist and blacklist
        self.watchlist = utils.create_empty_connection_type_dictionary()
        self.blacklist = self._default_blacklist

        self.lock.release()
예제 #10
0
    def get_remote_connection_state(self, remote_gateway):
        '''
          Equivalent to get_connection_state, but generates it from the public
          interface of a remote gateway

          @param remote_gateway : hash name for a remote gateway
          @type str
          @return dictionary of remote advertisements
          @rtype dictionary of connection type keyed connection values
       '''
        connections = utils.create_empty_connection_type_dictionary()
        key = hub_api.create_rocon_gateway_key(remote_gateway,
                                               'advertisements')
        public_interface = self._redis_server.smembers(key)
        for connection_str in public_interface:
            connection = utils.deserialize_connection(connection_str)
            connections[connection.rule.type].append(connection)
        return connections
예제 #11
0
def generate_rules(param):
    '''
      Converts a param of the suitable type (see default_blacklist.yaml)
      into a dictionary of Rule types.

      @return all rules as gateway_msgs.msg.Rule objects in our usual keyed dictionary format
      @rtype type keyed dictionary of Rule lists
    '''
    rules = utils.create_empty_connection_type_dictionary()
    for value in param:
        rule = Rule()
        rule.name = value['name']
        # maybe also check for '' here?
        pattern = re.compile("None", re.IGNORECASE)
        if pattern.match(value['node']):
            rule.node = ''  # ROS Message fields should not be None, maybe not a problem here though, see below
        else:
            rule.node = value['node']
        rule.type = value['type']
        rules[rule.type].append(rule)
    return rules
예제 #12
0
    def get_remote_connection_state(self, remote_gateway):
        '''
          Equivalent to get_connection_state, but generates it from the public
          interface of a remote gateway

          @param remote_gateway : hash name for a remote gateway
          @type str
          @return dictionary of remote advertisements
          @rtype dictionary of connection type keyed connection values
       '''
        connections = utils.create_empty_connection_type_dictionary()
        key = hub_api.create_rocon_gateway_key(remote_gateway, 'advertisements')
        try:
            public_interface = self._redis_server.smembers(key)
            for connection_str in public_interface:
                connection = utils.deserialize_connection(connection_str)
                connections[connection.rule.type].append(connection)
        except redis.exceptions.ConnectionError:
            # will arrive here if the hub happens to have been lost last update and arriving here
            pass
        return connections
예제 #13
0
    def advertise_all(self, blacklist):
        '''
          Allow all rules apart from the ones in the provided blacklist +
          default blacklist

          @param blacklist : list of Rule objects
          @type list : list of Rule objects

          @return failure if already advertising all, success otherwise
          @rtype bool
        '''
        rospy.loginfo("Gateway : received a request advertise everything!")
        self.lock.acquire()

        # Check if advertise all already enabled
        if self.advertise_all_enabled:
            self.lock.release()
            return False
        self.advertise_all_enabled = True

        # generate watchlist
        self.watchlist = utils.create_empty_connection_type_dictionary(
        )  # easy hack for getting a clean watchlist
        for connection_type in utils.connection_types:
            allow_all_rule = Rule()
            allow_all_rule.name = '.*'
            allow_all_rule.type = connection_type
            allow_all_rule.node = '.*'
            self.watchlist[connection_type].append(allow_all_rule)

        # generate blacklist (while making sure only unique rules get added)
        self.blacklist = copy.deepcopy(self._default_blacklist)
        for rule in blacklist:
            if not publicRuleExists(rule, self.blacklist[rule.type]):
                self.blacklist[rule.type].append(rule)

        self.lock.release()
        return True