Esempio n. 1
0
    def send_flip_request(self, remote_gateway, connection):
        '''
          Sends a message to the remote gateway via redis pubsub channel. This is called from the
          watcher thread, when a flip rule gets activated.

           - redis channel name: rocon:<remote_gateway_name>
           - data : list of [ command, gateway, rule type, type, xmlrpc_uri ]
            - [0] - command       : in this case 'flip'
            - [1] - gateway       : the name of this gateway, i.e. the flipper
            - [2] - name          : local name
            - [3] - node          : local node name
            - [4] - connection_type : one of ConnectionType.PUBLISHER etc
            - [5] - type_info     : a ros format type (e.g. std_msgs/String or service api)
            - [6] - xmlrpc_uri    : the xmlrpc node uri

          @param command : string command name - either 'flip' or 'unflip'
          @type str

          @param flip_rule : the flip to send
          @type gateway_msgs.RemoteRule

          @param type_info : topic type (e.g. std_msgs/String)
          @param str

          @param xmlrpc_uri : the node uri
          @param str
        '''
        source = hub_api.key_base_name(self._redis_keys['gateway'])
        cmd = utils.serialize_connection_request('flip', source, connection)
        try:
            self._redis_server.publish(
                hub_api.create_rocon_key(remote_gateway), cmd)
        except Exception as unused_e:
            return False
        return True
Esempio n. 2
0
    def run(self):
        '''
          Run the hub watcher (sidekick) thread at the rate specified by the
          watcher_thread_rate parameter. The watcher thread does the following:
              1. For all gateways available, see if we have a pinger available.
              2. Add and remove pingers as necessary
              3. Depending on pinger stats, update hub appropriately
        '''
        rate = WallRate(self.watcher_thread_rate)
        unavailable_set = set()
        while True:
            remote_gateway_names = self.hub.list_remote_gateway_names()

            # Check all pingers
            for name in remote_gateway_names:

                gateway_key = hub_api.create_rocon_key(name)
                # Get time for this gateway when hub was last seen
                ping_key = hub_api.create_rocon_gateway_key(name, ':ping')
                expiration_time = self.hub._redis_server.ttl(ping_key)
                # rospy.logwarn("<= {0} TTL {1}".format(ping_key, expiration_time))

                if expiration_time is None or expiration_time == -2:
                    # Probably in the process of starting up, ignore for now
                    continue

                seconds_since_last_seen = int(ConnectionStatistics.MAX_TTL -
                                              expiration_time)

                # rospy.logwarn("<= Not seen since {0} secs...".format(seconds_since_last_seen))

                # if it has been gone for more than one loop
                if seconds_since_last_seen > rate.period:
                    rospy.logwarn("Hub Watcher: gateway " + name +
                                  " has been unavailable for " +
                                  str(seconds_since_last_seen) + " seconds.")
                    unavailable_set.add(gateway_key)
                    self.hub.mark_named_gateway_available(
                        gateway_key, False, seconds_since_last_seen)

                    # Check if gateway gone
                    if seconds_since_last_seen > self.gateway_gone_timeout:
                        rospy.logwarn("Hub Watcher: gateway " + name +
                                      " has been unavailable for " +
                                      str(self.gateway_gone_timeout) +
                                      " seconds! Removing from hub.")

                        # Gone for too long => unregister
                        self.hub.unregister_named_gateway(gateway_key)

                # Mark gateway as available
                else:
                    if gateway_key in unavailable_set:
                        rospy.logwarn("Hub Watcher: gateway " + name +
                                      " detected available again !")
                        unavailable_set.remove(gateway_key)
                    self.hub.mark_named_gateway_available(
                        gateway_key, True, seconds_since_last_seen)

            rate.sleep()
Esempio n. 3
0
 def _send_unflip_request(self, remote_gateway, rule):
     source = hub_api.key_base_name(self._redis_keys['gateway'])
     cmd = utils.serialize_rule_request('unflip', source, rule)
     try:
         self._redis_server.publish(
             hub_api.create_rocon_key(remote_gateway), cmd)
     except Exception as unused_e:
         return False
     return True
Esempio n. 4
0
    def register_gateway(self, firewall, unique_gateway_name, hub_connection_lost_gateway_hook, gateway_ip):
        '''
          Register a gateway with the hub.

          @param firewall
          @param unique_gateway_name
          @param hub_connection_lost_gateway_hook : used to trigger Gateway.disengage_hub(hub)
                 on lost hub connections in redis pubsub listener thread.
          @gateway_ip

          @raise HubConnectionLostError if for some reason, the redis server has become unavailable.
        '''
        if not self._redis_server:
            raise HubConnectionLostError()
        self._unique_gateway_name = unique_gateway_name
        self._redis_keys['gateway'] = hub_api.create_rocon_key(unique_gateway_name)
        self._redis_keys['firewall'] = hub_api.create_rocon_gateway_key(unique_gateway_name, 'firewall')
        self._firewall = 1 if firewall else 0
        self._hub_connection_lost_gateway_hook = hub_connection_lost_gateway_hook
        if not self._redis_server.sadd(self._redis_keys['gatewaylist'], self._redis_keys['gateway']):
            # should never get here - unique should be unique
            pass
        self.mark_named_gateway_available(self._redis_keys['gateway'])
        self._redis_server.set(self._redis_keys['firewall'], self._firewall)
        # I think we just used this for debugging, but we might want to hide it in
        # future (it's the ros master hostname/ip)
        self._redis_keys['ip'] = hub_api.create_rocon_gateway_key(unique_gateway_name, 'ip')
        self._redis_server.set(self._redis_keys['ip'], gateway_ip)

        self.private_key, public_key = utils.generate_private_public_key()
        self._redis_keys['public_key'] = hub_api.create_rocon_gateway_key(unique_gateway_name, 'public_key')
        old_key = self._redis_server.get(self._redis_keys['public_key'])
        serialized_public_key = utils.serialize_key(public_key)
        self._redis_server.set(self._redis_keys['public_key'], serialized_public_key)
        if serialized_public_key != old_key:
            rospy.loginfo('Gateway : Found existing mismatched public key on the hub. ' +
                          'Requesting resend for all flip-ins.')
            self._resend_all_flip_ins()

        # Mark this gateway as now available
        self._redis_server.sadd(self._redis_keys['gatewaylist'], self._redis_keys['gateway'])
        self.hub_connection_checker_thread = HubConnectionCheckerThread(
            self.ip, self.port, self._hub_connection_lost_hook)
        self.hub_connection_checker_thread.start()
        self.connection_lost_lock = threading.Lock()

        # Let hub know we are alive
        ping_key = hub_api.create_rocon_gateway_key(self._unique_gateway_name, ':ping')
        self._redis_server.set(ping_key, True)
        self._redis_server.expire(ping_key, gateway_msgs.ConnectionStatistics.MAX_TTL)
