def create_endpoint(parameters: dict, namespace: str, id_token: str):
    if not tenant_exists(namespace, id_token=id_token):
        raise TenantDoesNotExistException(tenant_name=namespace)

    metadata = {"name": parameters['endpointName']}
    body = {"apiVersion": CRD_API_VERSION, "kind": CRD_KIND,
            "spec": parameters, "metadata": metadata}
    api_instance = get_k8s_api_client(id_token)
    if 'resources' in parameters:
        validate_quota_compliance(api_instance, namespace=namespace,
                                  endpoint_quota=parameters['resources'])
        parameters['resources'] = transform_quota(parameters['resources'])

    apps_api_instance = get_k8s_apps_api_client(id_token)
    verify_endpoint_amount(api_instance, apps_api_instance, namespace)

    custom_obj_api_instance = get_k8s_api_custom_client(id_token)
    try:
        custom_obj_api_instance.create_namespaced_custom_object(CRD_GROUP, CRD_VERSION, namespace,
                                                                CRD_PLURAL, body)
    except ApiException as apiException:
        raise KubernetesCreateException('endpoint', apiException)
    endpoint_url = create_url_to_service(parameters['endpointName'], namespace)
    logger.info('Endpoint {} created\n'.format(endpoint_url))
    return endpoint_url
def view_endpoint(endpoint_name: str, namespace: str, id_token: str):
    if not tenant_exists(namespace, id_token=id_token):
        raise TenantDoesNotExistException(tenant_name=namespace)
    if not endpoint_exists(endpoint_name, namespace, id_token):
        raise EndpointDoesNotExistException(endpoint_name=endpoint_name)
    custom_api_instance = get_k8s_api_custom_client(id_token)
    api_instance = get_k8s_api_client(id_token)
    apps_api_instance = get_k8s_apps_api_client(id_token)

    endpoint_status = get_endpoint_status(api_instance=api_instance, namespace=namespace,
                                          endpoint_name=endpoint_name)
    model_path = create_url_to_service(endpoint_name, namespace)
    subject_name, resources = get_crd_subject_name_and_resources(
        custom_api_instance=custom_api_instance, namespace=namespace, endpoint_name=endpoint_name)
    replicas = get_replicas(apps_api_instance=apps_api_instance, namespace=namespace,
                            endpoint_name=endpoint_name)

    view_dict = {'Endpoint status': endpoint_status,
                 'Model path': model_path,
                 'Subject name': subject_name,
                 'Resources': resources,
                 'Replicas': replicas,
                 }
    message = f"Endpoint {endpoint_name} in {namespace} tenant: {view_dict}\n"
    logger.info(message)
    return message
Пример #3
0
def delete_model(parameters: dict, namespace: str, id_token):
    if not tenant_exists(namespace, id_token):
        raise TenantDoesNotExistException(namespace)

    model_path = f"{parameters['modelName']}-{parameters['modelVersion']}"
    bucket = minio_resource.Bucket(name=namespace)
    model_in_bucket = bucket.objects.filter(Prefix=model_path)

    if not model_exists(model_in_bucket):
        raise ModelDoesNotExistException(model_path)

    apps_api_client = get_k8s_apps_api_client(id_token)
    try:
        deployments = apps_api_client.list_namespaced_deployment(namespace)
    except ApiException as apiException:
        raise KubernetesGetException('deployment', apiException)

    endpoint_names = endpoints_using_model(deployments, model_path)
    if endpoint_names:
        raise ModelDeleteException(
            f'model is used by endpoints: {endpoint_names}')

    for key in model_in_bucket:
        key.delete()

    return model_path
Пример #4
0
    def on_put(self, req, resp, tenant_name):
        namespace = tenant_name
        multipart_id = req.get_param('uploadId')
        try:
            part_number = int(req.get_param('partNumber'))
        except (ValueError, TypeError):
            raise InvalidParamException('partNumber',
                                        'Wrong partNumber parameter value')
        key = get_key(req.params)
        logger.info(f"Key: {key} ID: {multipart_id}")
        data = req.stream.read()
        if not tenant_exists(namespace, id_token=req.params['Authorization']):
            raise TenantDoesNotExistException(tenant_name=namespace)

        part_etag = upload_part(data=data,
                                part_number=part_number,
                                bucket=namespace,
                                key=key,
                                multipart_id=multipart_id)
        logger.info(f"ETag: {part_etag}")
        resp.status = falcon.HTTP_200
        resp.body = json.dumps({
            'status': 'OK',
            'data': {
                'ETag': part_etag,
                'op': 'upload_part'
            }
        })
