Exemplo n.º 1
0
 def read_msg(self, message: Any) -> AcsReadMsgResult:
     if type(message) == models.SetParameterValuesResponse:
         if not self.status_non_zero_allowed:
             if message.Status != 0:
                 raise Tr069Error(
                     'Received SetParameterValuesResponse with '
                     'Status=%d' % message.Status, )
         self._mark_as_configured()
         if not self.acs.are_invasive_changes_applied:
             return AcsReadMsgResult(True, self.apply_invasive_transition)
         return AcsReadMsgResult(True, self.done_transition)
     elif type(message) == models.Fault:
         logger.error(
             'Received Fault in response to SetParameterValues, '
             'Code (%s), Message (%s)',
             message.FaultCode,
             message.FaultString,
         )
         if message.SetParameterValuesFault is not None:
             for fault in message.SetParameterValuesFault:
                 logger.error(
                     'SetParameterValuesFault Param: %s, '
                     'Code: %s, String: %s',
                     fault.ParameterName,
                     fault.FaultCode,
                     fault.FaultString,
                 )
     return AcsReadMsgResult(False, None)
Exemplo n.º 2
0
async def check_and_apply_iptables_rules(
    port: str,
    enodebd_public_ip: str,
    enodebd_ip: str,
) -> None:
    command = 'sudo iptables -t nat -L'
    output = subprocess.run(command,
                            shell=True,
                            stdout=subprocess.PIPE,
                            check=True)
    command_output = output.stdout.decode('utf-8').strip()
    prerouting_rules = _get_prerouting_rules(command_output)
    if not prerouting_rules:
        logger.info('Configuring Iptables rule')
        await run(
            get_iptables_rule(
                port,
                enodebd_public_ip,
                enodebd_ip,
                add=True,
            ), )
    else:
        # Checks each rule in PREROUTING Chain
        expected_rules_present = check_rules(prerouting_rules, port,
                                             enodebd_public_ip, enodebd_ip)
        if not expected_rules_present:
            logger.info('Configuring Iptables rule')
            await run(
                get_iptables_rule(
                    port,
                    enodebd_public_ip,
                    enodebd_ip,
                    add=True,
                ), )
