Exemplo n.º 1
0
    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)
Exemplo n.º 2
0
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))
Exemplo n.º 3
0
    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)
Exemplo n.º 4
0
    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!')
Exemplo n.º 5
0
    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)
Exemplo n.º 6
0
    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)
Exemplo n.º 7
0
    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,
        )
Exemplo n.º 8
0
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
Exemplo n.º 9
0
 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()
Exemplo n.º 10
0
 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)
Exemplo n.º 11
0
    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
Exemplo n.º 12
0
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
Exemplo n.º 13
0
    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)
Exemplo n.º 14
0
 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)
Exemplo n.º 15
0
    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())
Exemplo n.º 16
0
 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')
Exemplo n.º 17
0
    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
Exemplo n.º 18
0
 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,
     )
Exemplo n.º 19
0
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
Exemplo n.º 20
0
    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,
        )
Exemplo n.º 21
0
    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."
            )
Exemplo n.º 22
0
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
Exemplo n.º 23
0
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
Exemplo n.º 24
0
    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)
Exemplo n.º 25
0
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)
Exemplo n.º 26
0
    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,
        )
Exemplo n.º 27
0
 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()
Exemplo n.º 28
0
 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)