def get_msg(self, message: Any) -> AcsMsgAndTransition: request = models.SetParameterValues() request.ParameterList = models.ParameterValueList() param_values = get_all_param_values_to_set(self.acs.desired_cfg, self.acs.device_cfg, self.acs.data_model) request.ParameterList.arrayType = 'cwmp:ParameterValueStruct[%d]' \ % len(param_values) request.ParameterList.ParameterValueStruct = [] logger.debug('Sending TR069 request to set CPE parameter values: %s', str(param_values)) for name, value in param_values.items(): param_info = self.acs.data_model.get_parameter(name) type_ = param_info.type name_value = models.ParameterValueStruct() name_value.Value = models.anySimpleType() name_value.Name = param_info.path enb_value = self.acs.data_model.transform_for_enb(name, value) if type_ in ('int', 'unsignedInt'): name_value.Value.type = 'xsd:%s' % type_ name_value.Value.Data = str(enb_value) elif type_ == 'boolean': # Boolean values have integral representations in spec name_value.Value.type = 'xsd:boolean' name_value.Value.Data = str(int(enb_value)) elif type_ == 'string': name_value.Value.type = 'xsd:string' name_value.Value.Data = str(enb_value) else: raise Tr069Error('Unsupported type for %s: %s' % (name, type_)) if param_info.is_invasive: self.acs.are_invasive_changes_applied = False request.ParameterList.ParameterValueStruct.append(name_value) return AcsMsgAndTransition(request, self.done_transition)
def bandwidth(bandwidth_rbs: Union[str, int, float]) -> float: """ Map bandwidth in number of RBs to MHz TODO: TR-196 spec says this should be '6' rather than 'n6', but BaiCells eNodeB uses 'n6'. Need to resolve this. Args: bandwidth_rbs (str): Bandwidth in number of RBs Returns: str: Bandwidth in MHz """ if bandwidth_rbs in BANDWIDTH_RBS_TO_MHZ_MAP: return BANDWIDTH_RBS_TO_MHZ_MAP[bandwidth_rbs] logger.debug('Unknown bandwidth_rbs (%s)', str(bandwidth_rbs)) if bandwidth_rbs in BANDWIDTH_MHZ_LIST: return bandwidth_rbs elif isinstance(bandwidth_rbs, str): mhz = None if bandwidth_rbs.isdigit(): mhz = int(bandwidth_rbs) elif bandwidth_rbs.replace('.', '', 1).isdigit(): mhz = float(bandwidth_rbs) if mhz in BANDWIDTH_MHZ_LIST: return mhz raise ConfigurationError('Unknown bandwidth specification (%s)' % str(bandwidth_rbs))
def read_msg(self, message: Any) -> AcsReadMsgResult: """ Process GetParameterValuesResponse Object parameters that have a reported value of None indicate that the object is not in the eNB's configuration. Most eNB devices will reply with a Fault message if we try to get values of parameters that don't exist on the data model, so this is an idiosyncrasy of Baicells QAFB. """ if not isinstance(message, models.GetParameterValuesResponse): return AcsReadMsgResult(False, None) path_to_val = {} for param_value_struct in message.ParameterList.ParameterValueStruct: path_to_val[param_value_struct.Name] = \ param_value_struct.Value.Data logger.debug('Received object parameters: %s', str(path_to_val)) num_plmns = self.acs.data_model.get_num_plmns() for i in range(1, num_plmns + 1): obj_name = ParameterName.PLMN_N % i obj_to_params = self.acs.data_model.get_numbered_param_names() param_name_list = obj_to_params[obj_name] for name in param_name_list: path = self.acs.data_model.get_parameter(name).path if path in path_to_val: value = path_to_val[path] if value is None: continue if obj_name not in self.acs.device_cfg.get_object_names(): self.acs.device_cfg.add_object(obj_name) magma_value = \ self.acs.data_model.transform_for_magma(name, value) self.acs.device_cfg.set_parameter_for_object(name, magma_value, obj_name) # Now we have enough information to build the desired configuration if self.acs.desired_cfg is None: self.acs.desired_cfg = build_desired_config( self.acs.mconfig, self.acs.service_config, self.acs.device_cfg, self.acs.data_model, self.acs.config_postprocessor, ) if len(get_all_objects_to_delete(self.acs.desired_cfg, self.acs.device_cfg)) > 0: return AcsReadMsgResult(True, self.rm_obj_transition) elif len(get_all_objects_to_add(self.acs.desired_cfg, self.acs.device_cfg)) > 0: return AcsReadMsgResult(True, self.add_obj_transition) elif len(get_all_param_values_to_set(self.acs.desired_cfg, self.acs.device_cfg, self.acs.data_model)) > 0: return AcsReadMsgResult(True, self.set_params_transition) return AcsReadMsgResult(True, self.skip_transition)
def _mark_as_configured(self) -> None: """ A successful attempt at setting parameter values means that we need to update what we think the eNB's configuration is to match what we just set the parameter values to. """ # Values of parameters name_to_val = get_param_values_to_set(self.acs.desired_cfg, self.acs.device_cfg, self.acs.data_model) for name, val in name_to_val.items(): magma_val = self.acs.data_model.transform_for_magma(name, val) self.acs.device_cfg.set_parameter(name, magma_val) # Values of object parameters obj_to_name_to_val = get_obj_param_values_to_set( self.acs.desired_cfg, self.acs.device_cfg, self.acs.data_model) for obj_name, name_to_val in obj_to_name_to_val.items(): for name, val in name_to_val.items(): logger.debug('Set obj: %s, name: %s, val: %s', str(obj_name), str(name), str(val)) magma_val = self.acs.data_model.transform_for_magma(name, val) self.acs.device_cfg.set_parameter_for_object( name, magma_val, obj_name) logger.info('Successfully configured CPE parameters!')
def read_msg(self, message: Any) -> AcsReadMsgResult: """ Process either GetParameterValuesResponse or a Fault """ if type(message) == models.Fault: self.acs.data_model.set_parameter_presence( self.optional_param, False, ) elif type(message) == models.GetParameterValuesResponse: name_to_val = parse_get_parameter_values_response( self.acs.data_model, message, ) logger.debug( 'Received CPE parameter values: %s', str(name_to_val), ) for name, val in name_to_val.items(): self.acs.data_model.set_parameter_presence( self.optional_param, True, ) magma_val = self.acs.data_model.transform_for_magma(name, val) self.acs.device_cfg.set_parameter(name, magma_val) else: return AcsReadMsgResult(False, None) if get_optional_param_to_check(self.acs.data_model) is not None: return AcsReadMsgResult(True, None) return AcsReadMsgResult(True, self.done_transition)
def _handle_tr069_message( cls, ctx: WsgiMethodContext, message: ComplexModelBase, ) -> ComplexModelBase: # Log incoming msg logger.debug('Handling TR069 message: %s %s', message.__class__.__name__, str(as_dict(message))) req = cls._get_tr069_response_from_sm(ctx, message) # Log outgoing msg logger.debug('Sending TR069 message: %s %s', req.__class__.__name__, str(as_dict(req))) # Set header ctx.out_header = models.ID(mustUnderstand='1') ctx.out_header.Data = 'null' # Set return message name if isinstance(req, models.DummyInput): # Generate 'empty' request to CPE using empty message name ctx.descriptor.out_message.Attributes.sub_name = 'EmptyHttp' return models.AcsToCpeRequests() ctx.descriptor.out_message.Attributes.sub_name = req.__class__.__name__ return cls._generate_acs_to_cpe_request_copy(req)
def start_fw_upgrade_timeout(self) -> None: """ Start a firmware upgrade timeout timer. When initialing a firmware upgrade download, the eNB can take an unknown amount of time for the download to finish. This process is indicated by a TransferComplete TR069 message, but the enB can still operate and can apply the firmware at any time and reboot. Since we do not want to re-issue a download request (eNB hasn't updated, its SW version is still 'old' and the firmware version check will still detect and older FW version still present on the eNB) we want to hold with the download flow for some time - which is what this timer is for. """ if self.fw_upgrade_timeout_handler is not None: return logger.debug( 'ACS starting fw upgrade timeout for %d seconds', self.FW_UPGRADE_TIMEOUT, ) self.fw_upgrade_timeout_handler = self.event_loop.call_later( self.FW_UPGRADE_TIMEOUT, self.stop_fw_upgrade_timeout, )
def _parse_sw_version(version_str): """ Parse SW version string. Expects format: BaiStation_V100R001C00B110SPC003 For the above version string, returns: [100, 1, 0, 110, 3] Note: trailing characters (for dev builds) are ignored. Null is returned for version strings that don't match the above format. """ logger.debug('Got firmware version: %s', version_str) version = re.findall( r'BaiStation_V(\d{3})R(\d{3})C(\d{2})B(\d{3})SPC(\d{3})', version_str) if not version: return None elif len(version) > 1: logger.warning('SW version (%s) not formatted as expected', version_str) version_int = [] for num in version[0]: try: version_int.append(int(num)) except ValueError: logger.warning('SW version (%s) not formatted as expected', version_str) return None logger.debug('Parsed firmware version: %s', version_int) return version_int
def transition(self, next_state: str) -> Any: logger.debug( 'State transition from <%s> to <%s>', self.state.__class__.__name__, next_state, ) self.state.exit() self.state = self.state_map[next_state] self.state.enter()
def read_msg(self, message: Any) -> AcsReadMsgResult: """ Process GetParameterValuesResponse """ if not isinstance(message, models.GetParameterValuesResponse): return AcsReadMsgResult(False, None) name_to_val = parse_get_parameter_values_response( self.acs.data_model, message) logger.debug('Received CPE parameter values: %s', str(name_to_val)) for name, val in name_to_val.items(): magma_val = self.acs.data_model.transform_for_magma(name, val) self.acs.device_cfg.set_parameter(name, magma_val) return AcsReadMsgResult(True, self.done_transition)
def stop_fw_upgrade_timeout(self) -> None: """ Stop firmware upgrade timeout timer. Invoking this method will re-enable firmware software version checking in the Download states. """ if self.fw_upgrade_timeout_handler is not None: logger.debug('ACS stopping fw upgrade timeout.') self.fw_upgrade_timeout_handler.cancel() self.fw_upgrade_timeout_handler = None
def _get_param_values_by_path(inform: models.Inform, ) -> Dict[str, Any]: if not hasattr(inform, 'ParameterList') or \ not hasattr(inform.ParameterList, 'ParameterValueStruct'): raise ConfigurationError('Did not receive ParamterList in Inform') param_values_by_path = {} for param_value in inform.ParameterList.ParameterValueStruct: path = param_value.Name value = param_value.Value.Data logger.debug('(Inform msg) Received parameter: %s = %s', path, value) param_values_by_path[path] = value return param_values_by_path
def _handle_tr069_message( cls, ctx: WsgiMethodContext, message: ComplexModelBase, ) -> ComplexModelBase: # Log incoming msg if hasattr(message, 'as_dict'): logger.debug('Handling TR069 message: %s', str(type(message))) else: logger.debug('Handling TR069 message.') # The manager will route the request to the state machine handling # the specific eNodeB. req = cls.state_machine_manager.handle_tr069_message(ctx, message) # Log outgoing msg if hasattr(req, 'as_dict'): logger.debug('Sending TR069 message: %s', str(req.as_dict())) else: logger.debug('Sending TR069 message.') # Set header ctx.out_header = models.ID(mustUnderstand='1') ctx.out_header.Data = 'null' # Set return message name if isinstance(req, models.DummyInput): # Generate 'empty' request to CPE using empty message name ctx.descriptor.out_message.Attributes.sub_name = 'EmptyHttp' return models.AcsToCpeRequests() ctx.descriptor.out_message.Attributes.sub_name = req.__class__.__name__ return cls._generate_acs_to_cpe_request_copy(req)
def get_msg(self, message: Any) -> AcsMsgAndTransition: request = models.AddObject() self.added_param = get_all_objects_to_add(self.acs.desired_cfg, self.acs.device_cfg)[0] desired_param = self.acs.data_model.get_parameter(self.added_param) desired_path = desired_param.path path_parts = desired_path.split('.') # If adding enumerated object, ie. XX.N. we should add it to the # parent object XX. so strip the index if len(path_parts) > 2 and \ path_parts[-1] == '' and path_parts[-2].isnumeric(): logger.debug('Stripping index from path=%s', desired_path) desired_path = '.'.join(path_parts[:-2]) + '.' request.ObjectName = desired_path return AcsMsgAndTransition(request, None)
def read_msg(self, message: Any) -> AcsReadMsgResult: """ Process GetParameterValuesResponse """ if not isinstance(message, models.GetParameterValuesResponse): return AcsReadMsgResult(False, None) # Current values of the fetched parameters name_to_val = parse_get_parameter_values_response(self.acs.data_model, message) logger.debug('Received Parameters: %s', str(name_to_val)) # Update device configuration for name in name_to_val: magma_value = \ self.acs.data_model.transform_for_magma(name, name_to_val[name]) self.acs.device_cfg.set_parameter(name, magma_value) return AcsReadMsgResult(True, self.get_next_state())
def _transition_for_unexpected_msg(self, message: Any) -> None: """ eNB devices may send an Inform message in the middle of a provisioning session. To deal with this, transition to a state that expects an Inform message, but also track the status of the eNB as not having been disconnected. """ if isinstance(message, models.Inform): logger.debug('ACS in (%s) state. Received an Inform message', self.state.state_description()) self._reset_state_machine(self.service) elif isinstance(message, models.Fault): logger.debug('ACS in (%s) state. Received a Fault <%s>', self.state.state_description(), message.FaultString) self.transition(self.unexpected_fault_state_name) else: raise ConfigurationError('Cannot handle unexpected TR069 msg')
def _get_enb_label_from_request(self, request) -> str: label = 'default' ip = request.headers.get('X-Forwarded-For') if ip is None: peername = request.transport.get_extra_info('peername') if peername is not None: ip, _ = peername if ip is None: return label label = self.enb_manager.get_serial_of_ip(ip) if label: logger.debug('Found serial %s for ip %s', label, ip) else: logger.error("Couldn't find serial for ip", ip) return label
def read_msg(self, message: Any) -> AcsReadMsgResult: """ It's expected that we transition into this state right after receiving an Inform message and replying with an InformResponse. At that point, the eNB sends an empty HTTP request (aka DummyInput) to initiate the rest of the provisioning process """ if not isinstance(message, models.DummyInput): logger.debug("Ignoring message %s", str(type(message))) return AcsReadMsgResult(msg_handled=False, next_state=None) if self.unknown_param_transition: if get_optional_param_to_check(self.acs.data_model): return AcsReadMsgResult( msg_handled=True, next_state=self.unknown_param_transition, ) return AcsReadMsgResult( msg_handled=True, next_state=self.done_transition, )
def get_firmware_upgrade_download_config(acs): device_serial_number = '' if acs.device_cfg.has_parameter(ParameterName.SERIAL_NUMBER): device_serial_number = acs.device_cfg.get_parameter( ParameterName.SERIAL_NUMBER, ) fw_upgrade_config = _get_firmware_upgrade_download_config_for_serial( acs, device_serial_number, ) if fw_upgrade_config: logger.debug(f'Found {fw_upgrade_config=} for {device_serial_number=}') return fw_upgrade_config device_model = acs.device_name fw_upgrade_config = _get_firmware_upgrade_download_config_for_model( acs, device_model, ) if fw_upgrade_config: logger.debug(f'Found {fw_upgrade_config=} for {device_model=}') return fw_upgrade_config
def read_msg(self, message: Any) -> AcsReadMsgResult: if not isinstance(message, models.GetParameterValuesResponse): return AcsReadMsgResult(msg_handled=False, next_state=None) # Current values of the fetched parameters name_to_val = parse_get_parameter_values_response( self.acs.data_model, message, ) EnodebdLogger.debug('Received Parameters: %s', str(name_to_val)) # Update device configuration StatusParameters.set_magma_device_cfg( name_to_val, self.acs.device_cfg, ) return AcsReadMsgResult( msg_handled=True, next_state=self.done_transition, )
def enter(self): """ Enter the state """ get_cbsd_state_request = CBSDRequest( serial_number=self.acs.device_cfg.get_parameter( ParameterName.SERIAL_NUMBER), ) state = get_cbsd_state(get_cbsd_state_request) qrtb_update_desired_config_from_cbsd_state(state, self.acs.desired_cfg) # NOTE: In case GPS scan is not completed, eNB reports LAT and LONG values as 0. # Only update CBSD in Domain Proxy when all params are available. gps_status = strtobool( self.acs.device_cfg.get_parameter(ParameterName.GPS_STATUS)) if gps_status: enodebd_update_cbsd_request = build_enodebd_update_cbsd_request( serial_number=self.acs.device_cfg.get_parameter( ParameterName.SERIAL_NUMBER), latitude_deg=self.acs.device_cfg.get_parameter( ParameterName.GPS_LAT), longitude_deg=self.acs.device_cfg.get_parameter( ParameterName.GPS_LONG), indoor_deployment=self.acs.device_cfg.get_parameter( ParameterName.INDOOR_DEPLOYMENT), antenna_height=self.acs.device_cfg.get_parameter( ParameterName.ANTENNA_HEIGHT), antenna_height_type=self.acs.device_cfg.get_parameter( ParameterName.ANTENNA_HEIGHT_TYPE), antenna_gain=self.acs.device_cfg.get_parameter( ParameterName.ANTENNA_GAIN), cbsd_category=self.acs.device_cfg.get_parameter( ParameterName.CBSD_CATEGORY), ) enodebd_update_cbsd(enodebd_update_cbsd_request) else: EnodebdLogger.debug( "Waiting for GPS to sync, before updating CBSD params in Domain Proxy." )
def _get_firmware_upgrade_download_config(acs, fw_version: str): if not fw_version: return {} firmware_cfg = acs.service_config.get('firmware_upgrade_download', {}).get( 'firmwares', {}, ).get(fw_version, {}) if not firmware_cfg: logger.debug( f'Could not find Firmware Upgrade download version {fw_version} in config.', ) return {} if not firmware_cfg.get('url', ''): logger.debug( f'Firmware Upgrade download config for {fw_version} does not have a valid url.', ) return {} # add a 'version' key for easy extraction later firmware_cfg['version'] = fw_version return firmware_cfg
def should_transition_to_firmware_upgrade_download(acs): device_sw_version = "" device_serial_number = "" if acs.device_cfg.has_parameter(ParameterName.SW_VERSION): device_sw_version = acs.device_cfg.get_parameter( ParameterName.SW_VERSION, ) if acs.device_cfg.has_parameter(ParameterName.SERIAL_NUMBER): device_serial_number = acs.device_cfg.get_parameter( ParameterName.SERIAL_NUMBER, ) if not device_sw_version or not device_serial_number: logger.debug( f'Skipping FW Download for eNB, missing device config: {device_sw_version=}, {device_serial_number=}.', ) return False if acs.is_fw_upgrade_in_progress(): logger.debug( 'Skipping FW Download for eNB [%s], firmware upgrade in progress.', device_serial_number, ) return False fw_upgrade_config = get_firmware_upgrade_download_config(acs) if not fw_upgrade_config: logger.debug( 'Skipping FW Download for eNB [%s], missing firmware upgrade config in enodebd.yml.', device_serial_number, ) return False target_software_version = fw_upgrade_config.get('version', '') if device_sw_version == target_software_version: logger.debug( 'Skipping FW Download for eNB [%s], eNB Software Version [%s] up to date with firmware upgrade config.', device_serial_number, target_software_version, ) acs.stop_fw_upgrade_timeout() return False logger.info( 'Initiate FW Download for eNB [%s], eNB SW Version [%s], target SW Version [%s]', device_serial_number, device_sw_version, target_software_version, ) return True
def read_msg(self, message: Any) -> AcsReadMsgResult: """ Process GetParameterValuesResponse """ if not isinstance(message, models.GetParameterValuesResponse): return AcsReadMsgResult(False, None) path_to_val = {} if hasattr(message.ParameterList, 'ParameterValueStruct') and \ message.ParameterList.ParameterValueStruct is not None: for param_value_struct in message.ParameterList.ParameterValueStruct: path_to_val[param_value_struct.Name] = \ param_value_struct.Value.Data logger.debug('Received object parameters: %s', str(path_to_val)) # Number of PLMN objects reported can be incorrect. Let's count them num_plmns = 0 obj_to_params = self.acs.data_model.get_numbered_param_names() while True: obj_name = ParameterName.PLMN_N % (num_plmns + 1) if obj_name not in obj_to_params or len( obj_to_params[obj_name]) == 0: logger.warning( "eNB has PLMN %s but not defined in model", obj_name, ) break param_name_list = obj_to_params[obj_name] obj_path = self.acs.data_model.get_parameter( param_name_list[0]).path if obj_path not in path_to_val: break if not self.acs.device_cfg.has_object(obj_name): self.acs.device_cfg.add_object(obj_name) num_plmns += 1 for name in param_name_list: path = self.acs.data_model.get_parameter(name).path value = path_to_val[path] magma_val = \ self.acs.data_model.transform_for_magma(name, value) self.acs.device_cfg.set_parameter_for_object( name, magma_val, obj_name, ) num_plmns_reported = \ int(self.acs.device_cfg.get_parameter(ParameterName.NUM_PLMNS)) if num_plmns != num_plmns_reported: logger.warning( "eNB reported %d PLMNs but found %d", num_plmns_reported, num_plmns, ) self.acs.device_cfg.set_parameter( ParameterName.NUM_PLMNS, num_plmns, ) # Now we can have the desired state if self.acs.desired_cfg is None: self.acs.desired_cfg = build_desired_config( self.acs.mconfig, self.acs.service_config, self.acs.device_cfg, self.acs.data_model, self.acs.config_postprocessor, ) if len( get_all_objects_to_delete( self.acs.desired_cfg, self.acs.device_cfg, ), ) > 0: return AcsReadMsgResult(True, self.rm_obj_transition) elif len( get_all_objects_to_add( self.acs.desired_cfg, self.acs.device_cfg, ), ) > 0: return AcsReadMsgResult(True, self.add_obj_transition) elif len( get_all_param_values_to_set( self.acs.desired_cfg, self.acs.device_cfg, self.acs.data_model, ), ) > 0: return AcsReadMsgResult(True, self.set_params_transition) return AcsReadMsgResult(True, self.skip_transition)
def _set_earfcn_freq_band_mode( device_cfg: EnodebConfiguration, cfg: EnodebConfiguration, data_model: DataModel, earfcndl: int, ) -> None: """ Set the following parameters: - EARFCNDL - EARFCNUL - Band """ # Note: validation of EARFCNDL done by mapping function. If invalid # EARFCN, raise ConfigurationError try: band, duplex_mode, earfcnul = map_earfcndl_to_band_earfcnul_mode( earfcndl) except ValueError as err: raise ConfigurationError(err) # Verify capabilities duplex_capability =\ device_cfg.get_parameter(ParameterName.DUPLEX_MODE_CAPABILITY) if duplex_mode == DuplexMode.TDD and duplex_capability != 'TDDMode': raise ConfigurationError( ('eNodeB duplex mode capability is <{0}>, ' 'but earfcndl is <{1}>, giving duplex ' 'mode <{2}> instead').format(duplex_capability, str(earfcndl), str(duplex_mode))) elif duplex_mode == DuplexMode.FDD and duplex_capability != 'FDDMode': raise ConfigurationError( ('eNodeB duplex mode capability is <{0}>, ' 'but earfcndl is <{1}>, giving duplex ' 'mode <{2}> instead').format(duplex_capability, str(earfcndl), str(duplex_mode))) elif duplex_mode not in [DuplexMode.TDD, DuplexMode.FDD]: raise ConfigurationError('Invalid duplex mode (%s)' % str(duplex_mode)) # Baicells indicated that they no longer use the band capability list, # so it may not be populated correctly band_capability_list = device_cfg.get_parameter( ParameterName.BAND_CAPABILITY) band_capabilities = band_capability_list.split(',') if str(band) not in band_capabilities: logger.warning( 'Band %d not in capabilities list (%s). Continuing' ' with config because capabilities list may not be' ' correct', band, band_capabilities) cfg.set_parameter(ParameterName.EARFCNDL, earfcndl) if duplex_mode == DuplexMode.FDD: _set_param_if_present(cfg, data_model, ParameterName.EARFCNUL, earfcnul) else: logger.debug('Not setting EARFCNUL - duplex mode is not FDD') _set_param_if_present(cfg, data_model, ParameterName.BAND, band) if duplex_mode == DuplexMode.TDD: logger.debug('Set EARFCNDL=%d, Band=%d', earfcndl, band) else: logger.debug('Set EARFCNDL=%d, EARFCNUL=%d, Band=%d', earfcndl, earfcnul, band)
def read_msg(self, message: Any) -> AcsReadMsgResult: """ Process GetParameterValuesResponse """ if not isinstance(message, models.GetParameterValuesResponse): return AcsReadMsgResult(msg_handled=False, next_state=None) path_to_val = {} for param_value_struct in message.ParameterList.ParameterValueStruct: path_to_val[param_value_struct.Name] = \ param_value_struct.Value.Data EnodebdLogger.debug('Received object parameters: %s', str(path_to_val)) # Parse simple params param_name_list = self.acs.data_model.get_parameter_names() for name in param_name_list: path = self.acs.data_model.get_parameter(name).path if path in path_to_val: value = path_to_val.get(path) magma_val = \ self.acs.data_model.transform_for_magma( name, value, ) self.acs.device_cfg.set_parameter(name, magma_val) # Parse object params num_plmns = self.acs.data_model.get_num_plmns() for i in range(1, num_plmns + 1): obj_name = ParameterName.PLMN_N % i obj_to_params = self.acs.data_model.get_numbered_param_names() param_name_list = obj_to_params[obj_name] for name in param_name_list: path = self.acs.data_model.get_parameter(name).path if path in path_to_val: value = path_to_val.get(path) if value is None: continue if obj_name not in self.acs.device_cfg.get_object_names(): self.acs.device_cfg.add_object(obj_name) magma_value = \ self.acs.data_model.transform_for_magma(name, value) self.acs.device_cfg.set_parameter_for_object( name, magma_value, obj_name, ) # Now we have enough information to build the desired configuration if self.acs.desired_cfg is None: self.acs.desired_cfg = build_desired_config( self.acs.mconfig, self.acs.service_config, self.acs.device_cfg, self.acs.data_model, self.acs.config_postprocessor, ) if len( get_all_objects_to_delete( self.acs.desired_cfg, self.acs.device_cfg, ), ) > 0: return AcsReadMsgResult( msg_handled=True, next_state=self.rm_obj_transition, ) elif len( get_all_objects_to_add( self.acs.desired_cfg, self.acs.device_cfg, ), ) > 0: return AcsReadMsgResult( msg_handled=True, next_state=self.add_obj_transition, ) elif len( get_all_param_values_to_set( self.acs.desired_cfg, self.acs.device_cfg, self.acs.data_model, ), ) > 0: return AcsReadMsgResult( msg_handled=True, next_state=self.set_params_transition, ) return AcsReadMsgResult( msg_handled=True, next_state=self.skip_transition, )
def transition(self, next_state: str) -> Any: logger.debug('State transition to <%s>', next_state) self.state.exit() self.state = self.state_map[next_state] self.state.enter()
def log_message(self, format, *args): """ Overwrite message logging to use python logging framework rather than stderr """ logger.debug("%s - %s", self.client_address[0], format % args)