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")
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
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
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")
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")
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")
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
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")
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")
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
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