Beispiel #1
0
def new_test_service_context(config_file_name: str = 'config.yml',
                             ml_dataset_openers: Dict[str, MultiLevelDatasetOpener] = None) -> ServiceContext:
    ctx = ServiceContext(base_dir=get_res_test_dir(), ml_dataset_openers=ml_dataset_openers)
    config_file = os.path.join(ctx.base_dir, config_file_name)
    with open(config_file, encoding='utf-8') as fp:
        ctx.config = yaml.safe_load(fp)
    return ctx
Beispiel #2
0
def new_demo_service_context(
    ml_dataset_openers: Dict[str, MultiLevelDatasetOpener] = None
) -> ServiceContext:
    ctx = ServiceContext(base_dir=get_res_demo_dir(),
                         ml_dataset_openers=ml_dataset_openers)
    config_file = os.path.join(ctx.base_dir, 'config.yml')
    with open(config_file) as fp:
        ctx.config = yaml.safe_load(fp)
    return ctx
Beispiel #3
0
    def test_get_colorbars(self):
        ctx = ServiceContext()

        response = get_color_bars(ctx, 'application/json')
        self.assertIsInstance(response, str)
        self.assertTrue(len(response) > 40)
        self.assertEqual('[\n  [\n    "Perceptually Uniform Sequenti', response[0:40])

        response = get_color_bars(ctx, 'text/html')
        self.assertIsInstance(response, str)
        self.assertTrue(len(response) > 40)
        self.assertEqual('<!DOCTYPE html>\n<html lang="en">\n<head><', response[0:40])

        with self.assertRaises(ServiceBadRequestError) as cm:
            get_color_bars(ctx, 'text/xml')
        self.assertEqual(400, cm.exception.status_code)
        self.assertEqual("Format 'text/xml' not supported for color bars", cm.exception.reason)
Beispiel #4
0
    def test_get_ne2_tile_grid(self):
        ctx = ServiceContext()
        tile_grid = get_ne2_tile_grid(ctx, 'ol4', 'http://bibo')
        self.assertEqual({
            'url': self.base_url + '/ne2/tiles/{z}/{x}/{y}.jpg',
            'projection': 'EPSG:4326',
            'minZoom': 0,
            'maxZoom': 2,
            'tileGrid': {'extent': [-180.0, -90.0, 180.0, 90.0],
                         'origin': [-180.0, 90.0],
                         'resolutions': [0.703125, 0.3515625, 0.17578125],
                         'tileSize': [256, 256]},
        }, tile_grid)

        with self.assertRaises(ServiceBadRequestError) as cm:
            get_ne2_tile_grid(ctx, 'cesium', 'http://bibo')
        self.assertEqual(400, cm.exception.status_code)
        self.assertEqual("Unknown tile client 'cesium'", cm.exception.reason)
Beispiel #5
0
    def test_point_ts_perf(self):
        TEST_CUBE = 'ts_test.zarr'

        if not os.path.isdir(TEST_CUBE):
            from xcube.core.new import new_cube
            cube = new_cube(time_periods=2000, variables=dict(analysed_sst=280.4))
            cube = cube.chunk(dict(time=1, lon=90, lat=90))
            cube.to_zarr(TEST_CUBE)

        ctx = ServiceContext(
            base_dir='.',
            config=dict(
                Datasets=[
                    dict(Identifier='ts_test',
                         FileSystem='file',
                         Path=TEST_CUBE,
                         Format='zarr')
                ]
            ))

        N = 5
        import random
        import time
        time_sum = 0.0
        for i in range(N):
            lon = -180 + 360 * random.random()
            lat = -90 + 180 * random.random()

            t1 = time.perf_counter()
            result = get_time_series(ctx, 'ts_test', 'analysed_sst', dict(type='Point', coordinates=[lon, lat]))
            t2 = time.perf_counter()

            self.assertIsInstance(result, list)
            self.assertEqual(2000, len(result))

            time_delta = t2 - t1
            time_sum += time_delta
            print(f'test {i + 1} took {time_delta} seconds')

        print(f'all tests took {time_sum / N} seconds in average')
