Chip Boling | 32aab30 | 2019-01-23 10:50:18 -0600 | [diff] [blame] | 1 | # |
| 2 | # Copyright 2018 the original author or authors. |
| 3 | # |
| 4 | # Licensed under the Apache License, Version 2.0 (the "License"); |
| 5 | # you may not use this file except in compliance with the License. |
| 6 | # You may obtain a copy of the License at |
| 7 | # |
| 8 | # http://www.apache.org/licenses/LICENSE-2.0 |
| 9 | # |
| 10 | # Unless required by applicable law or agreed to in writing, software |
| 11 | # distributed under the License is distributed on an "AS IS" BASIS, |
| 12 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| 13 | # See the License for the specific language governing permissions and |
| 14 | # limitations under the License. |
| 15 | # |
| 16 | |
| 17 | import structlog |
| 18 | from copy import deepcopy |
| 19 | from voltha.protos.device_pb2 import ImageDownload |
| 20 | from voltha.extensions.omci.omci_defs import EntityOperations, ReasonCodes |
| 21 | import voltha.extensions.omci.omci_entities as omci_entities |
| 22 | from voltha.extensions.omci.omci_cc import OMCI_CC |
| 23 | from common.event_bus import EventBusClient |
| 24 | from voltha.extensions.omci.tasks.task_runner import TaskRunner |
| 25 | from voltha.extensions.omci.onu_configuration import OnuConfiguration |
| 26 | from voltha.extensions.omci.tasks.reboot_task import OmciRebootRequest, RebootFlags |
| 27 | from voltha.extensions.omci.tasks.omci_modify_request import OmciModifyRequest |
| 28 | from voltha.extensions.omci.omci_me import OntGFrame |
| 29 | from voltha.extensions.omci.state_machines.image_agent import ImageAgent |
| 30 | |
| 31 | from twisted.internet import reactor, defer |
| 32 | from enum import IntEnum |
| 33 | |
| 34 | OP = EntityOperations |
| 35 | RC = ReasonCodes |
| 36 | |
| 37 | ACTIVE_KEY = 'active' |
| 38 | IN_SYNC_KEY = 'in-sync' |
| 39 | LAST_IN_SYNC_KEY = 'last-in-sync-time' |
| 40 | SUPPORTED_MESSAGE_ENTITY_KEY = 'managed-entities' |
| 41 | SUPPORTED_MESSAGE_TYPES_KEY = 'message-type' |
| 42 | |
| 43 | |
| 44 | class OnuDeviceEvents(IntEnum): |
| 45 | # Events of interest to Device Adapters and OpenOMCI State Machines |
| 46 | DeviceStatusEvent = 0 # OnuDeviceEntry running status changed |
| 47 | MibDatabaseSyncEvent = 1 # MIB database sync changed |
| 48 | OmciCapabilitiesEvent = 2 # OMCI ME and message type capabilities |
| 49 | AlarmDatabaseSyncEvent = 3 # Alarm database sync changed |
| 50 | |
| 51 | # TODO: Add other events here as needed |
| 52 | |
| 53 | |
| 54 | class OnuDeviceEntry(object): |
| 55 | """ |
| 56 | An ONU Device entry in the MIB |
| 57 | """ |
| 58 | def __init__(self, omci_agent, device_id, adapter_agent, custom_me_map, |
| 59 | mib_db, alarm_db, support_classes, clock=None): |
| 60 | """ |
| 61 | Class initializer |
| 62 | |
| 63 | :param omci_agent: (OpenOMCIAgent) Reference to OpenOMCI Agent |
| 64 | :param device_id: (str) ONU Device ID |
| 65 | :param adapter_agent: (AdapterAgent) Adapter agent for ONU |
| 66 | :param custom_me_map: (dict) Additional/updated ME to add to class map |
| 67 | :param mib_db: (MibDbApi) MIB Database reference |
| 68 | :param alarm_db: (MibDbApi) Alarm Table/Database reference |
| 69 | :param support_classes: (dict) State machines and tasks for this ONU |
| 70 | """ |
| 71 | self.log = structlog.get_logger(device_id=device_id) |
| 72 | |
| 73 | self._started = False |
| 74 | self._omci_agent = omci_agent # OMCI AdapterAgent |
| 75 | self._device_id = device_id # ONU Device ID |
| 76 | self._adapter_agent = adapter_agent |
| 77 | self._runner = TaskRunner(device_id, clock=clock) # OMCI_CC Task runner |
| 78 | self._deferred = None |
| 79 | # self._img_download_deferred = None # deferred of image file download from server |
| 80 | self._omci_upgrade_deferred = None # deferred of ONU OMCI upgrading procedure |
| 81 | self._omci_activate_deferred = None # deferred of ONU OMCI Softwre Image Activate |
| 82 | self._img_deferred = None # deferred returned to caller of do_onu_software_download |
| 83 | self._first_in_sync = False |
| 84 | self._first_capabilities = False |
| 85 | self._timestamp = None |
| 86 | # self._image_download = None # (voltha_pb2.ImageDownload) |
| 87 | self.reactor = clock if clock is not None else reactor |
| 88 | |
| 89 | # OMCI related databases are on a per-agent basis. State machines and tasks |
| 90 | # are per ONU Vendor |
| 91 | # |
| 92 | self._support_classes = support_classes |
| 93 | self._configuration = None |
| 94 | |
| 95 | try: |
| 96 | # MIB Synchronization state machine |
| 97 | self._mib_db_in_sync = False |
| 98 | mib_synchronizer_info = support_classes.get('mib-synchronizer') |
| 99 | advertise = mib_synchronizer_info['advertise-events'] |
| 100 | self._mib_sync_sm = mib_synchronizer_info['state-machine'](self._omci_agent, |
| 101 | device_id, |
| 102 | mib_synchronizer_info['tasks'], |
| 103 | mib_db, |
| 104 | advertise_events=advertise) |
| 105 | # ONU OMCI Capabilities state machine |
| 106 | capabilities_info = support_classes.get('omci-capabilities') |
| 107 | advertise = capabilities_info['advertise-events'] |
| 108 | self._capabilities_sm = capabilities_info['state-machine'](self._omci_agent, |
| 109 | device_id, |
| 110 | capabilities_info['tasks'], |
| 111 | advertise_events=advertise) |
| 112 | # ONU Performance Monitoring Intervals state machine |
| 113 | interval_info = support_classes.get('performance-intervals') |
| 114 | advertise = interval_info['advertise-events'] |
| 115 | self._pm_intervals_sm = interval_info['state-machine'](self._omci_agent, device_id, |
| 116 | interval_info['tasks'], |
| 117 | advertise_events=advertise) |
| 118 | |
| 119 | # ONU ALARM Synchronization state machine |
| 120 | self._alarm_db_in_sync = False |
| 121 | alarm_synchronizer_info = support_classes.get('alarm-synchronizer') |
| 122 | advertise = alarm_synchronizer_info['advertise-events'] |
| 123 | self._alarm_sync_sm = alarm_synchronizer_info['state-machine'](self._omci_agent, |
| 124 | device_id, |
| 125 | alarm_synchronizer_info['tasks'], |
| 126 | alarm_db, |
| 127 | advertise_events=advertise) |
| 128 | # State machine of downloading image file from server |
| 129 | downloader_info = support_classes.get('image_downloader') |
| 130 | image_upgrader_info = support_classes.get('image_upgrader') |
| 131 | # image_activate_info = support_classes.get('image_activator') |
| 132 | advertise = downloader_info['advertise-event'] |
| 133 | # self._img_download_sm = downloader_info['state-machine'](self._omci_agent, device_id, |
| 134 | # downloader_info['tasks'], |
| 135 | # advertise_events=advertise) |
| 136 | self._image_agent = ImageAgent(self._omci_agent, device_id, |
| 137 | downloader_info['state-machine'], downloader_info['tasks'], |
| 138 | image_upgrader_info['state-machine'], image_upgrader_info['tasks'], |
| 139 | # image_activate_info['state-machine'], |
| 140 | advertise_events=advertise, clock=clock) |
| 141 | |
| 142 | # self._omci_upgrade_sm = image_upgrader_info['state-machine'](device_id, advertise_events=advertise) |
| 143 | |
| 144 | except Exception as e: |
| 145 | self.log.exception('state-machine-create-failed', e=e) |
| 146 | raise |
| 147 | |
| 148 | # Put state machines in the order you wish to start them |
| 149 | |
| 150 | self._state_machines = [] |
| 151 | self._on_start_state_machines = [ # Run when 'start()' called |
| 152 | self._mib_sync_sm, |
| 153 | self._capabilities_sm, |
| 154 | ] |
| 155 | self._on_sync_state_machines = [ # Run after first in_sync event |
| 156 | self._alarm_sync_sm, |
| 157 | ] |
| 158 | self._on_capabilities_state_machines = [ # Run after first capabilities events |
| 159 | self._pm_intervals_sm |
| 160 | ] |
| 161 | self._custom_me_map = custom_me_map |
| 162 | self._me_map = omci_entities.entity_id_to_class_map.copy() |
| 163 | |
| 164 | if custom_me_map is not None: |
| 165 | self._me_map.update(custom_me_map) |
| 166 | |
| 167 | self.event_bus = EventBusClient() |
| 168 | |
| 169 | # Create OMCI communications channel |
| 170 | self._omci_cc = OMCI_CC(adapter_agent, self.device_id, self._me_map, clock=clock) |
| 171 | |
| 172 | @staticmethod |
| 173 | def event_bus_topic(device_id, event): |
| 174 | """ |
| 175 | Get the topic name for a given event for this ONU Device |
| 176 | :param device_id: (str) ONU Device ID |
| 177 | :param event: (OnuDeviceEvents) Type of event |
| 178 | :return: (str) Topic string |
| 179 | """ |
| 180 | assert event in OnuDeviceEvents, \ |
| 181 | 'Event {} is not an ONU Device Event'.format(event.name) |
| 182 | return 'omci-device:{}:{}'.format(device_id, event.name) |
| 183 | |
| 184 | @property |
| 185 | def device_id(self): |
| 186 | return self._device_id |
| 187 | |
| 188 | @property |
| 189 | def omci_cc(self): |
| 190 | return self._omci_cc |
| 191 | |
| 192 | @property |
| 193 | def adapter_agent(self): |
| 194 | return self._adapter_agent |
| 195 | |
| 196 | @property |
| 197 | def task_runner(self): |
| 198 | return self._runner |
| 199 | |
| 200 | @property |
| 201 | def mib_synchronizer(self): |
| 202 | """ |
| 203 | Reference to the OpenOMCI MIB Synchronization state machine for this ONU |
| 204 | """ |
| 205 | return self._mib_sync_sm |
| 206 | |
| 207 | @property |
| 208 | def omci_capabilities(self): |
| 209 | """ |
| 210 | Reference to the OpenOMCI OMCI Capabilities state machine for this ONU |
| 211 | """ |
| 212 | return self._capabilities_sm |
| 213 | |
| 214 | @property |
| 215 | def pm_intervals_state_machine(self): |
| 216 | """ |
| 217 | Reference to the OpenOMCI PM Intervals state machine for this ONU |
| 218 | """ |
| 219 | return self._pm_intervals_sm |
| 220 | |
| 221 | def set_pm_config(self, pm_config): |
| 222 | """ |
| 223 | Set PM interval configuration |
| 224 | |
| 225 | :param pm_config: (OnuPmIntervalMetrics) PM Interval configuration |
| 226 | """ |
| 227 | self._pm_intervals_sm.set_pm_config(pm_config) |
| 228 | |
| 229 | @property |
| 230 | def timestamp(self): |
| 231 | """Pollable Metrics last collected timestamp""" |
| 232 | return self._timestamp |
| 233 | |
| 234 | @timestamp.setter |
| 235 | def timestamp(self, value): |
| 236 | self._timestamp = value |
| 237 | |
| 238 | @property |
| 239 | def alarm_synchronizer(self): |
| 240 | """ |
| 241 | Reference to the OpenOMCI Alarm Synchronization state machine for this ONU |
| 242 | """ |
| 243 | return self._alarm_sync_sm |
| 244 | |
| 245 | @property |
| 246 | def active(self): |
| 247 | """ |
| 248 | Is the ONU device currently active/running |
| 249 | """ |
| 250 | return self._started |
| 251 | |
| 252 | @property |
| 253 | def custom_me_map(self): |
| 254 | """ Vendor-specific Managed Entity Map for this vendor's device""" |
| 255 | return self._custom_me_map |
| 256 | |
| 257 | @property |
| 258 | def me_map(self): |
| 259 | """ Combined ME and Vendor-specific Managed Entity Map for this device""" |
| 260 | return self._me_map |
| 261 | |
| 262 | def _cancel_deferred(self): |
| 263 | d, self._deferred = self._deferred, None |
| 264 | try: |
| 265 | if d is not None and not d.called: |
| 266 | d.cancel() |
| 267 | except: |
| 268 | pass |
| 269 | |
| 270 | @property |
| 271 | def mib_db_in_sync(self): |
| 272 | return self._mib_db_in_sync |
| 273 | |
| 274 | @mib_db_in_sync.setter |
| 275 | def mib_db_in_sync(self, value): |
| 276 | if self._mib_db_in_sync != value: |
| 277 | # Save value |
| 278 | self._mib_db_in_sync = value |
| 279 | |
| 280 | # Start up other state machines if needed |
| 281 | if self._first_in_sync: |
| 282 | self.first_in_sync_event() |
| 283 | |
| 284 | # Notify any event listeners |
| 285 | topic = OnuDeviceEntry.event_bus_topic(self.device_id, |
| 286 | OnuDeviceEvents.MibDatabaseSyncEvent) |
| 287 | msg = { |
| 288 | IN_SYNC_KEY: self._mib_db_in_sync, |
| 289 | LAST_IN_SYNC_KEY: self.mib_synchronizer.last_mib_db_sync |
| 290 | } |
| 291 | self.event_bus.publish(topic=topic, msg=msg) |
| 292 | |
| 293 | @property |
| 294 | def alarm_db_in_sync(self): |
| 295 | return self._alarm_db_in_sync |
| 296 | |
| 297 | @alarm_db_in_sync.setter |
| 298 | def alarm_db_in_sync(self, value): |
| 299 | if self._alarm_db_in_sync != value: |
| 300 | # Save value |
| 301 | self._alarm_db_in_sync = value |
| 302 | |
| 303 | # Start up other state machines if needed |
| 304 | if self._first_in_sync: |
| 305 | self.first_in_sync_event() |
| 306 | |
| 307 | # Notify any event listeners |
| 308 | topic = OnuDeviceEntry.event_bus_topic(self.device_id, |
| 309 | OnuDeviceEvents.AlarmDatabaseSyncEvent) |
| 310 | msg = { |
| 311 | IN_SYNC_KEY: self._alarm_db_in_sync |
| 312 | } |
| 313 | self.event_bus.publish(topic=topic, msg=msg) |
| 314 | |
| 315 | @property |
| 316 | def configuration(self): |
| 317 | """ |
| 318 | Get the OMCI Configuration object for this ONU. This is a class that provides some |
| 319 | common database access functions for ONU capabilities and read-only configuration values. |
| 320 | |
| 321 | :return: (OnuConfiguration) |
| 322 | """ |
| 323 | return self._configuration |
| 324 | |
| 325 | @property |
| 326 | def image_agent(self): |
| 327 | return self._image_agent |
| 328 | |
| 329 | # @property |
| 330 | # def image_download(self): |
| 331 | # return self._image_download |
| 332 | |
| 333 | def start(self): |
| 334 | """ |
| 335 | Start the ONU Device Entry state machines |
| 336 | """ |
| 337 | self.log.debug('OnuDeviceEntry.start', previous=self._started) |
| 338 | if self._started: |
| 339 | return |
| 340 | |
| 341 | self._started = True |
| 342 | self._omci_cc.enabled = True |
| 343 | self._first_in_sync = True |
| 344 | self._first_capabilities = True |
| 345 | self._runner.start() |
| 346 | self._configuration = OnuConfiguration(self._omci_agent, self._device_id) |
| 347 | |
| 348 | # Start MIB Sync and other state machines that can run before the first |
| 349 | # MIB Synchronization event occurs. Start 'later' so that any |
| 350 | # ONU Device, OMCI DB, OMCI Agent, and others are fully started before |
| 351 | # performing the start. |
| 352 | |
| 353 | self._state_machines = [] |
| 354 | |
| 355 | def start_state_machines(machines): |
| 356 | for sm in machines: |
| 357 | self._state_machines.append(sm) |
| 358 | sm.start() |
| 359 | |
| 360 | self._deferred = reactor.callLater(0, start_state_machines, |
| 361 | self._on_start_state_machines) |
| 362 | # Notify any event listeners |
| 363 | self._publish_device_status_event() |
| 364 | |
| 365 | def stop(self): |
| 366 | """ |
| 367 | Stop the ONU Device Entry state machines |
| 368 | """ |
| 369 | if not self._started: |
| 370 | return |
| 371 | |
| 372 | self._started = False |
| 373 | self._cancel_deferred() |
| 374 | self._omci_cc.enabled = False |
| 375 | |
| 376 | # Halt MIB Sync and other state machines |
| 377 | for sm in self._state_machines: |
| 378 | sm.stop() |
| 379 | |
| 380 | self._state_machines = [] |
| 381 | |
| 382 | # Stop task runner |
| 383 | self._runner.stop() |
| 384 | |
| 385 | # Notify any event listeners |
| 386 | self._publish_device_status_event() |
| 387 | |
| 388 | def first_in_sync_event(self): |
| 389 | """ |
| 390 | This event is called on the first MIB synchronization event after |
| 391 | OpenOMCI has been started. It is responsible for starting any |
| 392 | other state machine and to initiate an ONU Capabilities report |
| 393 | """ |
| 394 | if self._first_in_sync: |
| 395 | self._first_in_sync = False |
| 396 | |
| 397 | # Start up the ONU Capabilities task |
| 398 | self._configuration.reset() |
| 399 | |
| 400 | # Insure that the ONU-G Administrative lock is disabled |
| 401 | def failure(reason): |
| 402 | self.log.error('disable-admin-state-lock', reason=reason) |
| 403 | |
| 404 | frame = OntGFrame(attributes={'administrative_state': 0}).set() |
| 405 | task = OmciModifyRequest(self._omci_agent, self.device_id, frame) |
| 406 | self.task_runner.queue_task(task).addErrback(failure) |
| 407 | |
| 408 | # Start up any other remaining OpenOMCI state machines |
| 409 | def start_state_machines(machines): |
| 410 | for sm in machines: |
| 411 | self._state_machines.append(sm) |
| 412 | reactor.callLater(0, sm.start) |
| 413 | |
| 414 | self._deferred = reactor.callLater(0, start_state_machines, |
| 415 | self._on_sync_state_machines) |
| 416 | |
| 417 | # if an ongoing upgrading is not accomplished, restart it |
| 418 | if self._img_deferred is not None: |
| 419 | self._image_agent.onu_bootup() |
| 420 | |
| 421 | def first_in_capabilities_event(self): |
| 422 | """ |
| 423 | This event is called on the first capabilities event after |
| 424 | OpenOMCI has been started. It is responsible for starting any |
| 425 | other state machine. These are often state machines that have tasks |
| 426 | that are dependent upon knowing if various MEs are supported |
| 427 | """ |
| 428 | if self._first_capabilities: |
| 429 | self._first_capabilities = False |
| 430 | |
| 431 | # Start up any other remaining OpenOMCI state machines |
| 432 | def start_state_machines(machines): |
| 433 | for sm in machines: |
| 434 | self._state_machines.append(sm) |
| 435 | reactor.callLater(0, sm.start) |
| 436 | |
| 437 | self._deferred = reactor.callLater(0, start_state_machines, |
| 438 | self._on_capabilities_state_machines) |
| 439 | |
| 440 | # def __on_omci_download_success(self, image_download): |
| 441 | # self.log.debug("__on_omci_download_success", image=image_download) |
| 442 | # self._omci_upgrade_deferred = None |
| 443 | # # self._ret_deferred = None |
| 444 | # self._omci_activate_deferred = self._image_agent.activate_onu_image(image_download.name) |
| 445 | # self._omci_activate_deferred.addCallbacks(self.__on_omci_image_activate_success, |
| 446 | # self.__on_omci_image_activate_fail, errbackArgs=(image_name,)) |
| 447 | # return image_name |
| 448 | |
| 449 | # def __on_omci_download_fail(self, fail, image_name): |
| 450 | # self.log.debug("__on_omci_download_fail", failure=fail, image_name=image_name) |
| 451 | # self.reactor.callLater(0, self._img_deferred.errback, fail) |
| 452 | # self._omci_upgrade_deferred = None |
| 453 | # self._img_deferred = None |
| 454 | |
| 455 | def __on_omci_image_activate_success(self, image_name): |
| 456 | self.log.debug("__on_omci_image_activate_success", image_name=image_name) |
| 457 | self._omci_activate_deferred = None |
| 458 | self._img_deferred.callback(image_name) |
| 459 | self._img_deferred = None |
| 460 | return image_name |
| 461 | |
| 462 | def __on_omci_image_activate_fail(self, fail, image_name): |
| 463 | self.log.debug("__on_omci_image_activate_fail", faile=fail, image_name=image_name) |
| 464 | self._omci_activate_deferred = None |
| 465 | self._img_deferred.errback(fail) |
| 466 | self._img_deferred = None |
| 467 | |
| 468 | def _publish_device_status_event(self): |
| 469 | """ |
| 470 | Publish the ONU Device start/start status. |
| 471 | """ |
| 472 | topic = OnuDeviceEntry.event_bus_topic(self.device_id, |
| 473 | OnuDeviceEvents.DeviceStatusEvent) |
| 474 | msg = {ACTIVE_KEY: self._started} |
| 475 | self.event_bus.publish(topic=topic, msg=msg) |
| 476 | |
| 477 | def publish_omci_capabilities_event(self): |
| 478 | """ |
| 479 | Publish the ONU Device start/start status. |
| 480 | """ |
| 481 | if self.first_in_capabilities_event: |
| 482 | self.first_in_capabilities_event() |
| 483 | |
| 484 | topic = OnuDeviceEntry.event_bus_topic(self.device_id, |
| 485 | OnuDeviceEvents.OmciCapabilitiesEvent) |
| 486 | msg = { |
| 487 | SUPPORTED_MESSAGE_ENTITY_KEY: self.omci_capabilities.supported_managed_entities, |
| 488 | SUPPORTED_MESSAGE_TYPES_KEY: self.omci_capabilities.supported_message_types |
| 489 | } |
| 490 | self.event_bus.publish(topic=topic, msg=msg) |
| 491 | |
| 492 | def delete(self): |
| 493 | """ |
| 494 | Stop the ONU Device's state machine and remove the ONU, and any related |
| 495 | OMCI state information from the OpenOMCI Framework |
| 496 | """ |
| 497 | self.stop() |
| 498 | self.mib_synchronizer.delete() |
| 499 | |
| 500 | # OpenOMCI cleanup |
| 501 | if self._omci_agent is not None: |
| 502 | self._omci_agent.remove_device(self._device_id, cleanup=True) |
| 503 | |
| 504 | def query_mib(self, class_id=None, instance_id=None, attributes=None): |
| 505 | """ |
| 506 | Get MIB database information. |
| 507 | |
| 508 | This method can be used to request information from the database to the detailed |
| 509 | level requested |
| 510 | |
| 511 | :param class_id: (int) Managed Entity class ID |
| 512 | :param instance_id: (int) Managed Entity instance |
| 513 | :param attributes: (list or str) Managed Entity instance's attributes |
| 514 | |
| 515 | :return: (dict) The value(s) requested. If class/inst/attribute is |
| 516 | not found, an empty dictionary is returned |
| 517 | :raises DatabaseStateError: If the database is not enabled |
| 518 | """ |
| 519 | self.log.debug('query', class_id=class_id, instance_id=instance_id, |
| 520 | attributes=attributes) |
| 521 | |
| 522 | return self.mib_synchronizer.query_mib(class_id=class_id, instance_id=instance_id, |
| 523 | attributes=attributes) |
| 524 | |
| 525 | def query_mib_single_attribute(self, class_id, instance_id, attribute): |
| 526 | """ |
| 527 | Get MIB database information for a single specific attribute |
| 528 | |
| 529 | This method can be used to request information from the database to the detailed |
| 530 | level requested |
| 531 | |
| 532 | :param class_id: (int) Managed Entity class ID |
| 533 | :param instance_id: (int) Managed Entity instance |
| 534 | :param attribute: (str) Managed Entity instance's attribute |
| 535 | |
| 536 | :return: (varies) The value requested. If class/inst/attribute is |
| 537 | not found, None is returned |
| 538 | :raises DatabaseStateError: If the database is not enabled |
| 539 | """ |
| 540 | self.log.debug('query-single', class_id=class_id, |
| 541 | instance_id=instance_id, attributes=attribute) |
| 542 | assert isinstance(attribute, basestring), \ |
| 543 | 'Only a single attribute value can be retrieved' |
| 544 | |
| 545 | entry = self.mib_synchronizer.query_mib(class_id=class_id, |
| 546 | instance_id=instance_id, |
| 547 | attributes=attribute) |
| 548 | |
| 549 | return entry[attribute] if attribute in entry else None |
| 550 | |
| 551 | def query_alarm_table(self, class_id=None, instance_id=None): |
| 552 | """ |
| 553 | Get Alarm information |
| 554 | |
| 555 | This method can be used to request information from the alarm database to |
| 556 | the detailed level requested |
| 557 | |
| 558 | :param class_id: (int) Managed Entity class ID |
| 559 | :param instance_id: (int) Managed Entity instance |
| 560 | |
| 561 | :return: (dict) The value(s) requested. If class/inst/attribute is |
| 562 | not found, an empty dictionary is returned |
| 563 | :raises DatabaseStateError: If the database is not enabled |
| 564 | """ |
| 565 | self.log.debug('query', class_id=class_id, instance_id=instance_id) |
| 566 | |
| 567 | return self.alarm_synchronizer.query_mib(class_id=class_id, instance_id=instance_id) |
| 568 | |
| 569 | def reboot(self, |
| 570 | flags=RebootFlags.Reboot_Unconditionally, |
| 571 | timeout=OmciRebootRequest.DEFAULT_REBOOT_TIMEOUT): |
| 572 | """ |
| 573 | Request a reboot of the ONU |
| 574 | |
| 575 | :param flags: (RebootFlags) Reboot condition |
| 576 | :param timeout: (int) Reboot task priority |
| 577 | :return: (deferred) Fires upon completion or error |
| 578 | """ |
| 579 | assert self.active, 'This device is not active' |
| 580 | |
| 581 | return self.task_runner.queue_task(OmciRebootRequest(self._omci_agent, |
| 582 | self.device_id, |
| 583 | flags=flags, |
| 584 | timeout=timeout)) |
| 585 | |
| 586 | # def get_imagefile(self, local_name, local_dir, remote_url=None): |
| 587 | # """ |
| 588 | # Return a Deferred that will be triggered if the file is locally available |
| 589 | # or downloaded successfully |
| 590 | # """ |
| 591 | # self.log.info('start download from {}'.format(remote_url)) |
| 592 | |
| 593 | # # for debug purpose, start runner here to queue downloading task |
| 594 | # # self._runner.start() |
| 595 | |
| 596 | # return self._image_agent.get_image(self._image_download) |
| 597 | |
| 598 | def do_onu_software_download(self, image_dnld): |
| 599 | """ |
| 600 | image_dnld: (ImageDownload) |
| 601 | : Return a Deferred that will be triggered when upgrading results in success or failure |
| 602 | """ |
| 603 | self.log.debug('do_onu_software_download') |
| 604 | image_download = deepcopy(image_dnld) |
| 605 | # self._img_download_deferred = self._image_agent.get_image(self._image_download) |
| 606 | # self._img_download_deferred.addCallbacks(self.__on_download_success, self.__on_download_fail, errbackArgs=(self._image_download,)) |
| 607 | # self._ret_deferred = defer.Deferred() |
| 608 | # return self._ret_deferred |
| 609 | return self._image_agent.get_image(image_download) |
| 610 | |
| 611 | # def do_onu_software_switch(self): |
| 612 | def do_onu_image_activate(self, image_dnld_name): |
| 613 | """ |
| 614 | Return a Deferred that will be triggered when switching software image results in success or failure |
| 615 | """ |
| 616 | if self._img_deferred is None: |
| 617 | self.log.debug('do_onu_image_activate') |
| 618 | self._img_deferred = defer.Deferred() |
| 619 | self._omci_upgrade_deferred = self._image_agent.onu_omci_download(image_dnld_name) |
| 620 | self._omci_upgrade_deferred.addCallbacks(self.__on_omci_image_activate_success, |
| 621 | self.__on_omci_image_activate_fail, errbackArgs=(image_dnld_name,)) |
| 622 | return self._img_deferred |
| 623 | |
| 624 | def cancel_onu_software_download(self, image_name): |
| 625 | self.log.debug('cancel_onu_software_download') |
| 626 | self._image_agent.cancel_download_image(image_name) |
| 627 | self._image_agent.cancel_upgrade_onu() |
| 628 | if self._img_deferred and not self._img_deferred.called: |
| 629 | self._img_deferred.cancel() |
| 630 | self._img_deferred = None |
| 631 | # self._image_download = None |
| 632 | |
| 633 | def get_image_download_status(self, image_name): |
| 634 | return self._image_agent.get_image_status(image_name) |
| 635 | |