Esempio n. 5
0
    def run(self):
        '''
          Run the hub watcher (sidekick) thread at the rate specified by the
          watcher_thread_rate parameter. The wathcer thread does the following:
              1. For all gateways available, see if we have a pinger available.
              2. Add and remove pingers as necessary
              3. Depending on pinger stats, update hub appropriately
        '''
        rate = WallRate(self.watcher_thread_rate)
        while True:
            remote_gateway_names = self.hub.list_remote_gateway_names()

            # Check all pingers
            for name in remote_gateway_names:

                gateway_key = hub_api.create_rocon_key(name)
                # Get time for this gateway when hub was last seen
                ping_key = hub_api.create_rocon_gateway_key(name, ':ping')
                expiration_time = self.hub._redis_server.ttl(ping_key)

                if expiration_time is None:
                    # Probably in the process of starting up, ignore for now
                    continue

                seconds_since_last_seen = \
                        int(ConnectionStatistics.MAX_TTL - expiration_time)
                # Check if gateway gone for low timeout (unavailable)
                if seconds_since_last_seen > self.gateway_unavailable_timeout:
                    if name not in self.unavailable_gateways:
                        rospy.logwarn("Hub Watcher: gateway " + name +
                                      " has been unavailable for " +
                                      str(self.gateway_unavailable_timeout) +
                                      " seconds! Marking as unavailable.")
                        self.unavailable_gateways.append(name)
                    self.hub.mark_named_gateway_available(gateway_key, False,
                             seconds_since_last_seen)
                else:
                    if name in self.unavailable_gateways:
                        self.unavailable_gateways.remove(name)
                    self.hub.mark_named_gateway_available(gateway_key, True,
                             seconds_since_last_seen)

                # Check if gateway gone for high timeout (dead)
                if seconds_since_last_seen > self.gateway_dead_timeout:
                    rospy.logwarn("Hub Watcher: gateway " + name +
                                  " has been unavailable for " +
                                  str(self.gateway_dead_timeout) +
                                  " seconds! Removing from hub.")
                    self.hub.unregister_named_gateway(gateway_key)
            rate.sleep()
Esempio n. 6
0
    def register_gateway(self, firewall, unique_gateway_name,
                         remote_gateway_request_callbacks,
                         hub_connection_lost_gateway_hook, gateway_ip):
        '''
          Register a gateway with the hub.

          @param firewall
          @param unique_gateway_name
          @param remote_gateway_request_callbacks
          @param hub_connection_lost_hook : used to trigger Gateway.disengage_hub(hub) on lost hub connections in redis pubsub listener thread.
          @gateway_ip

          @raise HubConnectionLostError if for some reason, the redis server has become unavailable.
        '''
        if not self._redis_server:
            raise HubConnectionLostError()
        self._unique_gateway_name = unique_gateway_name
        self._redis_keys['gateway'] = hub_api.create_rocon_key(
            unique_gateway_name)
        self._redis_keys['firewall'] = hub_api.create_rocon_gateway_key(
            unique_gateway_name, 'firewall')
        self._firewall = 1 if firewall else 0
        self._redis_keys['gatewaylist'] = hub_api.create_rocon_hub_key(
            'gatewaylist')
        self._remote_gateway_request_callbacks = remote_gateway_request_callbacks
        self._hub_connection_lost_gateway_hook = hub_connection_lost_gateway_hook
        if not self._redis_server.sadd(self._redis_keys['gatewaylist'],
                                       self._redis_keys['gateway']):
            # should never get here - unique should be unique
            pass
        unused_ret = self._redis_server.sadd(self._redis_keys['gatewaylist'],
                                             self._redis_keys['gateway'])
        self._redis_server.set(self._redis_keys['firewall'], self._firewall)
        # I think we just used this for debugging, but we might want to hide it in future (it's the ros master hostname/ip)
        self._redis_keys['ip'] = hub_api.create_rocon_gateway_key(
            unique_gateway_name, 'ip')
        self._redis_server.set(self._redis_keys['ip'], gateway_ip)
        self._redis_channels['gateway'] = self._redis_keys['gateway']
        self._redis_pubsub_server.subscribe(self._redis_channels['gateway'])
        self.remote_gateway_listener_thread = RedisListenerThread(
            self._redis_pubsub_server, self._remote_gateway_request_callbacks,
            self._hub_connection_lost_hook)
        self.remote_gateway_listener_thread.start()