예제 #1
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)
예제 #2
0
    def test_frequency_related_params_removed_in_postprocessor(self):
        acs_state_machine = provision_clean_sm()
        acs_state_machine.device_cfg.set_parameter(ParameterName.IP_SEC_ENABLE,
                                                   'false')

        parameters_to_delete = [
            ParameterName.RADIO_ENABLE,
            ParameterName.POWER_SPECTRAL_DENSITY,
            ParameterName.EARFCNDL,
            ParameterName.EARFCNUL,
            ParameterName.BAND,
            ParameterName.DL_BANDWIDTH,
            ParameterName.UL_BANDWIDTH,
            ParameterName.SAS_RADIO_ENABLE,
        ]
        for p in parameters_to_delete:
            acs_state_machine.device_cfg.set_parameter(p, 'some_value')

        desired_cfg = build_desired_config(
            acs_state_machine.mconfig,
            acs_state_machine.service_config,
            acs_state_machine.device_cfg,
            acs_state_machine.data_model,
            acs_state_machine.config_postprocessor,
        )
        for p in parameters_to_delete:
            self.assertFalse(desired_cfg.has_parameter(p))
예제 #3
0
 def _prepare_desired_cfg_for_sm(sm):
     return build_desired_config(
         sm.mconfig,
         sm.service_config,
         sm.device_cfg,
         sm.data_model,
         sm.config_postprocessor,
     )
예제 #4
0
    def test_transition_depending_on_sas_enabled_flag(
        self,
        dp_mode,
        expected_state,
        mock_get_state,
    ):
        """Testing if SM steps in and out of FreedomFiOneWaitNotifyDPState as per state map depending on whether
        sas_enabled param is set to True or False in the service config

        Args:
            dp_mode: bool flag to enable or disable dp mode
            expected_state (Any): State
            mock_get_state (Any): mocking get_cbsd_state method
        """

        mock_get_state.return_value = MOCK_CBSD_STATE

        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.FREEDOMFI_ONE)
        acs_state_machine._service.config = _get_service_config(
            dp_mode=dp_mode)
        acs_state_machine.desired_cfg = build_desired_config(
            acs_state_machine.mconfig,
            acs_state_machine.service_config,
            acs_state_machine.device_cfg,
            acs_state_machine.data_model,
            acs_state_machine.config_postprocessor,
        )

        # Need to fill these values in the device_cfg if we're going to transition to notify_dp state
        acs_state_machine.device_cfg.set_parameter(SASParameters.SAS_USER_ID,
                                                   'test_user')
        acs_state_machine.device_cfg.set_parameter(SASParameters.SAS_FCC_ID,
                                                   'test_fcc')
        acs_state_machine.device_cfg.set_parameter(ParameterName.SERIAL_NUMBER,
                                                   'test_sn')
        acs_state_machine.transition('check_wait_get_params')

        msg = Tr069MessageBuilder.param_values_qrtb_response(
            [], models.GetParameterValuesResponse)

        # SM should transition from check_wait_get_params to end_session -> notify_dp automatically
        # upon receiving response from the radio
        acs_state_machine.handle_tr069_message(msg)

        self.assertIsInstance(acs_state_machine.state, expected_state)

        msg = Tr069MessageBuilder.get_inform(event_codes=['1 BOOT'])

        # SM should go into wait_inform state, respond with Inform response and transition to FreedomFiOneGetInitState
        acs_state_machine.handle_tr069_message(msg)

        self.assertIsInstance(acs_state_machine.state,
                              FreedomFiOneGetInitState)
예제 #5
0
    def read_msg(self, message: Any) -> AcsReadMsgResult:
        """ Process GetParameterValuesResponse """
        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
        logging.debug('Received object parameters: %s', str(path_to_val))

        # TODO: This might a string for some strange reason, investigate why
        # Get the names of parameters belonging to numbered objects
        num_plmns = \
            int(self.acs.device_cfg.get_parameter(ParameterName.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
                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)

        # 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)
예제 #6
0
    def test_sas_enable_mode_is_enabled(self):
        acs_state_machine = provision_clean_sm()
        acs_state_machine.device_cfg.set_parameter(ParameterName.IP_SEC_ENABLE,
                                                   'false')

        acs_state_machine.desired_cfg = build_desired_config(
            acs_state_machine.mconfig,
            acs_state_machine.service_config,
            acs_state_machine.device_cfg,
            acs_state_machine.data_model,
            acs_state_machine.config_postprocessor,
        )

        self.assertEqual(
            1,
            acs_state_machine.desired_cfg.get_parameter(
                ParameterName.SAS_ENABLED))
예제 #7
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)
예제 #8
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,
        )
