def setUp(self): super().setUp() self.dp_service = DPService(SessionManager(self.engine), self._now) DBInitializer(SessionManager(self.engine)).initialize() self.cbsd_states = { x.name: x.id for x in self.session.query(DBCbsdState).all() } self.grant_states = { x.name: x.id for x in self.session.query(DBGrantState).all() }
def run(): """ Top-level function for radio controller """ logger.info("Starting grpc server") config = get_config() scheduler = BackgroundScheduler() metricsd_client = get_metricsd_client() scheduler.add_job( process_metrics, args=[metricsd_client, config.SERVICE_HOSTNAME, "radio_controller"], trigger=IntervalTrigger( seconds=config.METRICS_PROCESSING_INTERVAL_SEC, ), max_instances=1, name="metrics_processing_job", ) scheduler.start() logger.info(f"grpc port is: {config.GRPC_PORT}") db_engine = create_engine( url=config.SQLALCHEMY_DB_URI, encoding=config.SQLALCHEMY_DB_ENCODING, echo=config.SQLALCHEMY_ECHO, future=config.SQLALCHEMY_FUTURE, pool_size=config.SQLALCHEMY_ENGINE_POOL_SIZE, max_overflow=config.SQLALCHEMY_ENGINE_MAX_OVERFLOW, ) session_manager = SessionManager(db_engine) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) add_RadioControllerServicer_to_server( RadioControllerService(session_manager=session_manager), server, ) add_ActiveModeControllerServicer_to_server( ActiveModeControllerService(session_manager=session_manager), server, ) add_DPServiceServicer_to_server( DPService( session_manager=session_manager, now_func=datetime.now, fluentd_client=FluentdClient(), ), server, ) server.add_insecure_port(f"[::]:{config.GRPC_PORT}") server.start() logger.info(f"GRPC Server started on port {config.GRPC_PORT}") def handle_sigterm(*_): logger.info("Received shutdown signal") all_rpcs_done_event = server.stop(30) all_rpcs_done_event.wait(30) logger.info("Shut down gracefully") signal(SIGTERM, handle_sigterm) server.wait_for_termination()
def run(): """ Top-level function for radio controller """ logger.info("Starting grpc server") config = get_config() logger.info(f"grpc port is: {config.GRPC_PORT}") db_engine = create_engine( url=config.SQLALCHEMY_DB_URI, encoding=config.SQLALCHEMY_DB_ENCODING, echo=config.SQLALCHEMY_ECHO, future=config.SQLALCHEMY_FUTURE, pool_size=config.SQLALCHEMY_ENGINE_POOL_SIZE, max_overflow=config.SQLALCHEMY_ENGINE_MAX_OVERFLOW, ) session_manager = SessionManager(db_engine) server = grpc.server(futures.ThreadPoolExecutor(max_workers=10)) add_RadioControllerServicer_to_server( RadioControllerService(session_manager=session_manager), server, ) add_ActiveModeControllerServicer_to_server( ActiveModeControllerService(session_manager=session_manager), server, ) add_DPServiceServicer_to_server( DPService( session_manager=session_manager, now_func=datetime.now, fluentd_client=FluentdClient(), ), server, ) server.add_insecure_port(f"[::]:{config.GRPC_PORT}") server.start() logger.info(f"GRPC Server started on port {config.GRPC_PORT}") def handle_sigterm(*_): logger.info("Received shutdown signal") all_rpcs_done_event = server.stop(30) all_rpcs_done_event.wait(30) logger.info("Shut down gracefully") signal(SIGTERM, handle_sigterm) server.wait_for_termination()
class DPTestCase(LocalDBTestCase): def setUp(self): super().setUp() self.dp_service = DPService(SessionManager(self.engine), self._now) DBInitializer(SessionManager(self.engine)).initialize() self.cbsd_states = { x.name: x.id for x in self.session.query(DBCbsdState).all() } self.grant_states = { x.name: x.id for x in self.session.query(DBGrantState).all() } def test_cbsd_registered_and_enabled_active_mode(self): request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) self._then_exactly_one_cbsd_is_active(request) def test_cbsd_register_when_already_registered(self): cbsd = self._build_cbsd(**test_cbsd_dict) self.session.add(cbsd) self.session.commit() request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) self._then_exactly_one_cbsd_is_active(request) def test_cbsd_register_updates_active_mode_config_if_desired_state_is_unregistered( self): cbsd = self._build_cbsd(**test_cbsd_dict) active_mode_config = DBActiveModeConfig( cbsd=cbsd, desired_state_id=self.cbsd_states[CbsdStates.UNREGISTERED.value], ) self.session.add_all([cbsd, active_mode_config]) self.session.commit() request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) self.assertEqual(1, self._get_active_cbsd_count(request)) def test_get_state_for_unknown_cbsd(self): request = self._build_request(**test_cbsd_dict) result = self.dp_service.GetCBSDState(request, None) self.assertEqual(self._build_empty_result(), result) def test_get_state_with_valid_authorized_grant(self): request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) cbsd = self.session.query(DBCbsd).filter( DBCbsd.cbsd_serial_number == request.serial_number, ).first() channel = self._build_channel(cbsd) grant = self._build_grant( cbsd, self.grant_states[GrantStates.AUTHORIZED.value], channel, ) grant.transmit_expire_time = datetime.now() + timedelta(seconds=60) grant.grant_expire_time = datetime.now() + timedelta(days=7) self.session.add_all([cbsd, channel, grant]) self.session.commit() request = self._build_request(**test_cbsd_dict) result = self.dp_service.GetCBSDState(request, None) self.assertEqual(self._build_expected_result(channel), result) def test_get_state_with_transmit_expired_authorized_grant(self): request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) cbsd = self.session.query(DBCbsd).filter( DBCbsd.cbsd_serial_number == request.serial_number, ).first() channel = self._build_channel(cbsd) grant = self._build_grant( cbsd, self.grant_states[GrantStates.AUTHORIZED.value], channel, ) grant.transmit_expire_time = datetime.now() - timedelta(seconds=1) grant.grant_expire_time = datetime.now() + timedelta(days=7) self.session.add_all([cbsd, channel, grant]) self.session.commit() request = self._build_request() result = self.dp_service.GetCBSDState(request, None) self.assertEqual(self._build_empty_result(), result) def test_get_state_with_grant_expired_authorized_grant(self): request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) cbsd = self.session.query(DBCbsd).filter( DBCbsd.cbsd_serial_number == request.serial_number, ).first() channel = self._build_channel(cbsd) grant = self._build_grant( cbsd, self.grant_states[GrantStates.AUTHORIZED.value], channel, ) grant.transmit_expire_time = datetime.now() - timedelta(seconds=1) grant.grant_expire_time = datetime.now() - timedelta(seconds=1) self.session.add_all([cbsd, channel, grant]) self.session.commit() request = self._build_request() result = self.dp_service.GetCBSDState(request, None) self.assertEqual(self._build_empty_result(), result) def test_get_state_with_unauthorized_grant(self): request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) cbsd = self.session.query(DBCbsd).filter( DBCbsd.cbsd_serial_number == request.serial_number, ).first() channel = self._build_channel(cbsd) grant = self._build_grant( cbsd, self.grant_states[GrantStates.IDLE.value], channel, ) self.session.add_all([cbsd, channel, grant]) self.session.commit() request = self._build_request() result = self.dp_service.GetCBSDState(request, None) self.assertEqual(self._build_empty_result(), result) def test_get_state_without_channel(self): request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) cbsd = self.session.query(DBCbsd).filter( DBCbsd.cbsd_serial_number == request.serial_number, ).first() grant = self._build_grant( cbsd, self.grant_states[GrantStates.AUTHORIZED.value], ) self.session.add_all([cbsd, grant]) self.session.commit() request = self._build_request() result = self.dp_service.GetCBSDState(request, None) self.assertEqual(self._build_empty_result(), result) def test_update_last_seen_on_request(self): request = self._build_request(**test_cbsd_dict) self.dp_service.CBSDRegister(request, None) self.dp_service.GetCBSDState(request, None) self.assertEqual( SOME_TIMESTAMP, self._get_last_seen_timestamp(request), ) @staticmethod def _now() -> datetime: return datetime.fromtimestamp(SOME_TIMESTAMP) @staticmethod def _build_request(**kwargs) -> CBSDRequest: return CBSDRequest(**kwargs) def _build_cbsd(self, serial_number, **kwargs) -> DBCbsd: return DBCbsd( cbsd_serial_number=serial_number, state_id=self.cbsd_states[CbsdStates.UNREGISTERED.value], ) @staticmethod def _build_channel(cbsd: DBCbsd) -> DBChannel: return DBChannel( cbsd=cbsd, channel_type="some_channel_type", rule_applied="some_rule", low_frequency=3550_000_000, high_frequency=3570_000_000, last_used_max_eirp=20, ) @staticmethod def _build_grant(cbsd: DBCbsd, state_id: str, channel: DBChannel = None) -> DBGrant: return DBGrant( cbsd=cbsd, channel=channel, grant_id="some_grant_id", state_id=state_id, ) def _then_exactly_one_cbsd_is_active(self, request: CBSDRequest): self.assertEqual(1, self._get_active_cbsd_count(request)) self.assertEqual( 1, self._get_cbsd_with_serial_count(request.serial_number), ) def _get_cbsd_with_serial_count(self, serial_number: str) -> int: return self.session.query(DBCbsd).\ filter(DBCbsd.cbsd_serial_number == serial_number).count() def _get_active_cbsd_count(self, request: CBSDRequest) -> int: return self._query_active_cbsd(request).count() def _get_last_seen_timestamp(self, request: CBSDRequest) -> int: return self._query_active_cbsd( request).first().cbsd.last_seen.timestamp() def _query_active_cbsd(self, request: CBSDRequest): return self.session.query(DBActiveModeConfig).join(DBCbsd). \ filter(*self._build_expected_filter_from_request(request)) def _build_expected_filter_from_request(self, request: CBSDRequest) -> List[Any]: return [ DBCbsd.cbsd_serial_number == request.serial_number, DBCbsd.state_id == self.cbsd_states[CbsdStates.UNREGISTERED.value], DBActiveModeConfig.desired_state_id == self.cbsd_states[ CbsdStates.REGISTERED.value], ] @staticmethod def _build_expected_result(channel: DBChannel) -> CBSDStateResult: return CBSDStateResult( radio_enabled=True, channel=LteChannel( low_frequency_hz=channel.low_frequency, high_frequency_hz=channel.high_frequency, max_eirp_dbm_mhz=channel.last_used_max_eirp, ), ) @staticmethod def _build_empty_result() -> CBSDStateResult: return CBSDStateResult(radio_enabled=False)