Пример #5
0
def list_models(namespace: str, id_token):
    if not tenant_exists(namespace, id_token):
        raise TenantDoesNotExistException(namespace)

    apps_api_client = get_k8s_apps_api_client(id_token)
    try:
        deployments = apps_api_client.list_namespaced_deployment(namespace)
    except ApiException as apiException:
        raise KubernetesGetException('deployment', apiException)

    try:
        bucket = minio_resource.Bucket(name=namespace)
    except ClientError as clientError:
        raise MinioCallException(
            f'An error occurred during bucket reading: {clientError}')

    models = []
    for object in bucket.objects.all():
        if object.size > 0:
            model_path = object.key.split('/')[0].rsplit('-', 1)
            model_name = model_path[0]
            model_version = model_path[-1]
            model_size = object.size
            deployment_count = len(
                endpoints_using_model(deployments, model_path))
            models.append(
                (model_name, model_version, model_size, deployment_count))

    if not models:
        return f"There are no models present in {namespace} tenant\n"
    else:
        return f'Models in {namespace} tenant ' \
               f'(model name, model version, model size, deployed count): {models}\n'
Пример #6
0
    def on_post(self, req, resp, tenant_name):
        namespace = tenant_name
        body = req.media
        key = get_key(body)
        if not tenant_exists(namespace, id_token=req.get_header('Authorization')):
            raise TenantDoesNotExistException(tenant_name=namespace)

        abort_upload(bucket=namespace, key=key, multipart_id=body['uploadId'])
        resp.status = falcon.HTTP_200
        resp.body = f"Upload with ID: {body['uploadId']} aborted successfully"
def list_endpoints(namespace: str, id_token: str):
    if not tenant_exists(namespace, id_token=id_token):
        raise TenantDoesNotExistException(tenant_name=namespace)
    apps_api_instance = get_k8s_apps_api_client(id_token)
    try:
        deployments = apps_api_instance.list_namespaced_deployment(namespace)
    except ApiException as apiException:
        raise KubernetesGetException('endpoint', apiException)
    endpoints_name_status = get_endpoints_name_status(deployments, namespace)
    logger.info(endpoints_name_status)
    return endpoints_name_status
Пример #8
0
    def on_post(self, req, resp, tenant_name):
        namespace = tenant_name
        body = req.media
        key = get_key(body)
        if not tenant_exists(namespace, id_token=req.get_header('Authorization')):
            raise TenantDoesNotExistException(tenant_name=namespace)

        upload_id = create_upload(bucket=namespace, key=key)
        logger.info("Key: " + key + "  ID: " + upload_id)
        resp.status = falcon.HTTP_200
        resp.body = json.dumps({'uploadId': upload_id})
Пример #9
0
 def on_post(self, req, resp, tenant_name):
     namespace = tenant_name
     body = req.media
     key = get_dir_key(body)
     if not tenant_exists(namespace,
                          id_token=req.get_header('Authorization')):
         raise TenantDoesNotExistException(tenant_name=namespace)
     response = create_dir(tenant_name, key)
     resp.status = falcon.HTTP_200
     resp.body = json.dumps({
         'status': 'OK',
         'data': {
             'dir': response,
             'op': 'create_dir'
         }
     })
Пример #10
0
    def on_post(self, req, resp, tenant_name):
        namespace = tenant_name
        body = req.media
        key = get_key(body)
        if not tenant_exists(namespace, id_token=req.params['Authorization']):
            raise TenantDoesNotExistException(tenant_name=namespace)

        abort_upload(bucket=namespace, key=key, multipart_id=body['uploadId'])
        resp.status = falcon.HTTP_200
        resp.body = json.dumps({
            'status': 'OK',
            'data': {
                'uploadId': body['uploadId'],
                'op': 'upload_abort'
            }
        })
Пример #11
0
def delete_model(parameters: dict, namespace: str, id_token):
    # TODO Add checking if model is used by endpoint
    if not tenant_exists(namespace, id_token):
        raise TenantDoesNotExistException(namespace)

    model_path = f"{parameters['modelName']}/{parameters['modelVersion']}/"
    bucket = minio_resource.Bucket(name=namespace)
    model_in_bucket = bucket.objects.filter(Prefix=model_path)

    if not model_exists(model_in_bucket):
        raise ModelDoesNotExistException(model_path)

    for key in model_in_bucket:
        key.delete()

    logger.info(f'Model {model_path} deleted')
    return model_path
Пример #12
0
def list_models(namespace: str, id_token):
    # TODO Add checking if model is used by endpoint
    if not tenant_exists(namespace, id_token):
        raise TenantDoesNotExistException(namespace)

    try:
        bucket = minio_resource.Bucket(name=namespace)
    except ClientError as clientError:
        raise MinioCallException(
            f'An error occurred during bucket reading: {clientError}')

    models = []
    for object in bucket.objects.all():
        if object.size > 0:
            model = dict()
            model_path = object.key.split('/', 2)
            model['path'] = object.key
            model['name'] = model_path[0]
            model['version'] = model_path[1]
            model['size'] = object.size
            models.append(model)

    logger.info(f'Models present in {namespace} tenant: {models}')
    return models