1
2
3
4
5
6
7
8
9
10
11 import threading
12 from gateway_msgs.msg import RemoteRule
13 import re
14 import copy
15
16
17 import utils
18
19
20
21
22
23
25 '''
26 Parent interface for flip and pull interfaces.
27 '''
28 - def __init__(self, default_rule_blacklist, default_rules, all_targets):
62
63
64
65
66
68 '''
69 Add a remote rule to the watchlist for monitoring.
70
71 @param remote_rule : the remote rule to add to the watchlist
72 @type gateway_msgs.msg.RemoteRule
73
74 @return the remote rule, or None if the rule already exists.
75 @rtype gateway_msgs.msg.RemoteRule || None
76 '''
77 result = None
78 self._lock.acquire()
79 rule_already_exists = False
80
81
82 for watched_rule in self.watchlist[remote_rule.rule.type]:
83 if watched_rule.gateway == remote_rule.gateway and \
84 watched_rule.rule.name == remote_rule.rule.name and \
85 watched_rule.rule.node == remote_rule.rule.node:
86 rule_already_exists = True
87 break
88 if not rule_already_exists:
89 self.watchlist[remote_rule.rule.type].append(remote_rule)
90 result = remote_rule
91 self._lock.release()
92 return result
93
95 '''
96 Remove a rule. Be a bit careful looking for a rule to remove, depending
97 on the node name, which can be set (exact rule/node name match) or
98 None in which case all nodes of that kind of flip will match.
99
100 Handle the remapping appropriately.
101
102 @param remote_rule : the remote rule to remove from the watchlist.
103 @type gateway_msgs.msg.RemoteRule
104
105 @return Rules remaining in the watchlist
106 @rtype RemoteRule[]
107 '''
108 if remote_rule.rule.node:
109
110 try:
111 self._lock.acquire()
112 self.watchlist[remote_rule.rule.type].remove(remote_rule)
113 self._lock.release()
114 return [remote_rule]
115 except ValueError:
116 self._lock.release()
117 return []
118 else:
119
120 existing_rules = []
121 self._lock.acquire()
122 for existing_rule in self.watchlist[remote_rule.rule.type]:
123 if (existing_rule.gateway == remote_rule.gateway) and \
124 (existing_rule.rule.name == remote_rule.rule.name):
125 existing_rules.append(existing_rule)
126 for rule in existing_rules:
127 self.watchlist[remote_rule.rule.type].remove(rule)
128 self._lock.release()
129 return existing_rules
130
131 - def add_all(self, gateway, blacklist):
132 '''
133 Instead of watching/acting on specific rules, take action
134 on everything except for rules in a blacklist.
135
136 @param gateway : target remote gateway string id
137 @type str
138
139 @param blacklist : do not act on rules matching these patterns
140 @type gateway_msgs.msg.Rule[]
141
142 @return success or failure depending on if it ahs already been set or not
143 @rtype Bool
144 '''
145 self._lock.acquire()
146
147 if gateway in self._blacklist:
148 self._lock.release()
149 return False
150 self._blacklist[gateway] = self._default_blacklist
151 for rule in blacklist:
152 self._blacklist[gateway][rule.type].append(rule)
153
154 for connection_type in utils.connection_types:
155 remote_rule = RemoteRule()
156 remote_rule.gateway = gateway
157 remote_rule.rule.name = '.*'
158 remote_rule.rule.node = None
159 remote_rule.rule.type = connection_type
160
161 self.watchlist[connection_type][:] = [rule for rule in self.watchlist[connection_type] if rule.gateway != gateway]
162
163 self.watchlist[connection_type].append(remote_rule)
164 self._lock.release()
165 return True
166
168 '''
169 Remove the add all rule for the specified gateway.
170
171 @param gateway : target remote gateway string id
172 @type str
173 '''
174 self._lock.acquire()
175 if gateway in self._blacklist:
176 del self._blacklist[gateway]
177 for connection_type in utils.connection_types:
178 for rule in self.watchlist[connection_type]:
179 if rule.gateway == gateway:
180
181 try:
182 self.watchlist[connection_type].remove(rule)
183 except ValueError:
184 pass
185 self._lock.release()
186
187
188
189
190
191 - def is_matched(self, rule, rule_name, name, node):
192 matched = False
193 name_match_result = re.match(rule_name, name)
194 if name_match_result and name_match_result.group() == name:
195 if utils.is_all_pattern(rule_name):
196 if self._is_in_blacklist(rule.gateway, rule.rule.type, name, node):
197 return False
198 if rule.rule.node:
199 node_match_result = re.match(rule.rule.node, node)
200 if node_match_result and node_match_result.group() == node:
201 matched = True
202 else:
203 matched = True
204 return matched
205
207 '''
208 Gets the local registrations for GatewayInfo consumption (flipped ins/pulls).
209
210 We don't need to show the service and node uri's here.
211
212 Basic operation : convert Registration -> RemoteRule for each registration
213
214 @return the list of registrations corresponding to remote interactions
215 @rtype RemoteRule[]
216 '''
217 local_registrations = []
218 for connection_type in utils.connection_types:
219 for registration in self.registrations[connection_type]:
220 remote_rule = RemoteRule()
221 remote_rule.gateway = registration.remote_gateway
222 remote_rule.rule.name = registration.connection.rule.name
223 remote_rule.rule.node = registration.connection.rule.node
224 remote_rule.rule.type = connection_type
225 local_registrations.append(remote_rule)
226 return local_registrations
227
229 '''
230 Gets the watchlist for GatewayInfo consumption.
231
232 @return the list of flip rules that are being watched
233 @rtype gateway_msgs.msg.RemoteRule[]
234 '''
235 watchlist = []
236 for connection_type in utils.connection_types:
237 watchlist.extend(copy.deepcopy(self.watchlist[connection_type]))
238
239 for remote in watchlist:
240 if not remote.rule.node:
241 remote.rule.node = 'None'
242 return watchlist
243
244
245
246
247
249 '''
250 Check to see if a registration exists. Note that it doesn't use the
251 local node name in the check. We will get things like unflip requests that
252 don't have this variable set (that gets autogenerated when registering
253 the flip), but we need to find the matching registration.
254
255 We then return the registration that matches.
256
257 @param remote_gateway : string remote gateway id
258 @type string
259 @param remote_name, remote_node, connection_type : remote connection details
260 @type string
261
262 @return matching registration or none
263 @rtype utils.Registration
264 '''
265
266 matched_registration = None
267 self._lock.acquire()
268 for registration in self.registrations[connection_type]:
269 if (registration.remote_gateway == remote_gateway) and \
270 (registration.connection.rule.name == remote_name) and \
271 (registration.connection.rule.node == remote_node) and \
272 (registration.connection.rule.type == connection_type):
273 matched_registration = registration
274 break
275 else:
276 continue
277 self._lock.release()
278 return matched_registration
279
281 '''
282 Check if a particular connection is in the blacklist. Use this to
283 filter connections from the flip_all command.
284
285 @todo move to utils - should be shared with the public interface.
286 '''
287 for blacklist_rule in self._blacklist[gateway][connection_type]:
288 name_match_result = re.match(blacklist_rule.name, name)
289 if name_match_result and name_match_result.group() == name:
290 if blacklist_rule.node:
291 node_match_result = re.match(blacklist_rule.node, node)
292 if node_match_result and node_match_result.group() == node:
293 return True
294 else:
295 return True
296 return False
297