Beispiel #6
0
    def __init__(self,
                 application: Application,
                 prefix: str = None,
                 address: str = DEFAULT_ADDRESS,
                 port: int = DEFAULT_PORT,
                 cube_paths: List[str] = None,
                 styles: Dict[str, Tuple] = None,
                 config_file: Optional[str] = None,
                 base_dir: Optional[str] = None,
                 tile_cache_size: Optional[str] = DEFAULT_TILE_CACHE_SIZE,
                 tile_comp_mode: int = DEFAULT_TILE_COMP_MODE,
                 update_period: Optional[float] = DEFAULT_UPDATE_PERIOD,
                 trace_perf: bool = DEFAULT_TRACE_PERF,
                 log_file_prefix: str = DEFAULT_LOG_PREFIX,
                 log_to_stderr: bool = False,
                 aws_prof: str = None,
                 aws_env: bool = False) -> None:

        """
        Start a tile service.

        The *service_info_file*, if given, represents the service in the filesystem, similar to
        the ``/var/run/`` directory on Linux systems.

        If the service file exist and its information is compatible with the requested *port*, *address*, *caller*, then
        this function simply returns without taking any other actions.

        :param application: The Tornado web application
        :param address: the address
        :param port: the port number
        :param cube_paths: optional list of cube paths
        :param config_file: optional configuration file
        :param base_dir: optional base directory
        :param update_period: if not-None, time of idleness in seconds before service is updated
        :param log_file_prefix: Log file prefix, default is "xcube-serve.log"
        :param log_to_stderr: Whether logging should be shown on stderr
        :return: service information dictionary
        """
        if config_file and cube_paths:
            raise ValueError("config_file and cube_paths cannot be given both")
        if config_file and styles:
            raise ValueError("config_file and styles cannot be given both")
        if config_file and aws_prof:
            raise ValueError("config_file and aws_profile cannot be given both")
        if config_file and aws_env:
            raise ValueError("config_file and aws_env cannot be given both")

        global SNAP_CPD_LIST
        if config_file:
            SNAP_CPD_LIST = _get_custom_color_list(config_file)

        log_dir = os.path.dirname(log_file_prefix)
        if log_dir and not os.path.isdir(log_dir):
            os.makedirs(log_dir, exist_ok=True)

        options = tornado.options.options
        options.log_file_prefix = log_file_prefix or DEFAULT_LOG_PREFIX
        options.log_to_stderr = log_to_stderr
        enable_pretty_logging()

        tile_cache_capacity = parse_mem_size(tile_cache_size)

        config = None
        if cube_paths:
            config = new_default_config(cube_paths, styles, aws_prof=aws_prof, aws_env=aws_env)

        self.config_file = os.path.abspath(config_file) if config_file else None
        self.update_period = update_period
        self.update_timer = None
        self.config_error = None
        self.service_info = dict(port=port,
                                 address=address,
                                 started=datetime.now().isoformat(sep=' '),
                                 pid=os.getpid())

        self.context = ServiceContext(prefix=prefix,
                                      config=config,
                                      base_dir=base_dir,
                                      trace_perf=trace_perf,
                                      tile_comp_mode=tile_comp_mode,
                                      tile_cache_capacity=tile_cache_capacity)
        self._maybe_load_config()

        application.service_context = self.context
        application.time_of_last_activity = time.process_time()
        self.application = application

        # Register handlers for common termination signals
        signal.signal(signal.SIGINT, self._sig_handler)
        signal.signal(signal.SIGTERM, self._sig_handler)

        self.server = application.listen(port, address=address or 'localhost')
        # Ensure we have the same event loop in all threads
        asyncio.set_event_loop_policy(_GlobalEventLoopPolicy(asyncio.get_event_loop()))
        self._maybe_load_config()
        self._maybe_install_update_check()
        self._shutdown_requested = False