Exemplo n.º 3
0
def get_all_enb_state(
        print_grpc_payload: bool = False) -> Optional[Dict[int, int]]:
    """
    Make RPC call to 'GetENBState' method of s1ap service
    """
    try:
        chan = ServiceRegistry.get_rpc_channel(
            S1AP_SERVICE_NAME,
            ServiceRegistry.LOCAL,
        )
    except ValueError:
        logger.error('Cant get RPC channel to %s', S1AP_SERVICE_NAME)
        return {}
    client = S1apServiceStub(chan)
    try:
        request = Void()
        print_grpc(
            request,
            print_grpc_payload,
            "Get All eNB State Request:",
        )
        res = client.GetENBState(request, DEFAULT_GRPC_TIMEOUT)
        print_grpc(
            res,
            print_grpc_payload,
            "Get All eNB State Response:",
        )
        return res.enb_state_map
    except grpc.RpcError as err:
        logger.warning(
            "GetEnbState error: [%s] %s",
            err.code(),
            err.details(),
        )
    return {}
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 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.warning('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.º 6
0
    def decompose_incoming_envelope(self, ctx, message=XmlDocument.REQUEST):
        """
        For TR-069, the SOAP fault message (CPE->ACS) contains useful
        information, and should not result in another fault response (ACS->CPE).
        Strip the outer SOAP fault structure, so that the CWMP fault structure
        is treated as a normal RPC call (to the 'Fault' function).
        """
        super(Tr069Soap11, self).decompose_incoming_envelope(ctx, message)

        if ctx.in_body_doc.tag == '{%s}Fault' % self.ns_soap_env:
            faultstring = ctx.in_body_doc.findtext('faultstring')
            if not faultstring or 'CWMP fault' not in faultstring:
                # Not a CWMP fault
                return

            # Strip SOAP fault structure, leaving inner CWMP fault structure
            detail_elem = ctx.in_body_doc.find('detail')
            if detail_elem is not None:
                detail_children = list(detail_elem)
                if len(detail_children):
                    if len(detail_children) > 1:
                        logger.warning("Multiple detail elements found in SOAP"
                                       " fault - using first one")
                    ctx.in_body_doc = detail_children[0]
                    ctx.method_request_string = ctx.in_body_doc.tag
                    self.validate_body(ctx, message)
Exemplo n.º 7
0
    def handle_tr069_message(
        self,
        ctx: WsgiMethodContext,
        tr069_message: ComplexModelBase,
    ) -> Any:
        """ Delegate message handling to the appropriate eNB state machine """
        client_ip = self._get_client_ip(ctx)
        if isinstance(tr069_message, models.Inform):
            try:
                self._update_device_mapping(client_ip, tr069_message)
            except UnrecognizedEnodebError as err:
                logger.warning(
                    'Received TR-069 Inform message from an '
                    'unrecognized device. '
                    'Ending TR-069 session with empty HTTP '
                    'response. Error: (%s)', err)
                return models.DummyInput()

        handler = self._get_handler(client_ip)
        if handler is None:
            logger.warning('Received non-Inform TR-069 message from unknown '
                           'eNB. Ending session with empty HTTP response.')
            return models.DummyInput()

        return handler.handle_tr069_message(tr069_message)
Exemplo n.º 8
0
 def _assert_param_in_model(self, param_name: ParameterName) -> None:
     trparam_model = self.data_model
     tr_param = trparam_model.get_parameter(param_name)
     if tr_param is None:
         logger.warning('Parameter <%s> not defined in model', param_name)
         raise ConfigurationError(
             f"Parameter not defined in model: {param_name}")
Exemplo n.º 9
0
async def set_enodebd_iptables_rule():
    """
    Remove & Set iptable rules for exposing public IP
    for enobeb instead of private IP..
    """
    # Remove & Set iptable rules for exposing public ip
    # for enobeb instead of private
    cfg = load_service_config('enodebd')
    port, interface = cfg['tr069']['port'], cfg['tr069']['interface']
    enodebd_public_ip = cfg['tr069']['public_ip']
    # IPv4 only as iptables only works for IPv4. TODO: Investigate ip6tables?
    enodebd_ip = get_ip_from_if(interface, preference=IpPreference.IPV4_ONLY)
    # Incoming data from 192.88.99.142 -> enodebd address (eg 192.168.60.142)
    enodebd_netmask = get_if_ip_with_netmask(
        interface,
        preference=IpPreference.IPV4_ONLY,
    )[1]
    verify_config = does_iface_config_match_expected(
        enodebd_ip,
        enodebd_netmask,
    )
    if not verify_config:
        logger.warning(
            'The IP address of the %s interface is %s. The '
            'expected IP addresses are %s', interface, enodebd_ip,
            str(EXPECTED_IP4))
    await check_and_apply_iptables_rules(
        port,
        enodebd_public_ip,
        enodebd_ip,
    )
Exemplo n.º 10
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.º 11
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.º 12
0
 def enter(self):
     self.rem_timer = StateMachineTimer(self.CONFIG_DELAY_AFTER_BOOT)
     logger.info(
         'Holding off of eNB configuration for %s seconds. '
         'Will resume after eNB REM process has finished. ',
         self.CONFIG_DELAY_AFTER_BOOT,
     )
Exemplo n.º 13
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.º 14
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.º 15
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.º 16
0
def main():
    """
    Top-level function for enodebd
    """
    service = MagmaService('enodebd', mconfigs_pb2.EnodebD())
    logger.init()

    # Optionally pipe errors to Sentry
    sentry_init(service_name=service.name,
                sentry_mconfig=service.shared_mconfig.sentry_config)

    # State machine manager for tracking multiple connected eNB devices.
    state_machine_manager = StateMachineManager(service)

    # Statistics manager
    stats_mgr = StatsManager(state_machine_manager)
    stats_mgr.run()

    # Start TR-069 thread
    server_thread = Thread(
        target=tr069_server,
        args=(state_machine_manager, ),
        daemon=True,
    )
    server_thread.start()

    print_grpc_payload = service.config.get('print_grpc_payload', False)

    # Add all servicers to the server
    enodebd_servicer = EnodebdRpcServicer(
        state_machine_manager,
        print_grpc_payload,
    )
    enodebd_servicer.add_to_server(service.rpc_server)

    # Register function to get service status
    def get_enodebd_status():
        return get_service_status_old(state_machine_manager)

    service.register_get_status_callback(get_enodebd_status)

    # Register a callback function for GetOperationalStates service303 function
    def get_enodeb_operational_states() -> List[State]:
        return get_operational_states(
            state_machine_manager,
            service.mconfig,
            print_grpc_payload,
        )

    service.register_operational_states_callback(get_enodeb_operational_states)

    # Set eNodeBD iptables rules due to exposing public IP to eNodeB
    service.loop.create_task(set_enodebd_iptables_rule())

    # Run the service loop
    service.run()

    # Cleanup the service
    service.close()
Exemplo n.º 17
0
 def _clear_stats(self) -> None:
     """
     Clear statistics. Called when eNodeB management plane disconnects
     """
     logger.info('Clearing performance counter statistics')
     # Set all metrics to 0 if eNodeB not connected
     for metric in self.PM_FILE_TO_METRIC_MAP.values():
         metric.set(0)
Exemplo n.º 18
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.º 19
0
    def postprocess(
        self,
        mconfig: Any,
        service_cfg: Any,
        desired_cfg: EnodebConfiguration,
    ) -> None:
        # TODO: Get this config from the domain proxy
        # TODO @amarpad, set these when DProxy integration is done.
        # For now the radio will directly talk to the SAS and get these
        # attributes.
        desired_cfg.delete_parameter(ParameterName.EARFCNDL)
        desired_cfg.delete_parameter(ParameterName.DL_BANDWIDTH)
        desired_cfg.delete_parameter(ParameterName.UL_BANDWIDTH)

        # go through misc parameters and set them to default.
        for name, val in FreedomFiOneMiscParameters.defaults.items():
            desired_cfg.set_parameter(name, val)

        # Bump up the parameter key version
        self.acs.parameter_version_inc()

        # Workaround a bug in Sercomm firmware in release 3920, 3921
        # where the meaning of CellReservedForOperatorUse is wrong.
        # Set to True to ensure the PLMN is not reserved
        num_plmns = self.acs.data_model.get_num_plmns()
        for i in range(1, num_plmns + 1):
            object_name = ParameterName.PLMN_N % i
            desired_cfg.set_parameter_for_object(
                param_name=ParameterName.PLMN_N_CELL_RESERVED % i,
                value=True,
                object_name=object_name,
            )

        if self.WEB_UI_ENABLE_LIST_KEY in service_cfg:
            serial_nos = service_cfg.get(self.WEB_UI_ENABLE_LIST_KEY)
            if self.acs.device_cfg.has_parameter(
                    ParameterName.SERIAL_NUMBER, ):
                if self.acs.get_parameter(ParameterName.SERIAL_NUMBER) in \
                        serial_nos:
                    desired_cfg.set_parameter(
                        FreedomFiOneMiscParameters.WEB_UI_ENABLE,
                        True,
                    )
            else:
                # This should not happen
                EnodebdLogger.error("Serial number unknown for device")

        if self.SAS_KEY not in service_cfg:
            return

        sas_cfg = service_cfg[self.SAS_KEY]
        sas_param_names = self.acs.data_model.get_sas_param_names()
        for name, val in sas_cfg.items():
            if name not in sas_param_names:
                EnodebdLogger.warning("Ignoring attribute %s", name)
                continue
            desired_cfg.set_parameter(name, val)
Exemplo n.º 20
0
 def get_msg(self, message: Any) -> AcsMsgAndTransition:
     if self.prev_msg_was_inform:
         response = models.InformResponse()
         # Set maxEnvelopes to 1, as per TR-069 spec
         response.MaxEnvelopes = 1
         return AcsMsgAndTransition(response, None)
     logger.info('Sending reboot request to eNB')
     request = models.Reboot()
     request.CommandKey = ''
     return AcsMsgAndTransition(request, self.done_transition)
Exemplo n.º 21
0
 def _clear_stats(self) -> None:
     """
     Clear statistics. Called when eNodeB management plane disconnects
     """
     logger.info('Clearing performance counter statistics')
     # Set all metrics to 0 if eNodeB not connected
     for pm_name, metric in self.PM_FILE_TO_METRIC_MAP:
         # eNB data usage metrics will not be cleared
         if pm_name not in ('PDCP.UpOctUl', 'PDCP.UpOctDl'):
             metric.set(0)
Exemplo n.º 22
0
 def get_msg(self) -> AcsMsgAndTransition:
     if self.prev_msg_was_inform:
         response = models.InformResponse()
         # Set maxEnvelopes to 1, as per TR-069 spec
         response.MaxEnvelopes = 1
         return AcsMsgAndTransition(response, None)
     logger.info('Sending reboot request to eNB')
     request = models.Reboot()
     request.CommandKey = ''
     self.acs.are_invasive_changes_applied = True
     return AcsMsgAndTransition(request, self.done_transition)
Exemplo n.º 23
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.º 24
0
async def run(cmd):
    """Fork shell and run command NOTE: Popen is non-blocking"""
    cmd = shlex.split(cmd)
    proc = await asyncio.create_subprocess_shell(" ".join(cmd))
    await proc.communicate()
    if proc.returncode != 0:
        # This can happen because the NAT prerouting rule didn't exist
        logger.error(
            'Possible error running async subprocess: %s exited with '
            'return code [%d].', cmd, proc.returncode)
    return proc.returncode
Exemplo n.º 25
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.º 26
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.º 27
0
 def get_metric_value(enodeb_status: Dict[str, str], key: str):
     # Metrics are "sticky" when synced to the cloud - if we don't
     # receive a status update from enodeb, set the metric to 0
     # to explicitly indicate that it was not received, otherwise the
     # metrics collector will continue to report the last value
     val = enodeb_status.get(key, None)
     if val is None:
         return 0
     if type(val) is not bool:
         logger.error('Could not cast metric value %s to int', val)
         return 0
     return int(val)  # val should be either True or False
Exemplo n.º 28
0
def _read_gps_coords_from_file():
    try:
        with open(CACHED_GPS_COORD_FILE_PATH) as f:
            lines = f.readlines()
            if len(lines) != 2:
                logger.warning(
                    'Expected to find 2 lines in GPS '
                    'coordinate file but only found %d', len(lines))
                return '0', '0'
            return tuple(map(lambda l: l.strip(), lines))
    except OSError:
        logger.warning('Could not open cached GPS coordinate file')
        return '0', '0'
Exemplo n.º 29
0
def _format_as_bool(
    param_value: Union[bool, str, int],
    param_name: Optional[Union[ParameterName, str]] = None,
) -> bool:
    """ Returns '1' for true, and '0' for false """
    stripped_value = str(param_value).lower().strip()
    if stripped_value in {'true', '1'}:
        return True
    elif stripped_value in {'false', '0'}:
        return False
    else:
        logger.warning('%s parameter not understood (%s)', param_name,
                       param_value)
        return False
Exemplo n.º 30
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