Go to the documentation of this file.00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011 import re
00012 import copy
00013 import threading
00014
00015 from gateway_msgs.msg import RemoteRule
00016
00017 from . import utils
00018
00019
00020
00021
00022
00023
00024 class InteractiveInterface(object):
00025
00026 '''
00027 Parent interface for flip and pull interfaces.
00028 '''
00029
00030 def __init__(self, default_rule_blacklist, default_rules, all_targets):
00031 '''
00032 @param default_rule_blacklist : used when in flip/pull all mode
00033 @type dictionary of gateway
00034 @param default_rules : static rules to flip/pull on startup
00035 @type gateway_msgs.msg.RemoteRule[]
00036 @param all_targets : static flip/pull all targets to flip/pull to on startup
00037 @type string[]
00038 '''
00039
00040
00041
00042
00043 self.active = utils.create_empty_connection_type_dictionary()
00044
00045
00046
00047 self._default_blacklist = default_rule_blacklist
00048
00049
00050
00051 self.watchlist = utils.create_empty_connection_type_dictionary()
00052
00053
00054
00055 self.registrations = utils.create_empty_connection_type_dictionary()
00056
00057
00058
00059 self._blacklist = {}
00060
00061 self._lock = threading.Lock()
00062
00063
00064 for rule in default_rules:
00065 self.add_rule(rule)
00066 for gateway in all_targets:
00067 self.add_all(gateway, [])
00068
00069
00070
00071
00072
00073 def add_rule(self, remote_rule):
00074 '''
00075 Add a remote rule to the watchlist for monitoring.
00076
00077 @param remote_rule : the remote rule to add to the watchlist
00078 @type gateway_msgs.msg.RemoteRule
00079
00080 @return the remote rule, or None if the rule already exists.
00081 @rtype gateway_msgs.msg.RemoteRule || None
00082 '''
00083 result = None
00084 self._lock.acquire()
00085 rule_already_exists = False
00086
00087
00088 for watched_rule in self.watchlist[remote_rule.rule.type]:
00089 if watched_rule.gateway == remote_rule.gateway and \
00090 watched_rule.rule.name == remote_rule.rule.name and \
00091 watched_rule.rule.node == remote_rule.rule.node:
00092 rule_already_exists = True
00093 break
00094 if not rule_already_exists:
00095 self.watchlist[remote_rule.rule.type].append(remote_rule)
00096 result = remote_rule
00097 self._lock.release()
00098 return result
00099
00100 def remove_rule(self, remote_rule):
00101 '''
00102 Remove a rule. Be a bit careful looking for a rule to remove, depending
00103 on the node name, which can be set (exact rule/node name match) or
00104 None in which case all nodes of that kind of flip will match.
00105
00106 Handle the remapping appropriately.
00107
00108 @param remote_rule : the remote rule to remove from the watchlist.
00109 @type gateway_msgs.msg.RemoteRule
00110
00111 @return Rules remaining in the watchlist
00112 @rtype RemoteRule[]
00113 '''
00114 if remote_rule.rule.node:
00115
00116 try:
00117 self._lock.acquire()
00118 self.watchlist[remote_rule.rule.type].remove(remote_rule)
00119 self._lock.release()
00120 return [remote_rule]
00121 except ValueError:
00122 self._lock.release()
00123 return []
00124 else:
00125
00126 existing_rules = []
00127 self._lock.acquire()
00128 for existing_rule in self.watchlist[remote_rule.rule.type]:
00129 if (existing_rule.gateway == remote_rule.gateway) and \
00130 (existing_rule.rule.name == remote_rule.rule.name):
00131 existing_rules.append(existing_rule)
00132 for rule in existing_rules:
00133 self.watchlist[remote_rule.rule.type].remove(rule)
00134 self._lock.release()
00135 return existing_rules
00136
00137 def add_all(self, gateway, blacklist):
00138 '''
00139 Instead of watching/acting on specific rules, take action
00140 on everything except for rules in a blacklist.
00141
00142 @param gateway : target remote gateway string id
00143 @type str
00144
00145 @param blacklist : do not act on rules matching these patterns
00146 @type gateway_msgs.msg.Rule[]
00147
00148 @return success or failure depending on if it ahs already been set or not
00149 @rtype Bool
00150 '''
00151 self._lock.acquire()
00152
00153 if gateway in self._blacklist:
00154 self._lock.release()
00155 return False
00156 self._blacklist[gateway] = self._default_blacklist
00157 for rule in blacklist:
00158 self._blacklist[gateway][rule.type].append(rule)
00159
00160 for connection_type in utils.connection_types:
00161 remote_rule = RemoteRule()
00162 remote_rule.gateway = gateway
00163 remote_rule.rule.name = '.*'
00164 remote_rule.rule.node = None
00165 remote_rule.rule.type = connection_type
00166
00167 self.watchlist[connection_type][:] = [
00168 rule for rule in self.watchlist[connection_type] if rule.gateway != gateway]
00169
00170 self.watchlist[connection_type].append(remote_rule)
00171 self._lock.release()
00172 return True
00173
00174 def remove_all(self, gateway):
00175 '''
00176 Remove the add all rule for the specified gateway.
00177
00178 @param gateway : target remote gateway string id
00179 @type str
00180 '''
00181 self._lock.acquire()
00182 if gateway in self._blacklist:
00183 del self._blacklist[gateway]
00184 for connection_type in utils.connection_types:
00185 for rule in self.watchlist[connection_type]:
00186 if rule.gateway == gateway:
00187
00188 try:
00189 self.watchlist[connection_type].remove(rule)
00190 except ValueError:
00191 pass
00192 self._lock.release()
00193
00194
00195
00196
00197
00198 def is_matched(self, rule, rule_name, name, node):
00199 matched = False
00200 name_match_result = re.match(rule_name, name)
00201 if name_match_result and name_match_result.group() == name:
00202 if utils.is_all_pattern(rule_name):
00203 if self._is_in_blacklist(rule.gateway, rule.rule.type, name, node):
00204 return False
00205 if rule.rule.node:
00206 node_match_result = re.match(rule.rule.node, node)
00207 if node_match_result and node_match_result.group() == node:
00208 matched = True
00209 else:
00210 matched = True
00211 return matched
00212
00213 def getLocalRegistrations(self):
00214 '''
00215 Gets the local registrations for GatewayInfo consumption (flipped ins/pulls).
00216
00217 We don't need to show the service and node uri's here.
00218
00219 Basic operation : convert Registration -> RemoteRule for each registration
00220
00221 @return the list of registrations corresponding to remote interactions
00222 @rtype RemoteRule[]
00223 '''
00224 local_registrations = []
00225 for connection_type in utils.connection_types:
00226 for registration in self.registrations[connection_type]:
00227 remote_rule = RemoteRule()
00228 remote_rule.gateway = registration.remote_gateway
00229 remote_rule.rule.name = registration.connection.rule.name
00230 remote_rule.rule.node = registration.connection.rule.node
00231 remote_rule.rule.type = connection_type
00232 local_registrations.append(remote_rule)
00233 return local_registrations
00234
00235 def getWatchlist(self):
00236 '''
00237 Gets the watchlist for GatewayInfo consumption.
00238
00239 @return the list of flip rules that are being watched
00240 @rtype gateway_msgs.msg.RemoteRule[]
00241 '''
00242 watchlist = []
00243 for connection_type in utils.connection_types:
00244 watchlist.extend(copy.deepcopy(self.watchlist[connection_type]))
00245
00246 for remote in watchlist:
00247 if not remote.rule.node:
00248 remote.rule.node = 'None'
00249 return watchlist
00250
00251
00252
00253
00254
00255 def find_registration_match(self, remote_gateway, remote_name, remote_node, connection_type):
00256 '''
00257 Check to see if a registration exists. Note that it doesn't use the
00258 local node name in the check. We will get things like unflip requests that
00259 don't have this variable set (that gets autogenerated when registering
00260 the flip), but we need to find the matching registration.
00261
00262 We then return the registration that matches.
00263
00264 @param remote_gateway : string remote gateway id
00265 @type string
00266 @param remote_name, remote_node, connection_type : remote connection details
00267 @type string
00268
00269 @return matching registration or none
00270 @rtype utils.Registration
00271 '''
00272
00273 matched_registration = None
00274 self._lock.acquire()
00275 for registration in self.registrations[connection_type]:
00276 if (registration.remote_gateway == remote_gateway) and \
00277 (registration.connection.rule.name == remote_name) and \
00278 (registration.connection.rule.node == remote_node) and \
00279 (registration.connection.rule.type == connection_type):
00280 matched_registration = registration
00281 break
00282 else:
00283 continue
00284 self._lock.release()
00285 return matched_registration
00286
00287 def _is_in_blacklist(self, gateway, connection_type, name, node):
00288 '''
00289 Check if a particular connection is in the blacklist. Use this to
00290 filter connections from the flip_all command.
00291
00292 @todo move to utils - should be shared with the public interface.
00293 '''
00294 for blacklist_rule in self._blacklist[gateway][connection_type]:
00295 name_match_result = re.match(blacklist_rule.name, name)
00296 if name_match_result and name_match_result.group() == name:
00297 if blacklist_rule.node:
00298 node_match_result = re.match(blacklist_rule.node, node)
00299 if node_match_result and node_match_result.group() == node:
00300 return True
00301 else:
00302 return True
00303 return False