예제 #9
0
    def test_provision(self, mock_get_state) -> None:
        """
        Test the basic provisioning workflow
        1 - enodeb sends Inform, enodebd sends InformResponse
        2 - enodeb sends empty HTTP message,
        3 - enodebd sends get transient params, updates the device state.
        4 - enodebd sends get param values, updates the device state
        5 - enodebd, sets fields including SAS fields.

        Args:
            mock_get_state (Any): mocking get_cbsd_state method
        """

        mock_get_state.return_value = MOCK_CBSD_STATE

        logging.root.level = logging.DEBUG
        acs_state_machine = EnodebAcsStateMachineBuilder.build_acs_state_machine(
            EnodebDeviceName.FREEDOMFI_ONE)
        acs_state_machine._service.config = _get_service_config()
        acs_state_machine.desired_cfg = build_desired_config(
            acs_state_machine.mconfig,
            acs_state_machine.service_config,
            acs_state_machine.device_cfg,
            acs_state_machine.data_model,
            acs_state_machine.config_postprocessor,
        )

        inform = Tr069MessageBuilder.get_inform(
            oui="000E8F",
            sw_version="TEST3920@210901",
            enb_serial="2006CW5000023",
        )
        resp = acs_state_machine.handle_tr069_message(inform)
        self.assertTrue(
            isinstance(resp, models.InformResponse),
            'Should respond with an InformResponse',
        )

        # Send an empty http request
        req = models.DummyInput()
        resp = acs_state_machine.handle_tr069_message(req)

        # Expect a request for read-only params
        self.assertTrue(
            isinstance(resp, models.GetParameterValues),
            'State machine should be requesting param values',
        )
        for tr69nodes in StatusParameters.STATUS_PARAMETERS.values():
            self.assertIn(tr69nodes.path, resp.ParameterNames.string)

        req = self._get_ff_one_read_only_param_values_resp()
        get_resp = acs_state_machine.handle_tr069_message(req)

        self.assertTrue(
            isinstance(get_resp, models.GetParameterValues),
            'State machine should be requesting param values',
        )
        req = self._get_freedomfi_one_param_values_response()
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.SetParameterValues),
            'State machine should be setting parameters',
        )
        self.assertIsNotNone(
            resp.ParameterKey.Data,
            'ParameterKey should be set for FreedomFiOne eNB',
        )

        msg = models.SetParameterValuesResponse()
        msg.Status = 1
        get_resp = acs_state_machine.handle_tr069_message(msg)
        self.assertTrue(
            isinstance(get_resp, models.GetParameterValues),
            'We should read back all parameters',
        )

        req = self._get_freedomfi_one_param_values_response()
        resp = acs_state_machine.handle_tr069_message(req)
        self.assertTrue(
            isinstance(resp, models.DummyInput),
            'Provisioning completed with Dummy response',
        )
예제 #10
0
    def test_device_and_desired_config_discrepancy_after_initial_configuration(
            self):
        """
        Testing a situation where device_cfg and desired_cfg are already present on the state machine,
        because the initial configuration of the radio has occurred, but then the configs have diverged
        (e.g. as a result of domain-proxy setting different values on the desired config)
        """
        # Skipping previous states
        acs_state_machine = provision_clean_sm('wait_get_transient_params')

        # Need to set this param on the device_cfg first, otherwise we won't be able to generate the desired_cfg
        # using 'build_desired_config' function
        acs_state_machine.device_cfg.set_parameter(ParameterName.IP_SEC_ENABLE,
                                                   'false')

        acs_state_machine.desired_cfg = build_desired_config(
            acs_state_machine.mconfig,
            acs_state_machine.service_config,
            acs_state_machine.device_cfg,
            acs_state_machine.data_model,
            acs_state_machine.config_postprocessor,
        )

        prepare_device_cfg_same_as_desired_cfg(acs_state_machine)

        # Let's say that while in 'wait_for_dp' state, the DP asked us to change this param's value in the desired_cfg
        acs_state_machine.desired_cfg.set_parameter(ParameterName.EARFCNDL, 5)

        req = Tr069MessageBuilder.param_values_qrtb_response(
            GET_TRANSIENT_PARAMS_RESPONSE_PARAMS,
            models.GetParameterValuesResponse,
        )

        # ACS asking for all params from data model
        acs_state_machine.handle_tr069_message(req)

        req = Tr069MessageBuilder.param_values_qrtb_response(
            GET_PARAMS_RESPONSE_PARAMS,
            models.GetParameterValuesResponse,
        )

        # ACS asking for object params
        acs_state_machine.handle_tr069_message(req)
        req = Tr069MessageBuilder.get_object_param_values_response(
            cell_reserved_for_operator_use='true',
            enable='true',
            is_primary='true',
            plmnid='00101',
        )

        # ACS should ask the radio to correct the only parameter that doesn't match the desired config - EARFCNDL
        resp = acs_state_machine.handle_tr069_message(req)

        self.assertIsInstance(resp, models.SetParameterValues)
        self.assertEqual(1, len(resp.ParameterList.ParameterValueStruct))
        self.assertEqual(
            'Device.Services.FAPService.1.CellConfig.LTE.RAN.RF.EARFCNDL',
            resp.ParameterList.ParameterValueStruct[0].Name,
        )
        self.assertEqual('5',
                         resp.ParameterList.ParameterValueStruct[0].Value.Data)