blob: 824bc85b6255431a19138a1e82e2142ef9822e3a [file] [log] [blame]
Zsolt Haraszti3eb27a52017-01-03 21:56:48 -08001# Copyright 2017 the original author or authors.
Zsolt Haraszti66862032016-11-28 14:28:39 -08002#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7# http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14#
Zsolt Haraszti3300f742017-01-09 01:14:20 -080015from Queue import Empty as QueueEmpty
Zsolt Haraszti66862032016-11-28 14:28:39 -080016from uuid import uuid4
17
18import structlog
Zsolt Haraszti3300f742017-01-09 01:14:20 -080019from google.protobuf.empty_pb2 import Empty
Zsolt Haraszti66862032016-11-28 14:28:39 -080020from grpc import StatusCode
21
22from common.utils.grpc_utils import twisted_async
khenaidooa8588f22017-06-16 12:13:34 -040023from common.utils.id_generation import create_cluster_device_id
Zsolt Haraszti66862032016-11-28 14:28:39 -080024from voltha.core.config.config_root import ConfigRoot
Zsolt Haraszti217a12e2016-12-19 16:37:55 -080025from voltha.protos.openflow_13_pb2 import PacketIn, Flows, FlowGroups, \
26 ofp_port_status
Zsolt Haraszti66862032016-11-28 14:28:39 -080027from voltha.protos.voltha_pb2 import \
28 add_VolthaLocalServiceServicer_to_server, VolthaLocalServiceServicer, \
29 VolthaInstance, Adapters, LogicalDevices, LogicalDevice, Ports, \
30 LogicalPorts, Devices, Device, DeviceType, \
Stephane Barbarie4db8ca22017-04-24 10:30:20 -040031 DeviceTypes, DeviceGroups, DeviceGroup, AdminState, OperStatus, ChangeEvent, \
32 AlarmFilter, AlarmFilters
Sergio Slobodrian71960022017-03-09 10:20:57 -050033from voltha.protos.device_pb2 import PmConfigs
Zsolt Haraszti66862032016-11-28 14:28:39 -080034from voltha.registry import registry
35
36log = structlog.get_logger()
37
38
39class LocalHandler(VolthaLocalServiceServicer):
khenaidoo032d3302017-06-09 14:50:04 -040040 def __init__(self, core, instance_id, core_store_id, **init_kw):
Zsolt Haraszti66862032016-11-28 14:28:39 -080041 self.core = core
khenaidoo032d3302017-06-09 14:50:04 -040042 self.instance_id = instance_id
43 self.core_store_id = core_store_id
Zsolt Haraszti66862032016-11-28 14:28:39 -080044 self.init_kw = init_kw
45 self.root = None
khenaidoo032d3302017-06-09 14:50:04 -040046 self.started_with_existing_data = False
Zsolt Haraszti66862032016-11-28 14:28:39 -080047 self.stopped = False
48
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080049 def start(self, config_backend=None):
Zsolt Haraszti66862032016-11-28 14:28:39 -080050 log.debug('starting')
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080051 if config_backend:
52 if 'root' in config_backend:
khenaidoo032d3302017-06-09 14:50:04 -040053 # This is going to block the entire reactor until loading is
54 # completed
55 log.info('loading-config-from-persisted-backend')
56 try:
57 self.root = ConfigRoot.load(VolthaInstance,
58 kv_store=config_backend)
59 self.started_with_existing_data = True
60 except Exception, e:
61 log.exception('Failure-loading-from-backend', e=e)
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080062 else:
khenaidoo032d3302017-06-09 14:50:04 -040063 log.info('initializing-a-new-config')
Khen Nursimulud068d812017-03-06 11:44:18 -050064 self.root = ConfigRoot(VolthaInstance(**self.init_kw),
65 kv_store=config_backend)
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080066 else:
67 self.root = ConfigRoot(VolthaInstance(**self.init_kw))
68
Zsolt Haraszti66862032016-11-28 14:28:39 -080069 registry('grpc_server').register(
70 add_VolthaLocalServiceServicer_to_server, self)
71 log.info('started')
72 return self
73
74 def stop(self):
75 log.debug('stopping')
76 self.stopped = True
77 log.info('stopped')
78
79 def get_proxy(self, path, exclusive=False):
80 return self.root.get_proxy(path, exclusive)
81
khenaidoo032d3302017-06-09 14:50:04 -040082 def has_started_with_existing_data(self):
83 return self.started_with_existing_data
84
Zsolt Haraszti66862032016-11-28 14:28:39 -080085 # gRPC service method implementations. BE CAREFUL; THESE ARE CALLED ON
86 # the gRPC threadpool threads.
87
88 @twisted_async
89 def GetVolthaInstance(self, request, context):
90 log.info('grpc-request', request=request)
91 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
92 res = self.root.get('/', depth=depth)
93 return res
94
95 @twisted_async
96 def GetHealth(self, request, context):
97 log.info('grpc-request', request=request)
98 return self.root.get('/health')
99
100 @twisted_async
101 def ListAdapters(self, request, context):
102 log.info('grpc-request', request=request)
103 items = self.root.get('/adapters')
104 return Adapters(items=items)
105
106 @twisted_async
107 def ListLogicalDevices(self, request, context):
108 log.info('grpc-request', request=request)
109 items = self.root.get('/logical_devices')
110 return LogicalDevices(items=items)
111
112 @twisted_async
113 def GetLogicalDevice(self, request, context):
114 log.info('grpc-request', request=request)
115
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800116 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
117
Zsolt Haraszti66862032016-11-28 14:28:39 -0800118 if '/' in request.id:
119 context.set_details(
120 'Malformed logical device id \'{}\''.format(request.id))
121 context.set_code(StatusCode.INVALID_ARGUMENT)
122 return LogicalDevice()
123
124 try:
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800125 return self.root.get('/logical_devices/' + request.id, depth=depth)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800126 except KeyError:
127 context.set_details(
128 'Logical device \'{}\' not found'.format(request.id))
129 context.set_code(StatusCode.NOT_FOUND)
130 return LogicalDevice()
131
132 @twisted_async
133 def ListLogicalDevicePorts(self, request, context):
134 log.info('grpc-request', request=request)
135
136 if '/' in request.id:
137 context.set_details(
138 'Malformed logical device id \'{}\''.format(request.id))
139 context.set_code(StatusCode.INVALID_ARGUMENT)
140 return LogicalPorts()
141
142 try:
Khen Nursimulud068d812017-03-06 11:44:18 -0500143 items = self.root.get(
144 '/logical_devices/{}/ports'.format(request.id))
Zsolt Haraszti66862032016-11-28 14:28:39 -0800145 return LogicalPorts(items=items)
146 except KeyError:
147 context.set_details(
148 'Logical device \'{}\' not found'.format(request.id))
149 context.set_code(StatusCode.NOT_FOUND)
150 return LogicalPorts()
151
152 @twisted_async
153 def ListLogicalDeviceFlows(self, request, context):
154 log.info('grpc-request', request=request)
155
156 if '/' in request.id:
157 context.set_details(
158 'Malformed logical device id \'{}\''.format(request.id))
159 context.set_code(StatusCode.INVALID_ARGUMENT)
160 return Flows()
161
162 try:
Khen Nursimulud068d812017-03-06 11:44:18 -0500163 flows = self.root.get(
164 '/logical_devices/{}/flows'.format(request.id))
Zsolt Haraszti66862032016-11-28 14:28:39 -0800165 return flows
166 except KeyError:
167 context.set_details(
168 'Logical device \'{}\' not found'.format(request.id))
169 context.set_code(StatusCode.NOT_FOUND)
170 return Flows()
171
Zsolt Haraszti66862032016-11-28 14:28:39 -0800172 @twisted_async
173 def UpdateLogicalDeviceFlowTable(self, request, context):
174 log.info('grpc-request', request=request)
175
176 if '/' in request.id:
177 context.set_details(
178 'Malformed logical device id \'{}\''.format(request.id))
179 context.set_code(StatusCode.INVALID_ARGUMENT)
180 return Empty()
181
182 try:
183 agent = self.core.get_logical_device_agent(request.id)
184 agent.update_flow_table(request.flow_mod)
185 return Empty()
186 except KeyError:
187 context.set_details(
188 'Logical device \'{}\' not found'.format(request.id))
189 context.set_code(StatusCode.NOT_FOUND)
190 return Empty()
191
192 @twisted_async
193 def ListLogicalDeviceFlowGroups(self, request, context):
194 log.info('grpc-request', request=request)
195
196 if '/' in request.id:
197 context.set_details(
198 'Malformed logical device id \'{}\''.format(request.id))
199 context.set_code(StatusCode.INVALID_ARGUMENT)
200 return FlowGroups()
201
202 try:
203 groups = self.root.get(
204 '/logical_devices/{}/flow_groups'.format(request.id))
205 return groups
206 except KeyError:
207 context.set_details(
208 'Logical device \'{}\' not found'.format(request.id))
209 context.set_code(StatusCode.NOT_FOUND)
210 return FlowGroups()
211
212 @twisted_async
213 def UpdateLogicalDeviceFlowGroupTable(self, request, context):
214 log.info('grpc-request', request=request)
215
216 if '/' in request.id:
217 context.set_details(
218 'Malformed logical device id \'{}\''.format(request.id))
219 context.set_code(StatusCode.INVALID_ARGUMENT)
220 return Empty()
221
222 try:
223 agent = self.core.get_logical_device_agent(request.id)
224 agent.update_group_table(request.group_mod)
225 return Empty()
226 except KeyError:
227 context.set_details(
228 'Logical device \'{}\' not found'.format(request.id))
229 context.set_code(StatusCode.NOT_FOUND)
230 return Empty()
231
232 @twisted_async
233 def ListDevices(self, request, context):
234 log.info('grpc-request', request=request)
235 items = self.root.get('/devices')
236 return Devices(items=items)
237
238 @twisted_async
239 def GetDevice(self, request, context):
240 log.info('grpc-request', request=request)
241
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800242 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
243
Zsolt Haraszti66862032016-11-28 14:28:39 -0800244 if '/' in request.id:
245 context.set_details(
246 'Malformed device id \'{}\''.format(request.id))
247 context.set_code(StatusCode.INVALID_ARGUMENT)
248 return Device()
249
250 try:
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800251 return self.root.get('/devices/' + request.id, depth=depth)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800252 except KeyError:
253 context.set_details(
254 'Device \'{}\' not found'.format(request.id))
255 context.set_code(StatusCode.NOT_FOUND)
256 return Device()
257
258 @twisted_async
259 def CreateDevice(self, request, context):
260 log.info('grpc-request', request=request)
261
262 known_device_types = dict(
263 (dt.id, dt) for dt in self.root.get('/device_types'))
264
265 try:
266 assert isinstance(request, Device)
267 device = request
268 assert device.id == '', 'Device to be created cannot have id yet'
269 assert device.type in known_device_types, \
270 'Unknown device type \'{}\''.format(device.type)
271 assert device.admin_state in (AdminState.UNKNOWN,
272 AdminState.PREPROVISIONED), \
273 'Newly created device cannot be ' \
274 'in admin state \'{}\''.format(device.admin_state)
275
276 except AssertionError, e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400277 context.set_details(e.message)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800278 context.set_code(StatusCode.INVALID_ARGUMENT)
279 return Device()
280
281 # fill additional data
khenaidooa8588f22017-06-16 12:13:34 -0400282 device.id = create_cluster_device_id(self.core_store_id)
283 log.debug('device-id-created', device_id=device.id)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800284 device_type = known_device_types[device.type]
285 device.adapter = device_type.adapter
286 if device.admin_state != AdminState.PREPROVISIONED:
287 device.admin_state = AdminState.PREPROVISIONED
288 device.oper_status = OperStatus.UNKNOWN
289
290 # add device to tree
291 self.root.add('/devices', device)
292
293 return request
294
295 @twisted_async
Khen Nursimulud068d812017-03-06 11:44:18 -0500296 def EnableDevice(self, request, context):
Zsolt Haraszti66862032016-11-28 14:28:39 -0800297 log.info('grpc-request', request=request)
298
299 if '/' in request.id:
300 context.set_details(
301 'Malformed device id \'{}\''.format(request.id))
302 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400303 return Empty()
Zsolt Haraszti66862032016-11-28 14:28:39 -0800304
305 try:
306 path = '/devices/{}'.format(request.id)
307 device = self.root.get(path)
Khen Nursimulud068d812017-03-06 11:44:18 -0500308 assert device.admin_state in (AdminState.PREPROVISIONED,
309 AdminState.DISABLED), \
310 'Device to enable cannot be ' \
311 'in admin state \'{}\''.format(device.admin_state)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800312 device.admin_state = AdminState.ENABLED
313 self.root.update(path, device, strict=True)
314
Khen Nursimulud068d812017-03-06 11:44:18 -0500315 except AssertionError, e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400316 context.set_details(e.message)
Khen Nursimulud068d812017-03-06 11:44:18 -0500317 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimulud068d812017-03-06 11:44:18 -0500318
319 except KeyError:
320 context.set_details(
321 'Device \'{}\' not found'.format(request.id))
322 context.set_code(StatusCode.NOT_FOUND)
323
324 return Empty()
325
326 @twisted_async
327 def DisableDevice(self, request, context):
328 log.info('grpc-request', request=request)
329
330 if '/' in request.id:
331 context.set_details(
332 'Malformed device id \'{}\''.format(request.id))
333 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400334 return Empty()
Khen Nursimulud068d812017-03-06 11:44:18 -0500335 try:
336 path = '/devices/{}'.format(request.id)
337 device = self.root.get(path)
338 assert device.admin_state == AdminState.ENABLED, \
339 'Device to disable cannot be ' \
340 'in admin state \'{}\''.format(device.admin_state)
341 device.admin_state = AdminState.DISABLED
342 self.root.update(path, device, strict=True)
343
344 except AssertionError, e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400345 context.set_details(e.message)
Khen Nursimulud068d812017-03-06 11:44:18 -0500346 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimulud068d812017-03-06 11:44:18 -0500347
348 except KeyError:
349 context.set_details(
350 'Device \'{}\' not found'.format(request.id))
351 context.set_code(StatusCode.NOT_FOUND)
352
khenaidoo032d3302017-06-09 14:50:04 -0400353 except Exception, e:
354 log.exception('disable-exception', e=e)
355
Khen Nursimulud068d812017-03-06 11:44:18 -0500356 return Empty()
357
358 @twisted_async
359 def RebootDevice(self, request, context):
360 log.info('grpc-request', request=request)
361
362 if '/' in request.id:
363 context.set_details(
364 'Malformed device id \'{}\''.format(request.id))
365 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400366 return Empty()
Khen Nursimulud068d812017-03-06 11:44:18 -0500367
368 try:
369 path = '/devices/{}'.format(request.id)
370 device = self.root.get(path)
371
372 agent = self.core.get_device_agent(device.id)
373 agent.reboot_device(device)
374
Khen Nursimulud068d812017-03-06 11:44:18 -0500375 except KeyError:
376 context.set_details(
377 'Device \'{}\' not found'.format(request.id))
378 context.set_code(StatusCode.NOT_FOUND)
379
380 return Empty()
381
382 @twisted_async
383 def DeleteDevice(self, request, context):
384 log.info('grpc-request', request=request)
385
386 if '/' in request.id:
387 context.set_details(
388 'Malformed device id \'{}\''.format(request.id))
389 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400390 return Empty()
Khen Nursimulud068d812017-03-06 11:44:18 -0500391
392 try:
393 path = '/devices/{}'.format(request.id)
394 device = self.root.get(path)
395 assert device.admin_state == AdminState.DISABLED, \
396 'Device to delete cannot be ' \
397 'in admin state \'{}\''.format(device.admin_state)
398
399 self.root.remove(path)
400
401 except AssertionError, e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400402 context.set_details(e.message)
Khen Nursimulud068d812017-03-06 11:44:18 -0500403 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimulud068d812017-03-06 11:44:18 -0500404
Zsolt Haraszti66862032016-11-28 14:28:39 -0800405 except KeyError:
406 context.set_details(
407 'Device \'{}\' not found'.format(request.id))
408 context.set_code(StatusCode.NOT_FOUND)
409
410 return Empty()
411
412 @twisted_async
413 def ListDevicePorts(self, request, context):
414 log.info('grpc-request', request=request)
415
416 if '/' in request.id:
417 context.set_details(
418 'Malformed device id \'{}\''.format(request.id))
419 context.set_code(StatusCode.INVALID_ARGUMENT)
420 return Ports()
421
422 try:
423 items = self.root.get('/devices/{}/ports'.format(request.id))
424 return Ports(items=items)
425 except KeyError:
426 context.set_details(
427 'Device \'{}\' not found'.format(request.id))
428 context.set_code(StatusCode.NOT_FOUND)
429 return Ports()
430
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500431 @twisted_async
432 def ListDevicePmConfigs(self, request, context):
Sergio Slobodrian71960022017-03-09 10:20:57 -0500433 log.info('grpc-request', request=request)
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500434
Sergio Slobodrian71960022017-03-09 10:20:57 -0500435 if '/' in request.id:
436 context.set_details(
437 'Malformed device id \'{}\''.format(request.id))
438 context.set_code(StatusCode.INVALID_ARGUMENT)
439 return PmConfigs()
440
441 try:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400442 pm_configs = self.root.get(
443 '/devices/{}/pm_configs'.format(request.id))
Sergio Slobodrian2db4c102017-03-09 22:29:23 -0500444 pm_configs.id = request.id
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400445 log.info('device-for-pms', pm_configs=pm_configs)
Sergio Slobodrian2db4c102017-03-09 22:29:23 -0500446 return pm_configs
Sergio Slobodrian71960022017-03-09 10:20:57 -0500447 except KeyError:
448 context.set_details(
449 'Device \'{}\' not found'.format(request.id))
450 context.set_code(StatusCode.NOT_FOUND)
451 return PmConfigs()
452
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500453 @twisted_async
454 def UpdateDevicePmConfigs(self, request, context):
Sergio Slobodrian2db4c102017-03-09 22:29:23 -0500455 log.info('grpc-request', request=request)
456
457 if '/' in request.id:
458 context.set_details(
459 'Malformed logical device id \'{}\''.format(request.id))
460 context.set_code(StatusCode.INVALID_ARGUMENT)
461 return Empty()
462
463 try:
464 device = self.root.get('/devices/{}'.format(request.id))
465 agent = self.core.get_device_agent(request.id)
466 agent.update_device_pm_config(request)
467 return Empty()
468 except KeyError:
469 context.set_details(
470 'Device \'{}\' not found'.format(request.id))
471 context.set_code(StatusCode.NOT_FOUND)
472 return Empty()
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500473
Zsolt Haraszti66862032016-11-28 14:28:39 -0800474 @twisted_async
475 def ListDeviceFlows(self, request, context):
476 log.info('grpc-request', request=request)
477
478 if '/' in request.id:
479 context.set_details(
480 'Malformed device id \'{}\''.format(request.id))
481 context.set_code(StatusCode.INVALID_ARGUMENT)
482 return Flows()
483
484 try:
485 flows = self.root.get('/devices/{}/flows'.format(request.id))
486 return flows
487 except KeyError:
488 context.set_details(
489 'Device \'{}\' not found'.format(request.id))
490 context.set_code(StatusCode.NOT_FOUND)
491 return Flows()
492
Zsolt Haraszti66862032016-11-28 14:28:39 -0800493 @twisted_async
494 def ListDeviceFlowGroups(self, request, context):
495 log.info('grpc-request', request=request)
496
497 if '/' in request.id:
498 context.set_details(
499 'Malformed device id \'{}\''.format(request.id))
500 context.set_code(StatusCode.INVALID_ARGUMENT)
501 return FlowGroups()
502
503 try:
Khen Nursimulud068d812017-03-06 11:44:18 -0500504 groups = self.root.get(
505 '/devices/{}/flow_groups'.format(request.id))
Zsolt Haraszti66862032016-11-28 14:28:39 -0800506 return groups
507 except KeyError:
508 context.set_details(
509 'Device \'{}\' not found'.format(request.id))
510 context.set_code(StatusCode.NOT_FOUND)
511 return FlowGroups()
512
513 @twisted_async
514 def ListDeviceTypes(self, request, context):
515 log.info('grpc-request', request=request)
516 items = self.root.get('/device_types')
517 return DeviceTypes(items=items)
518
519 @twisted_async
520 def GetDeviceType(self, request, context):
521 log.info('grpc-request', request=request)
522
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800523 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
524
Zsolt Haraszti66862032016-11-28 14:28:39 -0800525 if '/' in request.id:
526 context.set_details(
527 'Malformed device type id \'{}\''.format(request.id))
528 context.set_code(StatusCode.INVALID_ARGUMENT)
529 return DeviceType()
530
531 try:
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800532 return self.root.get('/device_types/' + request.id, depth=depth)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800533 except KeyError:
534 context.set_details(
535 'Device type \'{}\' not found'.format(request.id))
536 context.set_code(StatusCode.NOT_FOUND)
537 return DeviceType()
538
539 @twisted_async
540 def ListDeviceGroups(self, request, context):
541 log.info('grpc-request', request=request)
542 # TODO is this mapped to tree or taken from coordinator?
543 items = self.root.get('/device_groups')
544 return DeviceGroups(items=items)
545
546 @twisted_async
547 def GetDeviceGroup(self, request, context):
548 log.info('grpc-request', request=request)
549
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800550 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
551
Zsolt Haraszti66862032016-11-28 14:28:39 -0800552 if '/' in request.id:
553 context.set_details(
554 'Malformed device group id \'{}\''.format(request.id))
555 context.set_code(StatusCode.INVALID_ARGUMENT)
556 return DeviceGroup()
557
558 # TODO is this mapped to tree or taken from coordinator?
559 try:
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800560 return self.root.get('/device_groups/' + request.id, depth=depth)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800561 except KeyError:
562 context.set_details(
563 'Device group \'{}\' not found'.format(request.id))
564 context.set_code(StatusCode.NOT_FOUND)
565 return DeviceGroup()
566
567 def StreamPacketsOut(self, request_iterator, context):
568
569 @twisted_async
570 def forward_packet_out(packet_out):
571 agent = self.core.get_logical_device_agent(packet_out.id)
572 agent.packet_out(packet_out.packet_out)
573
574 for request in request_iterator:
575 forward_packet_out(packet_out=request)
576
577 return Empty()
578
579 def ReceivePacketsIn(self, request, context):
580 while 1:
Zsolt Haraszti3300f742017-01-09 01:14:20 -0800581 try:
582 packet_in = self.core.packet_in_queue.get(timeout=1)
583 yield packet_in
584 except QueueEmpty:
585 if self.stopped:
586 break
Zsolt Haraszti66862032016-11-28 14:28:39 -0800587
588 def send_packet_in(self, device_id, ofp_packet_in):
589 """Must be called on the twisted thread"""
590 packet_in = PacketIn(id=device_id, packet_in=ofp_packet_in)
591 self.core.packet_in_queue.put(packet_in)
Zsolt Haraszti217a12e2016-12-19 16:37:55 -0800592
593 def ReceiveChangeEvents(self, request, context):
594 while 1:
Zsolt Haraszti3300f742017-01-09 01:14:20 -0800595 try:
596 event = self.core.change_event_queue.get(timeout=1)
597 yield event
598 except QueueEmpty:
599 if self.stopped:
600 break
Zsolt Haraszti217a12e2016-12-19 16:37:55 -0800601
602 def send_port_change_event(self, device_id, port_status):
603 """Must be called on the twisted thread"""
604 assert isinstance(port_status, ofp_port_status)
605 event = ChangeEvent(id=device_id, port_status=port_status)
606 self.core.change_event_queue.put(event)
Stephane Barbarie4db8ca22017-04-24 10:30:20 -0400607
608
609 @twisted_async
610 def ListAlarmFilters(self, request, context):
611 try:
612 filters = self.root.get('/alarm_filters')
613 return AlarmFilters(filters=filters)
614 except KeyError:
615 context.set_code(StatusCode.NOT_FOUND)
616 return AlarmFilters()
617
618 @twisted_async
619 def GetAlarmFilter(self, request, context):
620 if '/' in request.id:
621 context.set_details(
622 'Malformed alarm filter id \'{}\''.format(request.id))
623 context.set_code(StatusCode.INVALID_ARGUMENT)
624 return AlarmFilter()
625
626 try:
627 alarm_filter = self.root.get('/alarm_filters/{}'.format(request.id))
628 return alarm_filter
629 except KeyError:
630 context.set_details(
631 'Alarm filter \'{}\' not found'.format(request.id))
632 context.set_code(StatusCode.NOT_FOUND)
633 return AlarmFilter()
634
635 @twisted_async
636 def DeleteAlarmFilter(self, request, context):
637 if '/' in request.id:
638 context.set_details(
639 'Malformed alarm filter id \'{}\''.format(request.id))
640 context.set_code(StatusCode.INVALID_ARGUMENT)
641 return Empty()
642
643 try:
644 self.root.remove('/alarm_filters/{}'.format(request.id))
645 except KeyError:
646 context.set_code(StatusCode.NOT_FOUND)
647
648 return Empty()
649
650 @twisted_async
651 def CreateAlarmFilter(self, request, context):
652 log.info('grpc-request', request=request)
653
654 try:
655 assert isinstance(request, AlarmFilter)
656 alarm_filter = request
657 assert alarm_filter.id == '', 'Alarm filter to be created cannot have id yet'
658
659 except AssertionError, e:
660 context.set_details(e.message)
661 context.set_code(StatusCode.INVALID_ARGUMENT)
662 return AlarmFilter()
663
664 # fill additional data
665 alarm_filter.id = uuid4().hex[:12]
666
667 # add device to tree
668 self.root.add('/alarm_filters', alarm_filter)
669
670 return request
671
672 @twisted_async
673 def UpdateAlarmFilter(self, request, context):
674 if '/' in request.id:
675 context.set_details(
676 'Malformed alarm filter id \'{}\''.format(request.id))
677 context.set_code(StatusCode.INVALID_ARGUMENT)
678 return AlarmFilter()
679
680 try:
681 assert isinstance(request, AlarmFilter)
682 alarm_filter = self.root.get('/alarm_filters/{}'.format(request.id))
683 self.root.update('/alarm_filters/{}'.format(request.id), request)
684
685 return request
686 except KeyError:
687 context.set_details(
688 'Alarm filter \'{}\' not found'.format(request.id))
689 context.set_code(StatusCode.NOT_FOUND)
690 return AlarmFilter()