예제 #1
0
async def list_records(service_id: str,
                       table_name: str,
                       sync: bool = False,
                       ttl: int = 3600,
                       dql_options: str = "",
                       db: databases.Database = Depends(models.get_db)):
    service = await services.get_service(service_id, db)
    if service.driver:
        driver = await drivers.get_driver(service.driver)
        path = f"/table/{table_name}/record"
        if dql_options:
            try:
                json.loads(dql_options)
            except json.decoder.JSONDecodeError:
                raise errors.ServiceException(dql_options, errors.DATA_ERROR,
                                              "Value is not JSON decodable")
        return drivers.service_stack(driver,
                                     service,
                                     "get",
                                     path,
                                     data={"dql": dql_options},
                                     sync=sync,
                                     ttl=ttl)
    raise errors.ServiceException(service.id, errors.NO_DRV_ERROR,
                                  "Service has no driver assigned")
예제 #2
0
def check_api_status():
    try:
        resp = requests.get(f'{config.QUEUE_API_URL}/ping')
        if resp.status_code != 200:
            raise errors.ServiceException(config.QUEUE_API_URL,
                                          errors.QAPI_UNREACH_ERROR,
                                          "Check service or network")
    except requests.exceptions.ConnectionError:
        raise errors.ServiceException(config.QUEUE_API_URL,
                                      errors.QAPI_UNREACH_ERROR,
                                      "Check service or network")
    return True
예제 #3
0
async def get_job(job_id: str):
    try:
        resp = requests.get(f"{config.QUEUE_API_URL}/queue/{job_id}")
        if resp.status_code == 200:
            output = json.loads(resp.text)
        else:
            raise errors.ServiceException(job_id, errors.QAPI_JOB_ERROR,
                                          "Job not found")
    except requests.exceptions.ConnectionError:
        raise errors.ServiceException(config.QUEUE_API_URL,
                                      errors.QAPI_UNREACH_ERROR,
                                      "Check service or network")
    return output
예제 #4
0
async def describe_table(service_id: str, table_name: str, sync: bool = False, ttl: int = 3600,
                         db: databases.Database = Depends(models.get_db)):
    service = await services.get_service(service_id, db)
    if service.driver:
        driver = await drivers.get_driver(service.driver)
        return drivers.service_stack(driver, service, "get", f"/table/{table_name}", sync=sync, ttl=ttl)
    raise errors.ServiceException(service.id, errors.NO_DRV_ERROR, "Service has no driver assigned")
예제 #5
0
async def post_table(service_id: str, table: schemas.Table, sync: bool = False, ttl: int = 3600,
                     db: databases.Database = Depends(models.get_db)):
    service = await services.get_service(service_id, db)
    if service.driver:
        driver = await drivers.get_driver(service.driver)
        return drivers.service_stack(driver, service, "post", "/table", data=table.dict(), sync=sync, ttl=ttl)
    raise errors.ServiceException(service.id, errors.NO_DRV_ERROR, "Service has no driver assigned")
예제 #6
0
async def delete_records(service_id: str, table_name: str, dml_options: schemas.RecordDMLOptions,
                       sync: bool = False, ttl: int = 3600, db: databases.Database = Depends(models.get_db)):
    service = await services.get_service(service_id, db)
    if service.driver:
        driver = await drivers.get_driver(service.driver)
        path = f"/table/{table_name}/record"
        return drivers.service_stack(driver, service, "delete", path, data=dml_options.dict(), sync=sync, ttl=ttl)
    raise errors.ServiceException(service.id, errors.NO_DRV_ERROR, "Service has no driver assigned")
예제 #7
0
def get_driver_container(driver: schemas.DriverBase):
    cont = None
    cont_name = f"{driver.name}-{driver.version}"
    client = docker.from_env()
    try:
        client.images.get(f"{driver.name}:{driver.version}")
        cont = client.containers.get(cont_name)
    except docker.errors.ImageNotFound:
        raise errors.ServiceException(cont_name, errors.NO_DRV_ERROR,
                                      "Image doesn't exist.")
    except docker.errors.NotFound:
        raise errors.ServiceException(cont_name, errors.NO_DRV_ERROR,
                                      "Container doesn't exist.")
    if cont.status == 'exited':
        logger.debug(
            f"Container {cont_name} is not running. Running starting command")
        cont.start()
        time.sleep(3)
        cont = client.containers.get(cont_name)
    return cont
