blob: 13e8b682961d50d34f8f4668d47472b11bd9a62d [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
23from voltha.core.config.config_root import ConfigRoot
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080024from voltha.core.config.config_backend import ConsulStore
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 Barbarieee409292017-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):
Zsolt Haraszti66862032016-11-28 14:28:39 -080040 def __init__(self, core, **init_kw):
41 self.core = core
42 self.init_kw = init_kw
43 self.root = None
44 self.stopped = False
45
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080046 def start(self, config_backend=None):
Zsolt Haraszti66862032016-11-28 14:28:39 -080047 log.debug('starting')
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080048 if config_backend:
49 if 'root' in config_backend:
50 # This is going to block the entire reactor until loading is completed
51 log.info('loading config from persisted backend')
Khen Nursimulud068d812017-03-06 11:44:18 -050052 self.root = ConfigRoot.load(VolthaInstance,
53 kv_store=config_backend)
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080054 else:
55 log.info('initializing new config')
Khen Nursimulud068d812017-03-06 11:44:18 -050056 self.root = ConfigRoot(VolthaInstance(**self.init_kw),
57 kv_store=config_backend)
Ryan Van Gilder5a0ab622017-03-01 16:39:25 -080058 else:
59 self.root = ConfigRoot(VolthaInstance(**self.init_kw))
60
Zsolt Haraszti66862032016-11-28 14:28:39 -080061 registry('grpc_server').register(
62 add_VolthaLocalServiceServicer_to_server, self)
63 log.info('started')
64 return self
65
66 def stop(self):
67 log.debug('stopping')
68 self.stopped = True
69 log.info('stopped')
70
71 def get_proxy(self, path, exclusive=False):
72 return self.root.get_proxy(path, exclusive)
73
74 # gRPC service method implementations. BE CAREFUL; THESE ARE CALLED ON
75 # the gRPC threadpool threads.
76
77 @twisted_async
78 def GetVolthaInstance(self, request, context):
79 log.info('grpc-request', request=request)
80 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
81 res = self.root.get('/', depth=depth)
82 return res
83
84 @twisted_async
85 def GetHealth(self, request, context):
86 log.info('grpc-request', request=request)
87 return self.root.get('/health')
88
89 @twisted_async
90 def ListAdapters(self, request, context):
91 log.info('grpc-request', request=request)
92 items = self.root.get('/adapters')
93 return Adapters(items=items)
94
95 @twisted_async
96 def ListLogicalDevices(self, request, context):
97 log.info('grpc-request', request=request)
98 items = self.root.get('/logical_devices')
99 return LogicalDevices(items=items)
100
101 @twisted_async
102 def GetLogicalDevice(self, request, context):
103 log.info('grpc-request', request=request)
104
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800105 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
106
Zsolt Haraszti66862032016-11-28 14:28:39 -0800107 if '/' in request.id:
108 context.set_details(
109 'Malformed logical device id \'{}\''.format(request.id))
110 context.set_code(StatusCode.INVALID_ARGUMENT)
111 return LogicalDevice()
112
113 try:
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800114 return self.root.get('/logical_devices/' + request.id, depth=depth)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800115 except KeyError:
116 context.set_details(
117 'Logical device \'{}\' not found'.format(request.id))
118 context.set_code(StatusCode.NOT_FOUND)
119 return LogicalDevice()
120
121 @twisted_async
122 def ListLogicalDevicePorts(self, request, context):
123 log.info('grpc-request', request=request)
124
125 if '/' in request.id:
126 context.set_details(
127 'Malformed logical device id \'{}\''.format(request.id))
128 context.set_code(StatusCode.INVALID_ARGUMENT)
129 return LogicalPorts()
130
131 try:
Khen Nursimulud068d812017-03-06 11:44:18 -0500132 items = self.root.get(
133 '/logical_devices/{}/ports'.format(request.id))
Zsolt Haraszti66862032016-11-28 14:28:39 -0800134 return LogicalPorts(items=items)
135 except KeyError:
136 context.set_details(
137 'Logical device \'{}\' not found'.format(request.id))
138 context.set_code(StatusCode.NOT_FOUND)
139 return LogicalPorts()
140
141 @twisted_async
142 def ListLogicalDeviceFlows(self, request, context):
143 log.info('grpc-request', request=request)
144
145 if '/' in request.id:
146 context.set_details(
147 'Malformed logical device id \'{}\''.format(request.id))
148 context.set_code(StatusCode.INVALID_ARGUMENT)
149 return Flows()
150
151 try:
Khen Nursimulud068d812017-03-06 11:44:18 -0500152 flows = self.root.get(
153 '/logical_devices/{}/flows'.format(request.id))
Zsolt Haraszti66862032016-11-28 14:28:39 -0800154 return flows
155 except KeyError:
156 context.set_details(
157 'Logical device \'{}\' not found'.format(request.id))
158 context.set_code(StatusCode.NOT_FOUND)
159 return Flows()
160
Zsolt Haraszti66862032016-11-28 14:28:39 -0800161 @twisted_async
162 def UpdateLogicalDeviceFlowTable(self, request, context):
163 log.info('grpc-request', request=request)
164
165 if '/' in request.id:
166 context.set_details(
167 'Malformed logical device id \'{}\''.format(request.id))
168 context.set_code(StatusCode.INVALID_ARGUMENT)
169 return Empty()
170
171 try:
172 agent = self.core.get_logical_device_agent(request.id)
173 agent.update_flow_table(request.flow_mod)
174 return Empty()
175 except KeyError:
176 context.set_details(
177 'Logical device \'{}\' not found'.format(request.id))
178 context.set_code(StatusCode.NOT_FOUND)
179 return Empty()
180
181 @twisted_async
182 def ListLogicalDeviceFlowGroups(self, request, context):
183 log.info('grpc-request', request=request)
184
185 if '/' in request.id:
186 context.set_details(
187 'Malformed logical device id \'{}\''.format(request.id))
188 context.set_code(StatusCode.INVALID_ARGUMENT)
189 return FlowGroups()
190
191 try:
192 groups = self.root.get(
193 '/logical_devices/{}/flow_groups'.format(request.id))
194 return groups
195 except KeyError:
196 context.set_details(
197 'Logical device \'{}\' not found'.format(request.id))
198 context.set_code(StatusCode.NOT_FOUND)
199 return FlowGroups()
200
201 @twisted_async
202 def UpdateLogicalDeviceFlowGroupTable(self, request, context):
203 log.info('grpc-request', request=request)
204
205 if '/' in request.id:
206 context.set_details(
207 'Malformed logical device id \'{}\''.format(request.id))
208 context.set_code(StatusCode.INVALID_ARGUMENT)
209 return Empty()
210
211 try:
212 agent = self.core.get_logical_device_agent(request.id)
213 agent.update_group_table(request.group_mod)
214 return Empty()
215 except KeyError:
216 context.set_details(
217 'Logical device \'{}\' not found'.format(request.id))
218 context.set_code(StatusCode.NOT_FOUND)
219 return Empty()
220
221 @twisted_async
222 def ListDevices(self, request, context):
223 log.info('grpc-request', request=request)
224 items = self.root.get('/devices')
225 return Devices(items=items)
226
227 @twisted_async
228 def GetDevice(self, request, context):
229 log.info('grpc-request', request=request)
230
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800231 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
232
Zsolt Haraszti66862032016-11-28 14:28:39 -0800233 if '/' in request.id:
234 context.set_details(
235 'Malformed device id \'{}\''.format(request.id))
236 context.set_code(StatusCode.INVALID_ARGUMENT)
237 return Device()
238
239 try:
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800240 return self.root.get('/devices/' + request.id, depth=depth)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800241 except KeyError:
242 context.set_details(
243 'Device \'{}\' not found'.format(request.id))
244 context.set_code(StatusCode.NOT_FOUND)
245 return Device()
246
247 @twisted_async
248 def CreateDevice(self, request, context):
249 log.info('grpc-request', request=request)
250
251 known_device_types = dict(
252 (dt.id, dt) for dt in self.root.get('/device_types'))
253
254 try:
255 assert isinstance(request, Device)
256 device = request
257 assert device.id == '', 'Device to be created cannot have id yet'
258 assert device.type in known_device_types, \
259 'Unknown device type \'{}\''.format(device.type)
260 assert device.admin_state in (AdminState.UNKNOWN,
261 AdminState.PREPROVISIONED), \
262 'Newly created device cannot be ' \
263 'in admin state \'{}\''.format(device.admin_state)
264
265 except AssertionError, e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400266 context.set_details(e.message)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800267 context.set_code(StatusCode.INVALID_ARGUMENT)
268 return Device()
269
270 # fill additional data
271 device.id = uuid4().hex[:12]
272 device_type = known_device_types[device.type]
273 device.adapter = device_type.adapter
274 if device.admin_state != AdminState.PREPROVISIONED:
275 device.admin_state = AdminState.PREPROVISIONED
276 device.oper_status = OperStatus.UNKNOWN
277
278 # add device to tree
279 self.root.add('/devices', device)
280
281 return request
282
283 @twisted_async
Khen Nursimulud068d812017-03-06 11:44:18 -0500284 def EnableDevice(self, request, context):
Zsolt Haraszti66862032016-11-28 14:28:39 -0800285 log.info('grpc-request', request=request)
286
287 if '/' in request.id:
288 context.set_details(
289 'Malformed device id \'{}\''.format(request.id))
290 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400291 return Empty()
Zsolt Haraszti66862032016-11-28 14:28:39 -0800292
293 try:
294 path = '/devices/{}'.format(request.id)
295 device = self.root.get(path)
Khen Nursimulud068d812017-03-06 11:44:18 -0500296 assert device.admin_state in (AdminState.PREPROVISIONED,
297 AdminState.DISABLED), \
298 'Device to enable cannot be ' \
299 'in admin state \'{}\''.format(device.admin_state)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800300 device.admin_state = AdminState.ENABLED
301 self.root.update(path, device, strict=True)
302
Khen Nursimulud068d812017-03-06 11:44:18 -0500303 except AssertionError, e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400304 context.set_details(e.message)
Khen Nursimulud068d812017-03-06 11:44:18 -0500305 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimulud068d812017-03-06 11:44:18 -0500306
307 except KeyError:
308 context.set_details(
309 'Device \'{}\' not found'.format(request.id))
310 context.set_code(StatusCode.NOT_FOUND)
311
312 return Empty()
313
314 @twisted_async
315 def DisableDevice(self, request, context):
316 log.info('grpc-request', request=request)
317
318 if '/' in request.id:
319 context.set_details(
320 'Malformed device id \'{}\''.format(request.id))
321 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400322 return Empty()
Khen Nursimulud068d812017-03-06 11:44:18 -0500323 try:
324 path = '/devices/{}'.format(request.id)
325 device = self.root.get(path)
326 assert device.admin_state == AdminState.ENABLED, \
327 'Device to disable cannot be ' \
328 'in admin state \'{}\''.format(device.admin_state)
329 device.admin_state = AdminState.DISABLED
330 self.root.update(path, device, strict=True)
331
332 except AssertionError, e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400333 context.set_details(e.message)
Khen Nursimulud068d812017-03-06 11:44:18 -0500334 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimulud068d812017-03-06 11:44:18 -0500335
336 except KeyError:
337 context.set_details(
338 'Device \'{}\' not found'.format(request.id))
339 context.set_code(StatusCode.NOT_FOUND)
340
341 return Empty()
342
343 @twisted_async
344 def RebootDevice(self, request, context):
345 log.info('grpc-request', request=request)
346
347 if '/' in request.id:
348 context.set_details(
349 'Malformed device id \'{}\''.format(request.id))
350 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400351 return Empty()
Khen Nursimulud068d812017-03-06 11:44:18 -0500352
353 try:
354 path = '/devices/{}'.format(request.id)
355 device = self.root.get(path)
356
357 agent = self.core.get_device_agent(device.id)
358 agent.reboot_device(device)
359
Khen Nursimulud068d812017-03-06 11:44:18 -0500360 except KeyError:
361 context.set_details(
362 'Device \'{}\' not found'.format(request.id))
363 context.set_code(StatusCode.NOT_FOUND)
364
365 return Empty()
366
367 @twisted_async
368 def DeleteDevice(self, request, context):
369 log.info('grpc-request', request=request)
370
371 if '/' in request.id:
372 context.set_details(
373 'Malformed device id \'{}\''.format(request.id))
374 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400375 return Empty()
Khen Nursimulud068d812017-03-06 11:44:18 -0500376
377 try:
378 path = '/devices/{}'.format(request.id)
379 device = self.root.get(path)
380 assert device.admin_state == AdminState.DISABLED, \
381 'Device to delete cannot be ' \
382 'in admin state \'{}\''.format(device.admin_state)
383
384 self.root.remove(path)
385
386 except AssertionError, e:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400387 context.set_details(e.message)
Khen Nursimulud068d812017-03-06 11:44:18 -0500388 context.set_code(StatusCode.INVALID_ARGUMENT)
Khen Nursimulud068d812017-03-06 11:44:18 -0500389
Zsolt Haraszti66862032016-11-28 14:28:39 -0800390 except KeyError:
391 context.set_details(
392 'Device \'{}\' not found'.format(request.id))
393 context.set_code(StatusCode.NOT_FOUND)
394
395 return Empty()
396
397 @twisted_async
398 def ListDevicePorts(self, request, context):
399 log.info('grpc-request', request=request)
400
401 if '/' in request.id:
402 context.set_details(
403 'Malformed device id \'{}\''.format(request.id))
404 context.set_code(StatusCode.INVALID_ARGUMENT)
405 return Ports()
406
407 try:
408 items = self.root.get('/devices/{}/ports'.format(request.id))
409 return Ports(items=items)
410 except KeyError:
411 context.set_details(
412 'Device \'{}\' not found'.format(request.id))
413 context.set_code(StatusCode.NOT_FOUND)
414 return Ports()
415
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500416 @twisted_async
417 def ListDevicePmConfigs(self, request, context):
Sergio Slobodrian71960022017-03-09 10:20:57 -0500418 log.info('grpc-request', request=request)
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500419
Sergio Slobodrian71960022017-03-09 10:20:57 -0500420 if '/' in request.id:
421 context.set_details(
422 'Malformed device id \'{}\''.format(request.id))
423 context.set_code(StatusCode.INVALID_ARGUMENT)
424 return PmConfigs()
425
426 try:
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400427 pm_configs = self.root.get(
428 '/devices/{}/pm_configs'.format(request.id))
Sergio Slobodrian2db4c102017-03-09 22:29:23 -0500429 pm_configs.id = request.id
Khen Nursimuluc60afa12017-03-13 14:33:50 -0400430 log.info('device-for-pms', pm_configs=pm_configs)
Sergio Slobodrian2db4c102017-03-09 22:29:23 -0500431 return pm_configs
Sergio Slobodrian71960022017-03-09 10:20:57 -0500432 except KeyError:
433 context.set_details(
434 'Device \'{}\' not found'.format(request.id))
435 context.set_code(StatusCode.NOT_FOUND)
436 return PmConfigs()
437
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500438 @twisted_async
439 def UpdateDevicePmConfigs(self, request, context):
Sergio Slobodrian2db4c102017-03-09 22:29:23 -0500440 log.info('grpc-request', request=request)
441
442 if '/' in request.id:
443 context.set_details(
444 'Malformed logical device id \'{}\''.format(request.id))
445 context.set_code(StatusCode.INVALID_ARGUMENT)
446 return Empty()
447
448 try:
449 device = self.root.get('/devices/{}'.format(request.id))
450 agent = self.core.get_device_agent(request.id)
451 agent.update_device_pm_config(request)
452 return Empty()
453 except KeyError:
454 context.set_details(
455 'Device \'{}\' not found'.format(request.id))
456 context.set_code(StatusCode.NOT_FOUND)
457 return Empty()
Sergio Slobodriana2eb52b2017-03-07 12:24:46 -0500458
Zsolt Haraszti66862032016-11-28 14:28:39 -0800459 @twisted_async
460 def ListDeviceFlows(self, request, context):
461 log.info('grpc-request', request=request)
462
463 if '/' in request.id:
464 context.set_details(
465 'Malformed device id \'{}\''.format(request.id))
466 context.set_code(StatusCode.INVALID_ARGUMENT)
467 return Flows()
468
469 try:
470 flows = self.root.get('/devices/{}/flows'.format(request.id))
471 return flows
472 except KeyError:
473 context.set_details(
474 'Device \'{}\' not found'.format(request.id))
475 context.set_code(StatusCode.NOT_FOUND)
476 return Flows()
477
Zsolt Haraszti66862032016-11-28 14:28:39 -0800478 @twisted_async
479 def ListDeviceFlowGroups(self, request, context):
480 log.info('grpc-request', request=request)
481
482 if '/' in request.id:
483 context.set_details(
484 'Malformed device id \'{}\''.format(request.id))
485 context.set_code(StatusCode.INVALID_ARGUMENT)
486 return FlowGroups()
487
488 try:
Khen Nursimulud068d812017-03-06 11:44:18 -0500489 groups = self.root.get(
490 '/devices/{}/flow_groups'.format(request.id))
Zsolt Haraszti66862032016-11-28 14:28:39 -0800491 return groups
492 except KeyError:
493 context.set_details(
494 'Device \'{}\' not found'.format(request.id))
495 context.set_code(StatusCode.NOT_FOUND)
496 return FlowGroups()
497
498 @twisted_async
499 def ListDeviceTypes(self, request, context):
500 log.info('grpc-request', request=request)
501 items = self.root.get('/device_types')
502 return DeviceTypes(items=items)
503
504 @twisted_async
505 def GetDeviceType(self, request, context):
506 log.info('grpc-request', request=request)
507
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800508 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
509
Zsolt Haraszti66862032016-11-28 14:28:39 -0800510 if '/' in request.id:
511 context.set_details(
512 'Malformed device type id \'{}\''.format(request.id))
513 context.set_code(StatusCode.INVALID_ARGUMENT)
514 return DeviceType()
515
516 try:
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800517 return self.root.get('/device_types/' + request.id, depth=depth)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800518 except KeyError:
519 context.set_details(
520 'Device type \'{}\' not found'.format(request.id))
521 context.set_code(StatusCode.NOT_FOUND)
522 return DeviceType()
523
524 @twisted_async
525 def ListDeviceGroups(self, request, context):
526 log.info('grpc-request', request=request)
527 # TODO is this mapped to tree or taken from coordinator?
528 items = self.root.get('/device_groups')
529 return DeviceGroups(items=items)
530
531 @twisted_async
532 def GetDeviceGroup(self, request, context):
533 log.info('grpc-request', request=request)
534
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800535 depth = int(dict(context.invocation_metadata()).get('get-depth', 0))
536
Zsolt Haraszti66862032016-11-28 14:28:39 -0800537 if '/' in request.id:
538 context.set_details(
539 'Malformed device group id \'{}\''.format(request.id))
540 context.set_code(StatusCode.INVALID_ARGUMENT)
541 return DeviceGroup()
542
543 # TODO is this mapped to tree or taken from coordinator?
544 try:
Zsolt Harasztif7722f92016-12-13 17:54:30 -0800545 return self.root.get('/device_groups/' + request.id, depth=depth)
Zsolt Haraszti66862032016-11-28 14:28:39 -0800546 except KeyError:
547 context.set_details(
548 'Device group \'{}\' not found'.format(request.id))
549 context.set_code(StatusCode.NOT_FOUND)
550 return DeviceGroup()
551
552 def StreamPacketsOut(self, request_iterator, context):
553
554 @twisted_async
555 def forward_packet_out(packet_out):
556 agent = self.core.get_logical_device_agent(packet_out.id)
557 agent.packet_out(packet_out.packet_out)
558
559 for request in request_iterator:
560 forward_packet_out(packet_out=request)
561
562 return Empty()
563
564 def ReceivePacketsIn(self, request, context):
565 while 1:
Zsolt Haraszti3300f742017-01-09 01:14:20 -0800566 try:
567 packet_in = self.core.packet_in_queue.get(timeout=1)
568 yield packet_in
569 except QueueEmpty:
570 if self.stopped:
571 break
Zsolt Haraszti66862032016-11-28 14:28:39 -0800572
573 def send_packet_in(self, device_id, ofp_packet_in):
574 """Must be called on the twisted thread"""
575 packet_in = PacketIn(id=device_id, packet_in=ofp_packet_in)
576 self.core.packet_in_queue.put(packet_in)
Zsolt Haraszti217a12e2016-12-19 16:37:55 -0800577
578 def ReceiveChangeEvents(self, request, context):
579 while 1:
Zsolt Haraszti3300f742017-01-09 01:14:20 -0800580 try:
581 event = self.core.change_event_queue.get(timeout=1)
582 yield event
583 except QueueEmpty:
584 if self.stopped:
585 break
Zsolt Haraszti217a12e2016-12-19 16:37:55 -0800586
587 def send_port_change_event(self, device_id, port_status):
588 """Must be called on the twisted thread"""
589 assert isinstance(port_status, ofp_port_status)
590 event = ChangeEvent(id=device_id, port_status=port_status)
591 self.core.change_event_queue.put(event)
Stephane Barbarieee409292017-04-24 10:30:20 -0400592
593
594 @twisted_async
595 def ListAlarmFilters(self, request, context):
596 try:
597 filters = self.root.get('/alarm_filters')
598 return AlarmFilters(filters=filters)
599 except KeyError:
600 context.set_code(StatusCode.NOT_FOUND)
601 return AlarmFilters()
602
603 @twisted_async
604 def GetAlarmFilter(self, request, context):
605 if '/' in request.id:
606 context.set_details(
607 'Malformed alarm filter id \'{}\''.format(request.id))
608 context.set_code(StatusCode.INVALID_ARGUMENT)
609 return AlarmFilter()
610
611 try:
612 alarm_filter = self.root.get('/alarm_filters/{}'.format(request.id))
613 return alarm_filter
614 except KeyError:
615 context.set_details(
616 'Alarm filter \'{}\' not found'.format(request.id))
617 context.set_code(StatusCode.NOT_FOUND)
618 return AlarmFilter()
619
620 @twisted_async
621 def DeleteAlarmFilter(self, request, context):
622 if '/' in request.id:
623 context.set_details(
624 'Malformed alarm filter id \'{}\''.format(request.id))
625 context.set_code(StatusCode.INVALID_ARGUMENT)
626 return Empty()
627
628 try:
629 self.root.remove('/alarm_filters/{}'.format(request.id))
630 except KeyError:
631 context.set_code(StatusCode.NOT_FOUND)
632
633 return Empty()
634
635 @twisted_async
636 def CreateAlarmFilter(self, request, context):
637 log.info('grpc-request', request=request)
638
639 try:
640 assert isinstance(request, AlarmFilter)
641 alarm_filter = request
642 assert alarm_filter.id == '', 'Alarm filter to be created cannot have id yet'
643
644 except AssertionError, e:
645 context.set_details(e.message)
646 context.set_code(StatusCode.INVALID_ARGUMENT)
647 return AlarmFilter()
648
649 # fill additional data
650 alarm_filter.id = uuid4().hex[:12]
651
652 # add device to tree
653 self.root.add('/alarm_filters', alarm_filter)
654
655 return request
656
657 @twisted_async
658 def UpdateAlarmFilter(self, request, context):
659 if '/' in request.id:
660 context.set_details(
661 'Malformed alarm filter id \'{}\''.format(request.id))
662 context.set_code(StatusCode.INVALID_ARGUMENT)
663 return AlarmFilter()
664
665 try:
666 assert isinstance(request, AlarmFilter)
667 alarm_filter = self.root.get('/alarm_filters/{}'.format(request.id))
668 self.root.update('/alarm_filters/{}'.format(request.id), request)
669
670 return request
671 except KeyError:
672 context.set_details(
673 'Alarm filter \'{}\' not found'.format(request.id))
674 context.set_code(StatusCode.NOT_FOUND)
675 return AlarmFilter()