def perform_get_mds(self): """ Get the 'mib_data_sync' attribute of the ONU """ self.log.info('perform-get-mds') try: device = self.omci_agent.get_device(self.device_id) ######################################### # Request (MDS supplied value does not matter for a 'get' request) results = yield device.omci_cc.send(OntDataFrame(mib_data_sync=123).get()) omci_msg = results.fields['omci_message'].fields status = omci_msg['success_code'] self.log.debug('ont-data-mds', status=status) assert status == RC.Success, 'Unexpected Response Status: {}'.format(status) # Successful if here self.deferred.callback(omci_msg['data']['mib_data_sync']) except TimeoutError as e: self.log.warn('get-mds-timeout', e=e) self.deferred.errback(failure.Failure(e)) except Exception as e: self.log.exception('get-mds', e=e) self.deferred.errback(failure.Failure(e))
def perform_test_omci(self): """ Perform the initial test request """ ani_g_entities = self._device.configuration.ani_g_entities ani_g_entities_ids = ani_g_entities.keys() if ani_g_entities \ is not None else None self._entity_id = ani_g_entities_ids[0] self.log.info('perform-test', entity_class=self._entity_class, entity_id=self._entity_id) try: frame = MEFrame(self._entity_class, self._entity_id, []).test() result = yield self._device.omci_cc.send(frame) if not result.fields['omci_message'].fields['success_code']: self.log.info( 'Self-Test Submitted Successfully', code=result.fields['omci_message'].fields['success_code']) else: raise TestFailure('Test Failure: {}'.format( result.fields['omci_message'].fields['success_code'])) except TimeoutError as e: self.deferred.errback(failure.Failure(e)) except Exception as e: self.log.exception('perform-test', e=e, class_id=self._entity_class, entity_id=self._entity_id) self.deferred.errback(failure.Failure(e))
def perform_sync_time(self): """ Sync the time """ self.log.debug('perform-sync-time') try: device = self.omci_agent.get_device(self.device_id) ######################################### # ONT-G (ME #256) dt = datetime.utcnow() if self._use_utc else datetime.now() results = yield device.omci_cc.send(OntGFrame().synchronize_time(dt)) omci_msg = results.fields['omci_message'].fields status = omci_msg['success_code'] self.log.debug('sync-time', status=status) if status == RC.Success: self.log.info('sync-time', success_info=omci_msg['success_info'] & 0x0f) assert status == RC.Success, 'Unexpected Response Status: {}'.format(status) # Successful if here self.deferred.callback(results) except TimeoutError as e: self.log.warn('sync-time-timeout', e=e) self.deferred.errback(failure.Failure(e)) except Exception as e: self.log.exception('sync-time', e=e) self.deferred.errback(failure.Failure(e))
def perform_alarm_resync(self): """ Perform the ALARM Resynchronization sequence The sequence to be performed is: - get a copy of the current ALARM database - perform ALARM upload commands to get ONU's database and save this to a local DB. During the alarm upload process, the maximum time between alarm upload next requests is 1 minute. """ self.log.info('perform-alarm-resync') try: command_sequence_number = yield self.snapshot_alarm() # Start the ALARM upload sequence, save alarms to the table commands_retrieved, alarm_table = yield self.upload_alarm( command_sequence_number) if commands_retrieved < command_sequence_number: e = AlarmDownloadException( 'Only retrieved {} of {} instances'.format( commands_retrieved, command_sequence_number)) self.deferred.errback(failure.Failure(e)) self.deferred.callback({ 'commands_retrieved': commands_retrieved, 'alarm_table': alarm_table }) except Exception as e: self.log.exception('resync', e=e) self.deferred.errback(failure.Failure(e))
def perform_mib_resync(self): """ Perform the MIB Resynchronization sequence The sequence to be performed are: - get a copy of the current MIB database (db_copy) - perform MIB upload commands to get ONU's database and save this to a local DB (db_active). Note that the ONU can still receive create/delete/set/get operations from the operator and source AVC notifications as well during this period. - Compare the information in the db_copy to the db_active During the mib upload process, the maximum time between mib upload next requests is 1 minute. """ self.log.info('perform-mib-resync') # Try at least 3 times to snapshot the current MIB and get the # MIB upload request out so ONU snapshots its database db_copy = None number_of_commands = None commands_retrieved = 0 try: results = yield self.snapshot_mib() db_copy = results[0] number_of_commands = results[1] # Start the MIB upload sequence commands_retrieved = yield self.upload_mib(number_of_commands) except Exception as e: self.deferred.errback(failure.Failure(e)) returnValue(None) if db_copy is None: e = MibCopyException('Failed to get local database copy') self.deferred.errback(failure.Failure(e)) returnValue('FAILED') if commands_retrieved < number_of_commands: e = MibDownloadException('Only retrieved {} of {} instances'. format(commands_retrieved, number_of_commands)) self.deferred.errback(failure.Failure(e)) returnValue('FAILED') # Compare the database mib_differences = self.compare_mibs(db_copy, self._db_active.query(self.device_id)) if mib_differences is None: self.deferred.callback('success') self.deferred.callback('TODO: This task has not been coded.') # TODO: Handle mismatches pass
def send(self, frame, timeout=DEFAULT_OMCI_TIMEOUT, retry=0, high_priority=False): """ Queue the OMCI Frame for a transmit to the ONU via the proxy_channel :param frame: (OMCIFrame) Message to send :param timeout: (int) Rx Timeout. 0=No response needed :param retry: (int) Additional retry attempts on channel failure, default=0 :param high_priority: (bool) High Priority requests :return: (deferred) A deferred that fires when the response frame is received or if an error/timeout occurs """ if not self.enabled or self._proxy_address is None: # TODO custom exceptions throughout this code would be helpful self._tx_errors += 1 return fail(result=failure.Failure(Exception('OMCI is not enabled'))) timeout = float(timeout) if timeout > float(MAX_OMCI_REQUEST_AGE): self._tx_errors += 1 msg = 'Maximum timeout is {} seconds'.format(MAX_OMCI_REQUEST_AGE) return fail(result=failure.Failure(Exception(msg))) if not isinstance(frame, OmciFrame): self._tx_errors += 1 msg = "Invalid frame class '{}'".format(type(frame)) return fail(result=failure.Failure(Exception(msg))) try: index = self._get_priority_index(high_priority) tx_tid = frame.fields['transaction_id'] if tx_tid is None: tx_tid = self._get_tx_tid(high_priority=high_priority) frame.fields['transaction_id'] = tx_tid assert tx_tid not in self._pending[index], 'TX TID {} is already exists'.format(tx_tid) assert tx_tid > 0, 'Invalid Tx TID: {}'.format(tx_tid) # Queue it and request next Tx if tx channel is free d = defer.Deferred() self._queue_frame(d, frame, timeout, retry, high_priority, front=False) self._send_next_request(high_priority) if timeout == 0: self.log.debug("send-timeout-zero", tx_tid=tx_tid) self.reactor.callLater(0, d.callback, 'queued') return d except Exception as e: self._tx_errors += 1 self._consecutive_errors += 1 if self._consecutive_errors == 1: self.reactor.callLater(0, self._publish_connectivity_event, False) self.log.exception('send-omci', e=e) return fail(result=failure.Failure(e))
def perform_mib_reconcile(self): """ Perform the MIB Reconciliation sequence. The sequence to reconcile will be to clean up ONU only MEs, followed by OLT/OpenOMCI-only MEs, and then finally correct common MEs with differing attributes. """ self.log.debug('perform-mib-reconcile') try: successes = 0 failures = 0 if self._diffs['onu-only'] is not None and len(self._diffs['onu-only']): results = yield self.fix_onu_only(self._diffs['onu-only'], self._diffs['onu-db']) self.log.debug('onu-only-results', good=results[0], bad=results[1]) successes += results[0] failures += results[1] if self._diffs['olt-only'] is not None and len(self._diffs['olt-only']): results = yield self.fix_olt_only(self._diffs['olt-only'], self._diffs['onu-db'], self._diffs['olt-db']) self.log.debug('olt-only-results', good=results[0], bad=results[1]) successes += results[0] failures += results[1] if self._diffs['attributes'] is not None and len(self._diffs['attributes']): results = yield self.fix_attributes_only(self._diffs['attributes'], self._diffs['onu-db'], self._diffs['olt-db']) self.log.debug('attributes-results', good=results[0], bad=results[1]) successes += results[0] failures += results[1] # Success? Update MIB-data-sync if failures == 0: results = yield self.update_mib_data_sync() successes += results[0] failures += results[1] # Send back final status if failures > 0: msg = '{} Successful updates, {} failures'.format(successes, failure) error = MibPartialSuccessException(msg) if successes \ else MibReconcileException(msg) self.deferred.errback(failure.Failure(error)) else: self.deferred.callback('{} Successful updates'.format(successes)) except Exception as e: if not self.deferred.called: self.log.exception('reconcile', e=e) self.deferred.errback(failure.Failure(e))
def perform_mib_resync(self): """ Perform the MIB Resynchronization sequence The sequence to be performed is: - get a copy of the current MIB database (db_copy) - perform MIB upload commands to get ONU's database and save this to a local DB (db_active). Note that the ONU can still receive create/delete/set/get operations from the operator and source AVC notifications as well during this period. - Compare the information in the db_copy to the db_active During the mib upload process, the maximum time between mib upload next requests is 1 minute. """ self.log.info('perform-mib-resync') try: results = yield self.snapshot_mib() db_copy = results[0] if db_copy is None: e = MibCopyException('Failed to get local database copy') self.deferred.errback(failure.Failure(e)) else: number_of_commands = results[1] # Start the MIB upload sequence commands_retrieved = yield self.upload_mib(number_of_commands) if commands_retrieved < number_of_commands: e = MibDownloadException( 'Only retrieved {} of {} instances'.format( commands_retrieved, number_of_commands)) self.deferred.errback(failure.Failure(e)) else: # Compare the databases on_olt_only, on_onu_only, attr_diffs = \ self.compare_mibs(db_copy, self._db_active.query(self.device_id)) self.deferred.callback({ 'on-olt-only': on_olt_only if len(on_olt_only) else None, 'on-onu-only': on_onu_only if len(on_onu_only) else None, 'attr-diffs': attr_diffs if len(attr_diffs) else None }) except Exception as e: self.log.exception('resync', e=e) self.deferred.errback(failure.Failure(e))
def send(self, frame, timeout=DEFAULT_OMCI_TIMEOUT): """ Send the OMCI Frame to the ONU via the proxy_channel :param frame: (OMCIFrame) Message to send :param timeout: (int) Rx Timeout. 0=Forever :return: (deferred) A deferred that fires when the response frame is received or if an error/timeout occurs """ self.flush(max_age=MAX_OMCI_REQUEST_AGE) assert timeout <= MAX_OMCI_REQUEST_AGE, \ 'Maximum timeout is {} seconds'.format(MAX_OMCI_REQUEST_AGE) assert isinstance(frame, OmciFrame), \ "Invalid frame class '{}'".format(type(frame)) if not self.enabled or self._proxy_address is None: # TODO custom exceptions throughout this code would be helpful return fail( result=failure.Failure(Exception('OMCI is not enabled'))) try: tx_tid = frame.fields['transaction_id'] if tx_tid is None: tx_tid = self._get_tx_tid() frame.fields['transaction_id'] = tx_tid assert tx_tid not in self._requests, 'TX TID {} is already exists'.format( tx_tid) assert tx_tid >= 0, 'Invalid Tx TID: {}'.format(tx_tid) ts = arrow.utcnow().float_timestamp d = defer.Deferred() self._adapter_agent.send_proxied_message(self._proxy_address, hexify(str(frame))) self._tx_frames += 1 self._requests[tx_tid] = (ts, d, frame, timeout) d.addCallbacks(self._request_success, self._request_failure, errbackArgs=(tx_tid, )) if timeout > 0: d.addTimeout(timeout, reactor) except Exception as e: self._tx_errors += 1 self._consecutive_errors += 1 self.log.exception('send-omci', e=e) return fail(result=failure.Failure(e)) return d
def perform_alarm_sync_data(self): """ Sync the time """ self.log.info('perform-alarm-sync-data') try: device = self.omci_agent.get_device(self.device_id) ######################################### # ONU Data (ME #2) # alarm_retrieval_mode=1, time=DEFAULT_OMCI_TIMEOUT results = yield device.omci_cc.send_get_all_alarm(alarm_retrieval_mode=1) self.stop_if_not_running() command_sequence_number = results.fields['omci_message'].fields['number_of_commands'] for seq_no in xrange(command_sequence_number): if not device.active or not device.omci_cc.enabled: raise AlarmSyncDataFailure('OMCI and/or ONU is not active') for retry in range(0, 3): try: self.log.debug('alarm-data-next-request', seq_no=seq_no, retry=retry, command_sequence_number=command_sequence_number) yield device.omci_cc.send_get_all_alarm_next(seq_no) self.stop_if_not_running() self.log.debug('alarm-data-next-success', seq_no=seq_no, command_sequence_number=command_sequence_number) break except TimeoutError as e: from common.utils.asleep import asleep self.log.warn('alarm-data-timeout', e=e, seq_no=seq_no, command_sequence_number=command_sequence_number) if retry >= 2: raise AlarmSyncDataFailure('Alarm timeout failure on req {} of {}'. format(seq_no + 1, command_sequence_number)) yield asleep(0.3) self.stop_if_not_running() # Successful if here self.log.info('alarm-synchronized') self.deferred.callback(command_sequence_number) except TimeoutError as e: self.log.warn('alarm-sync-time-timeout', e=e) self.deferred.errback(failure.Failure(e)) except Exception as e: self.log.exception('alarm-sync-time', e=e) self.deferred.errback(failure.Failure(e))
def delete_tcont_and_associated_me(self): self.log.info('deleting-tcont') omci_cc = self._onu_device.omci_cc try: ################################################################################ # Reset TCONT ME ################################################################################ tcont_idents = self._onu_device.query_mib(Tcont.class_id) self.log.debug('tcont-idents', tcont_idents=tcont_idents) tcont_entity_id = None for k, v in tcont_idents.items(): if not isinstance(v, dict): continue alloc_check = v.get('attributes', {}).get('alloc_id', 0) # Some onu report both to indicate an available tcont if alloc_check == self._alloc_id: tcont_entity_id = k break if tcont_entity_id is None: self.log.error("tcont-not-found-for-delete", alloc_id=self._alloc_id) return self.log.debug('found-tcont', tcont_entity_id=tcont_entity_id, alloc_id=self._alloc_id) # Remove the TCONT (rather reset the TCONT to point alloc_id to 0xffff) # The _tcont.remove_from_hardware is already doing check_status_and_state yield self._tcont.remove_from_hardware(omci_cc) # At this point, the gem-ports should have been removed already. # Remove the 8021p Mapper and ANI MacBridgePortConfigData yield self._delete__8021p_mapper__ani_mac_bridge_port() # There are no other associated MEs now. # There might be TrafficScheduler MEs that point to a TCONT. # TrafficScheduler ME not used currently. self.deferred.callback("tech-profile-remove-success--tcont") except TimeoutError as e: self.log.warn('rx-timeout-tech-profile', e=e) self.deferred.errback(failure.Failure(e)) except Exception as e: self.log.exception('omci-delete-tech-profile', e=e) self.deferred.errback(failure.Failure(e))
def _connectedEb(self, f): if f.check(errors.ConnectionFailedError): # switch the failure and return an UNKNOWN status msg = "Unable to connect to manager." f = failure.Failure(util.NagiosUnknown(msg)) util.unknown(msg) if f.check(errors.ConnectionRefusedError): # switch the failure and return a CRITICAL status msg = "Manager refused connection." f = failure.Failure(util.NagiosCritical(msg)) util.critical(msg) # all other failures get forwarded to the managerDeferred errback as-is self.managerDeferred.errback(f)
def perform_mib_download(self): """ Send the commands to minimally configure the PON, Bridge, and UNI ports for this device. The application of any service flows and other characteristics are done as needed. """ try: self.log.debug('function-entry') self.log.info('perform-download') device = self._handler.adapter_agent.get_device(self.device_id) if self._handler.enabled and len(self._handler.uni_ports) > 0: device.reason = 'performing-initial-mib-download' self._handler.adapter_agent.update_device(device) try: # Lock the UNI ports to prevent any alarms during initial configuration # of the ONU self.strobe_watchdog() # Provision the initial bridge configuration yield self.perform_initial_bridge_setup() for uni_port in self._handler.uni_ports: yield self.enable_uni(uni_port, True) # Provision the initial bridge configuration yield self.perform_uni_initial_bridge_setup(uni_port) # And re-enable the UNIs if needed yield self.enable_uni(uni_port, False) self.deferred.callback('initial-download-success') except TimeoutError as e: self.log.error('initial-download-failure', e=e) self.deferred.errback(failure.Failure(e)) except Exception as e: self.log.exception('initial-download-failure', e=e) self.deferred.errback(failure.Failure(e)) else: e = MibResourcesFailure('Required resources are not available', len(self._handler.uni_ports)) self.deferred.errback(failure.Failure(e)) except BaseException as e: self.log.debug('@thyy_mib_check:', exception=e)
def perform_mib_download(self): """ Send the commands to minimally configure the PON, Bridge, and UNI ports for this device. The application of any service flows and other characteristics are done as needed. """ self.log.info('perform-download') device = self._handler.adapter_agent.get_device(self.device_id) def resources_available(): return (device.vlan > 0 and len(self._handler.uni_ports) > 0 and len(self._handler.pon_port.tconts) and len(self._handler.pon_port.gem_ports)) if self._handler.enabled and resources_available(): device.reason = 'Performing OMCI Download' self._handler.adapter_agent.update_device(device) try: # Lock the UNI ports to prevent any alarms during initial configuration # of the ONU self.strobe_watchdog() yield self.enable_unis(self._handler.uni_ports, True) # Provision the initial bridge configuration yield self.perform_initial_bridge_setup() # And not all the service specific work yield self.perform_service_specific_steps() # And re-enable the UNIs if needed yield self.enable_unis(self._handler.uni_ports, False) # If here, we are done device = self._handler.adapter_agent.get_device(self.device_id) device.reason = '' self._handler.adapter_agent.update_device(device) self.deferred.callback('TODO: What should we return to the caller?') except TimeoutError as e: self.deferred.errback(failure.Failure(e)) else: # TODO: Provide better error reason, what was missing... e = MibResourcesFailure('Required resources are not available') self.deferred.errback(failure.Failure(e))
def perform_task(self): """ Get the 'mib_data_sync' attribute of the ONU """ try: if self._delay > 0: yield asleep(self._delay) if self._success: self.deferred.callback(self._value) self.deferred.errback(failure.Failure(self._value)) except Exception as e: self.deferred.errback(failure.Failure(e))
def perform_get_capabilities(self): """ Perform the MIB Capabilities sequence. The sequence is to perform a Get request with the attribute mask equal to 'me_type_table'. The response to this request will carry the size of (number of get-next sequences). Then a loop is entered and get-next commands are sent for each sequence requested. """ self.log.info('perform-get') try: self.strobe_watchdog() self._supported_entities = yield self.get_supported_entities() self.strobe_watchdog() self._supported_msg_types = yield self.get_supported_message_types( ) self.log.debug('get-success', supported_entities=self.supported_managed_entities, supported_msg_types=self.supported_message_types) results = { 'supported-managed-entities': self.supported_managed_entities, 'supported-message-types': self.supported_message_types } self.deferred.callback(results) except Exception as e: self.log.exception('perform-get', e=e) self.deferred.errback(failure.Failure(e))
def perform_multicast(self): self.log.debug('performing-multicast', device_id=self._device._device_id, uni_id=self._uni_port.uni_id, vlan_id=self._set_vlan_id, multicast_gem_id=self._mcast_gem_id) try: # create gem port and use tcont yield self._create_gem_ports() # create multicast operation profile yield self._create_mcast_operation_profile() # set multicast operation profile yield self._set_mcast_operation_profile() # create multicast subscriber config data yield self._create_mcast_subscriber_conf_info() # create mac bridge port configuration data yield self._create_mac_bridge_configuration_data() # create vlan filtering entity yield self._create_vlan_tagging_filter_data() # set vlan filtering entity yield self._set_vlan_tagging_filter_data() self.deferred.callback(self) except Exception as e: self.log.exception('multicast exception', e=e) self.deferred.errback(failure.Failure(e))
def perform_get_capabilities(self): """ Perform the MIB Capabilities sequence. The sequence is to perform a Get request with the attribute mask equal to 'me_type_table'. The response to this request will carry the size of (number of get-next sequences). Then a loop is entered and get-next commands are sent for each sequence requested. """ self.log.info('perform-get') if self._omci_managed: # Return generator deferred/results return super(AdtnCapabilitiesTask, self).perform_get_capabilities() # Fixed values, no need to query try: self._supported_entities = self.supported_managed_entities self._supported_msg_types = self.supported_message_types self.log.debug('get-success', supported_entities=self.supported_managed_entities, supported_msg_types=self.supported_message_types) results = { 'supported-managed-entities': self.supported_managed_entities, 'supported-message-types': self.supported_message_types } self.deferred.callback(results) except Exception as e: self.log.exception('get-failed', e=e) self.deferred.errback(failure.Failure(e))
def perform_vlan_tagging(self): """ Perform the vlan tagging """ self.log.debug('vlan-filter-tagging-task', uni_port=self._uni_port, set_vlan_id=self._set_vlan_id, set_vlan_pcp=self._set_vlan_pcp, match_vlan=self._match_vlan, tp_id=self._tp_id, add_tag=self._add_tag) try: if self._add_tag: if not self._onu_handler.args.accept_incremental_evto_update: yield self._bulk_update_evto_and_vlan_tag_filter() else: yield self._incremental_update_evto_and_vlan_tag_filter() else: # addTag = False if self._onu_handler.args.accept_incremental_evto_update: self.log.info('removing-vlan-tagging') yield self._delete_service_flow() yield self._delete_vlan_filter_entity() else: # Will be reset anyway on new vlan tagging operation self.log.info("not-removing-vlan-tagging") self.deferred.callback(self) except Exception as e: self.log.exception('setting-vlan-tagging', e=e) self.deferred.errback(failure.Failure(e))
def _on_timeout(err): all_states = [_svc.state for _svc in services().values()] if 'INFLUENCE' in all_states or 'STARTING' in all_states or 'STOPPING' in all_states: restart_result.errback(failure.Failure(Exception('timeout'))) return err _do_stop() return None
def perform_delete(self): """ Perform the delete requests """ self.log.debug('perform-delete') try: for me in self._me_tuples: class_id = me[0] entity_id = me[1] frame = OmciFrame(transaction_id=None, message_type=OmciDelete.message_id, omci_message=OmciDelete( entity_class=class_id, entity_id=entity_id)) self.strobe_watchdog() results = yield self._device.omci_cc.send(frame) status = results.fields['omci_message'].fields['success_code'] self.log.debug('perform-delete-status', status=status) # Did it fail, it instance does not exist, not an error if status != RC.Success.value and status != RC.UnknownInstance.value: msg = 'ME: {}, entity: {} failed with status {}'.format( class_id, entity_id, status) raise DeletePMException(msg) self.log.debug('delete-pm-success', class_id=class_id, entity_id=entity_id) self.deferred.callback(self) except Exception as e: self.log.exception('perform-create', e=e) self.deferred.errback(failure.Failure(e))
def perform_get_omci(self): """ Perform the initial get request """ self.log.info('perform-get') try: frame = MEFrame(self._entity_class, self._entity_id, self._attributes).get() self.strobe_watchdog() results = yield self._device.omci_cc.send(frame) status = results.fields['omci_message'].fields['success_code'] self.log.info('perform-get-status', status=status) # Success? if status == RC.Success.value: self._results = results results_omci = results.fields['omci_message'].fields # Were all attributes fetched? missing_attr = frame.fields['omci_message'].fields['attributes_mask'] ^ \ results_omci['attributes_mask'] if missing_attr > 0: self.strobe_watchdog() self._local_deferred = reactor.callLater( 0, self.perform_get_missing_attributes, missing_attr) returnValue(self._local_deferred) elif status == RC.AttributeFailure.value: # What failed? Note if only one attribute was attempted, then # that is an overall failure if not self._allow_failure or len(self._attributes) <= 1: raise GetException( 'Get failed with status code: {}'.format( RC.AttributeFailure.value)) self.strobe_watchdog() self._local_deferred = reactor.callLater( 0, self.perform_get_failed_attributes, results, self._attributes) returnValue(self._local_deferred) else: raise GetException( 'Get failed with status code: {}'.format(status)) self.log.info('get-completed') self.deferred.callback(self) except Exception as e: self.log.exception('perform-get', e=e, class_id=self._entity_class, entity_id=self._entity_id, attributes=self._attributes) self.deferred.errback(failure.Failure(e))
def perform_mib_download(self): """ Send the commands to minimally configure the PON, Bridge, and UNI ports for this device. The application of any service flows and other characteristics are done as needed. """ self.log.debug('function-entry') self.log.info('perform-download') device = self._handler.adapter_agent.get_device(self.device_id) def resources_available(): return (len(self._handler.uni_ports) > 0 and len(self._handler.pon_port.tconts) and len(self._handler.pon_port.gem_ports)) if self._handler.enabled and resources_available(): device.reason = 'performing-initial-mib-download' self._handler.adapter_agent.update_device(device) try: # Lock the UNI ports to prevent any alarms during initial configuration # of the ONU self.strobe_watchdog() yield self.enable_uni(self._uni_port, True) # Provision the initial bridge configuration yield self.perform_initial_bridge_setup() # And not all the service specific work yield self.perform_service_specific_steps() # And re-enable the UNIs if needed yield self.enable_uni(self._uni_port, False) self.deferred.callback('initial-download-success') except TimeoutError as e: self.deferred.errback(failure.Failure(e)) else: e = MibResourcesFailure('Required resources are not available', tconts=len(self._handler.pon_port.tconts), gems=len(self._handler.pon_port.gem_ports), unis=len(self._handler.uni_ports)) self.deferred.errback(failure.Failure(e))
def ebRequestWriting(err): if self._state == 'TRANSMITTING': self._state = 'GENERATION_FAILED' self.transport.loseConnection() self._finishedRequest.errback( failure.Failure(RequestGenerationFailed([err]))) else: log.err(err, 'Error writing request, but not in valid state ' 'to finalize request: %s' % self._state)
def perform_reboot(self): """ Perform the reboot requests Depending on the ONU implementation, a response may not be returned. For this reason, a timeout is considered successful. """ self.log.info('perform-reboot') try: frame = OntGFrame().reboot(reboot_code=self._flags) self.strobe_watchdog() results = yield self._device.omci_cc.send(frame, timeout=self._timeout, high_priority=True) status = results.fields['omci_message'].fields['success_code'] self.log.debug('reboot-status', status=status) # Did it fail if status != RC.Success.value: if self._flags != RebootFlags.Reboot_Unconditionally and\ status == RC.DeviceBusy.value: raise DeviceBusy('ONU is busy, try again later') else: msg = 'Reboot request failed with status {}'.format(status) raise RebootException(msg) self.log.info('reboot-success') self.deferred.callback(self) except TimeoutError: self.log.info('timeout', msg='Request timeout is not considered an error') self.deferred.callback(None) except DeviceBusy as e: self.log.warn('perform-reboot', msg=e) self.deferred.errback(failure.Failure(e)) except Exception as e: self.log.exception('perform-reboot', e=e) self.deferred.errback(failure.Failure(e))
def perform_service_download(self): """ Send the commands to minimally configure the PON, Bridge, and UNI ports for this device. The application of any service flows and other characteristics are done once resources (gem-ports, tconts, ...) have been defined. """ self.log.debug('perform-service-download') device = self._handler.adapter_agent.get_device(self.device_id) def resources_available(): return (len(self._handler.uni_ports) > 0 and len(self._pon.tconts) and len(self._pon.gem_ports)) if self._handler.enabled and resources_available(): device.reason = 'Performing Service OMCI Download' self._handler.adapter_agent.update_device(device) try: # Lock the UNI ports to prevent any alarms during initial configuration # of the ONU self.strobe_watchdog() # Provision the initial bridge configuration yield self.perform_service_specific_steps() # And re-enable the UNIs if needed yield self.enable_unis(self._handler.uni_ports, False) # If here, we are done device = self._handler.adapter_agent.get_device(self.device_id) device.reason = '' self._handler.adapter_agent.update_device(device) self.deferred.callback('service-download-success') except TimeoutError as e: self.deferred.errback(failure.Failure(e)) except Exception as e: self.deferred.errback(failure.Failure(e)) else: # TODO: Provide better error reason, what was missing... e = ServiceResourcesFailure('Required resources are not available') self.deferred.errback(failure.Failure(e))
def perform_lock(self): """ Perform the lock/unlock """ self.log.info('setting-uni-lock-state', lock=self._lock) try: state = 1 if self._lock else 0 # lock the whole ont and all the pptp. some onu dont causing odd behavior. msg = OntGFrame(attributes={'administrative_state': state}) frame = msg.set() self.log.debug('openomci-msg', msg=msg) results = yield self._device.omci_cc.send(frame) self.strobe_watchdog() status = results.fields['omci_message'].fields['success_code'] self.log.info('response-status', status=status) # Success? if status in (RC.Success.value, RC.InstanceExists): self.log.debug('set-lock-ontg', lock=self._lock) else: self.log.warn('cannot-set-lock-ontg', lock=self._lock) pptp = self._config.pptp_entities for key, value in pptp.iteritems(): msg = PptpEthernetUniFrame( key, attributes=dict(administrative_state=state)) frame = msg.set() self.log.debug('openomci-msg', msg=msg) results = yield self._device.omci_cc.send(frame) self.strobe_watchdog() status = results.fields['omci_message'].fields['success_code'] self.log.info('response-status', status=status) # Success? if status in (RC.Success.value, RC.InstanceExists): self.log.debug('set-lock-uni', uni=key, value=value, lock=self._lock) else: self.log.warn('cannot-set-lock-uni', uni=key, value=value, lock=self._lock) self.deferred.callback(self) except Exception as e: self.log.exception('setting-uni-lock-state', e=e) self.deferred.errback(failure.Failure(e))
def get_supported_entities(self): """ Get the supported ME Types for this ONU. """ try: # Get the number of requests needed frame = OmciFrame(me_type_table=True).get() self.strobe_watchdog() results = yield self._device.omci_cc.send(frame) omci_msg = results.fields['omci_message'] status = omci_msg.fields['success_code'] if status != ReasonCodes.Success.value: raise GetCapabilitiesFailure( 'Get count of supported entities failed with status code: {}' .format(status)) data = omci_msg.fields['data']['me_type_table'] count = self.get_count_from_data_buffer(bytearray(data)) seq_no = 0 data_buffer = bytearray(0) self.log.debug('me-type-count', octets=count, data=hexlify(data)) # Start the loop for offset in xrange(0, count, self._pdu_size): frame = OmciFrame(me_type_table=seq_no).get_next() seq_no += 1 self.strobe_watchdog() results = yield self._device.omci_cc.send(frame) omci_msg = results.fields['omci_message'] status = omci_msg.fields['success_code'] if status != ReasonCodes.Success.value: raise GetCapabilitiesFailure( 'Get supported entities request at offset {} of {} failed with status code: {}' .format(offset + 1, count, status)) # Extract the data num_octets = count - offset if num_octets > self._pdu_size: num_octets = self._pdu_size data = omci_msg.fields['data']['me_type_table'] data_buffer += bytearray(data[:num_octets]) me_types = {(data_buffer[x] << 8) + data_buffer[x + 1] for x in xrange(0, len(data_buffer), 2)} returnValue(me_types) except Exception as e: self.log.exception('get-entities', e=e) self.deferred.errback(failure.Failure(e))
def delete_gem_port_nw_ctp_and_associated_me(self): self.log.info('deleting-gem-port-iw') omci_cc = self._onu_device.omci_cc try: ################################################################################ # Delete GemPortNetworkCTP and GemPortInterworkingPoint ################################################################################ # The _gem_port.remove_from_hardware is already doing check_status_and_state yield self._gem_port.remove_from_hardware(omci_cc) self.deferred.callback("tech-profile-remove-success--gem-port") except TimeoutError as e: self.log.warn('rx-timeout-tech-profile', e=e) self.deferred.errback(failure.Failure(e)) except Exception as e: self.log.exception('omci-delete-tech-profile', e=e) self.deferred.errback(failure.Failure(e))
def perform_mib_download(self): """ Send the commands to minimally configure the PON, Bridge, and UNI ports for this device. The application of any service flows and other characteristics are done once resources (gem-ports, tconts, ...) have been defined. """ self.log.info('perform-initial-download') device = self._handler.adapter_agent.get_device(self.device_id) def resources_available(): return len(self._handler.uni_ports) > 0 if self._handler.enabled and resources_available(): device.reason = 'Performing Initial OMCI Download' self._handler.adapter_agent.update_device(device) try: # Lock the UNI ports to prevent any alarms during initial configuration # of the ONU self.strobe_watchdog() # yield self.enable_unis(self._handler.uni_ports, True) # Provision the initial bridge configuration yield self.perform_initial_bridge_setup() # If here, we are done with the generic MIB download device = self._handler.adapter_agent.get_device(self.device_id) device.reason = 'Initial OMCI Download Complete' self._handler.adapter_agent.update_device(device) self.deferred.callback('MIB Download - success') except TimeoutError as e: self.deferred.errback(failure.Failure(e)) else: # TODO: Provide better error reason, what was missing... e = MibResourcesFailure('ONU is not enabled') self.deferred.errback(failure.Failure(e))