예제 #8
0
async def ping_service(service_id: str,
                       db: databases.Database = Depends(models.get_db)):
    service = await get_service(service_id, db)
    if service.driver:
        driver = await drivers.get_driver(service.driver)
        return drivers.service_stack(driver,
                                     service,
                                     "get",
                                     "/ping",
                                     sync=True)
    raise errors.ServiceException(service.id, errors.NO_DRV_ERROR,
                                  "Service has no driver assigned")
예제 #9
0
async def predict(service_id: str,
                  image_file: UploadFile = File(...),
                  sync: bool = False,
                  ttl: int = 3600,
                  db: databases.Database = Depends(models.get_db)):
    service = await services.get_service(service_id, db)
    if service.driver:
        driver = await drivers.get_driver(service.driver)
        return drivers.service_stack(driver,
                                     service,
                                     "post",
                                     "/predict",
                                     data=image_file,
                                     sync=sync,
                                     ttl=ttl)
    raise errors.ServiceException(service.id, errors.NO_DRV_ERROR,
                                  "Service has no driver assigned")
예제 #10
0
async def assign_driver(service_id: str,
                        driver: schemas.DriverCreate,
                        db: databases.Database = Depends(models.get_db)):
    """ Assign a driver to a service

    Stacks by default may be assigned to a driver if they have one available natively,
    this can be changes in this function.

    To get a list of available drivers for a service, execute a GET call to
    /service/{service_id}/driver
    """
    await get_service(service_id, db)
    if driver.source_type == schemas.SourceTypes.native.value:
        driver_list = await drivers.list_drivers()
        for avail_driver in driver_list:
            if avail_driver.name == driver.name:
                driver = avail_driver
                break
    if isinstance(driver, schemas.DriverCreate):
        raise errors.ServiceException(
            driver.name, errors.NO_DRV_ERROR,
            "Execute a GET to /driver for a list of native drivers")
    drivers.deploy_driver(driver)
    return driver
예제 #11
0
def service_stack(driver: schemas.DriverBase,
                  service: schemas.Service,
                  method: str,
                  path: str,
                  data: dict = {},
                  sync: bool = False,
                  ttl: int = 3600):
    output = ""
    hosts = list(service.locations.values())
    meta = service.meta
    if not meta:
        meta = config.DEFAULT_META.get(driver.scope, {}).get(driver.app)
    headers = {"Metadata": json.dumps(meta), "Hosts": ",".join(hosts)}
    try:
        ip = get_driver_ip(driver)
    except errors.ServiceException as exc:
        drv_create = {
            "name": driver.name,
            "source_type": driver.source_type,
            "location": driver.location
        }
        exc.detail += f"Redeploy driver by executing a POST call to /service/{service.id}/driver with data: {json.dumps(drv_create)}"
        raise exc
    url = f"http://{ip}:{config.DRIVER_PORT}{path}"
    if sync:
        logger.debug(
            f"Executing {method.upper()} {url} with headers: {headers} and data: {data}"
        )
        try:
            kwargs = {
                "headers": headers,
                "proxies": {
                    "http": None
                },
                "json": None,
                "params": None,
                "files": None
            }
            if method == "get":
                kwargs["params"] = data
            else:
                if isinstance(data, dict):
                    kwargs["json"] = data
                if isinstance(data, UploadFile):
                    kwargs["files"] = {
                        'img': (data.filename, data.file.read())
                    }
            resp = requests.request(method.upper(), url, **kwargs)
        except requests.exceptions.ConnectionError:
            raise errors.ServiceException(driver.name,
                                          errors.DRV_UNREACH_ERROR,
                                          f"No route to {url}")
        if resp.status_code == 200:
            try:
                output = json.loads(resp.text)
            except json.decoder.JSONDecodeError:
                raise errors.ServiceException(
                    url, errors.DRV_IMPL_ERROR,
                    f'Ouptut is not JSON deserializable: "{resp.text}"')
        else:
            raise errors.ServiceException(url, errors.DRV_EXEC_ERROR,
                                          resp.text)
    else:
        queues.check_api_status()
        resp = queues.queue_service(service.name, url, method, headers, data,
                                    ttl)
        if resp.status_code == 200:
            output = json.loads(resp.text)
        else:
            raise errors.ServiceException("", errors.QAPI_EXEC_ERROR,
                                          resp.text)
    return output