Exemplo n.º 1
0
    def AddBento(self, request, context=None):
        try:
            # TODO: validate request

            bento_metadata_pb = self.bento_metadata_store.get(
                request.bento_name, request.bento_version)
            if bento_metadata_pb:
                error_message = "BentoService bundle: {}:{} already exist".format(
                    request.bento_name, request.bento_version)
                logger.error(error_message)
                return AddBentoResponse(status=Status.ABORTED(error_message))

            new_bento_uri = self.repo.add(request.bento_name,
                                          request.bento_version)
            self.bento_metadata_store.add(
                bento_name=request.bento_name,
                bento_version=request.bento_version,
                uri=new_bento_uri.uri,
                uri_type=new_bento_uri.type,
            )

            return AddBentoResponse(status=Status.OK(), uri=new_bento_uri)
        except BentoMLException as e:
            logger.error("RPC ERROR AddBento: %s", e)
            return DeleteDeploymentResponse(status=e.status_proto)
Exemplo n.º 2
0
    def DescribeDeployment(self, request, context=None):
        try:
            request.namespace = request.namespace or self.default_namespace
            deployment_pb = self.deployment_store.get(request.deployment_name,
                                                      request.namespace)

            if deployment_pb:
                operator = get_deployment_operator(self, deployment_pb)

                response = operator.describe(deployment_pb)

                if response.status.status_code == status_pb2.Status.OK:
                    with self.deployment_store.update_deployment(
                            request.deployment_name,
                            request.namespace) as deployment:
                        deployment.state = ProtoMessageToDict(response.state)

                return response
            else:
                return DescribeDeploymentResponse(status=Status.NOT_FOUND(
                    'Deployment "{}" in namespace "{}" not found'.format(
                        request.deployment_name, request.namespace)))
        except BentoMLException as e:
            logger.error("RPC ERROR DescribeDeployment: %s", e)
            return DeleteDeploymentResponse(status=e.status_proto)
Exemplo n.º 3
0
    def DeleteDeployment(self, request, context=None):
        try:
            request.namespace = request.namespace or self.default_namespace
            deployment_pb = self.deployment_store.get(request.deployment_name,
                                                      request.namespace)

            if deployment_pb:
                # find deployment operator based on deployment spec
                operator = get_deployment_operator(self, deployment_pb)

                # executing deployment deletion
                response = operator.delete(deployment_pb)

                # if delete successful, remove it from active deployment records table
                if response.status.status_code == status_pb2.Status.OK:
                    self.deployment_store.delete(request.deployment_name,
                                                 request.namespace)
                    return response

                # If force delete flag is True, we will remove the record
                # from yatai database.
                if request.force_delete:
                    self.deployment_store.delete(request.deployment_name,
                                                 request.namespace)
                    return DeleteDeploymentResponse(status=Status.OK())

                if response.status.status_code == status_pb2.Status.NOT_FOUND:
                    modified_message = (
                        'Cloud resources not found, error: {} - it may have been '
                        'deleted manually. Try delete deployment '
                        'with "--force" option to ignore this error '
                        'and force deleting the deployment record'.format(
                            response.status.error_message))
                    response.status.error_message = modified_message

                return response
            else:
                return DeleteDeploymentResponse(status=Status.NOT_FOUND(
                    'Deployment "{}" in namespace "{}" not found'.format(
                        request.deployment_name, request.namespace)))

        except BentoMLException as e:
            logger.error("RPC ERROR DeleteDeployment: %s", e)
            return DeleteDeploymentResponse(status=e.status_proto)
        except Exception as e:
            logger.error("RPC ERROR DeleteDeployment: %s", e)
            return DeleteDeploymentResponse(status=status_pb2.Status.INTERNAL)
Exemplo n.º 4
0
    def delete(self, deployment_pb, yatai_service=None):
        try:
            state = self.describe(deployment_pb, yatai_service).state
            if state.state != DeploymentState.RUNNING:
                message = ('Failed to delete, no active deployment {name}. '
                           'The current state is {state}'.format(
                               name=deployment_pb.name,
                               state=DeploymentState.State.Name(state.state),
                           ))
                return DeleteDeploymentResponse(status=Status.ABORTED(message))

            deployment_spec = deployment_pb.spec
            gcp_config = deployment_spec.gcp_function_operator_config

            bento_pb = yatai_service.GetBento(
                GetBentoRequest(
                    bento_name=deployment_spec.bento_name,
                    bento_version=deployment_spec.bento_version,
                ))
            bento_service_metadata = bento_pb.bento.bento_service_metadata
            api_names = ([gcp_config.api_name] if gcp_config.api_name else
                         [api.name for api in bento_service_metadata.apis])
            with TempDirectory() as serverless_project_dir:
                generate_gcp_function_serverless_config(
                    deployment_pb.name,
                    api_names,
                    serverless_project_dir,
                    gcp_config.region,
                    # BentoML namespace is mapping to serverless stage.
                    stage=deployment_pb.namespace,
                )
                try:
                    response = call_serverless_command(['remove'],
                                                       serverless_project_dir)
                    if "Serverless: Stack removal finished..." in response:
                        status = Status.OK()
                    else:
                        status = Status.ABORTED()
                except BentoMLException as e:
                    status = Status.INTERNAL(str(e))

            return DeleteDeploymentResponse(status=status)
        except BentoMLException as error:
            return DeleteDeploymentResponse(
                status=exception_to_return_status(error))
Exemplo n.º 5
0
    def delete(self, deployment_pb, repo=None):
        deployment_spec = deployment_pb.spec
        sagemaker_config = deployment_spec.sagemaker_operator_config
        if sagemaker_config is None:
            raise BentoMLDeploymentException('Sagemaker configuration is missing.')
        sagemaker_client = boto3.client('sagemaker', sagemaker_config.region)

        endpoint_name = generate_aws_compatible_string(
            deployment_pb.namespace + '-' + deployment_spec.bento_name
        )
        delete_endpoint_response = sagemaker_client.delete_endpoint(
            EndpointName=endpoint_name
        )
        logger.debug("AWS delete endpoint response: %s", delete_endpoint_response)
        if delete_endpoint_response["ResponseMetadata"]["HTTPStatusCode"] == 200:
            # We will also try to delete both model and endpoint configuration for user.
            # Since they are not critical, even they failed, we will still count delete
            # deployment a success action
            model_name = create_sagemaker_model_name(
                deployment_spec.bento_name, deployment_spec.bento_version
            )
            delete_model_response = sagemaker_client.delete_model(ModelName=model_name)
            logger.debug("AWS delete model response: %s", delete_model_response)
            if delete_model_response["ResponseMetadata"]["HTTPStatusCode"] != 200:
                logger.error(
                    "Encounter error when deleting model: %s", delete_model_response
                )

            endpoint_config_name = create_sagemaker_endpoint_config_name(
                deployment_spec.bento_name, deployment_spec.bento_version
            )
            delete_endpoint_config_response = sagemaker_client.delete_endpoint_config(  # noqa: E501
                EndpointConfigName=endpoint_config_name
            )
            logger.debug(
                "AWS delete endpoint config response: %s",
                delete_endpoint_config_response,
            )
            return DeleteDeploymentResponse(status=Status.OK())
        else:
            return DeleteDeploymentResponse(
                status=Status.INTERNAL(str(delete_endpoint_response))
            )
Exemplo n.º 6
0
def create_yatai_service_mock():
    yatai_service_mock = Mock()
    yatai_service_mock.ApplyDeployment.return_value = ApplyDeploymentResponse()
    yatai_service_mock.DeleteDeployment.return_value = DeleteDeploymentResponse()
    yatai_service_mock.DescribeDeployment.return_value = DescribeDeploymentResponse()
    yatai_service_mock.GetDeployment.return_value = GetDeploymentResponse(
        status=Status.NOT_FOUND()
    )
    yatai_service_mock.ListDeployments.return_value = ListDeploymentsResponse()
    return yatai_service_mock
Exemplo n.º 7
0
    def DeleteDeployment(self, request, context):
        try:
            deployment_name = request.deployment_name
            deployment_pb = self.store.get(deployment_name)
            operator = get_deployment_operator(deployment_pb)
            return operator.delete(request)

        except BentoMLException:
            response = DeleteDeploymentResponse()
            # response.status = ...
            # LOG.error(....)
            return response
Exemplo n.º 8
0
    def ListDeployments(self, request, context=None):
        try:
            namespace = request.namespace or self.default_namespace
            deployment_pb_list = self.deployment_store.list(
                namespace=namespace,
                labels_query=request.labels_query,
                offset=request.offset,
                limit=request.limit,
                operator=request.operator,
                order_by=request.order_by,
                ascending_order=request.ascending_order,
            )

            return ListDeploymentsResponse(status=Status.OK(),
                                           deployments=deployment_pb_list)
        except BentoMLException as e:
            logger.error("RPC ERROR ListDeployments: %s", e)
            return DeleteDeploymentResponse(status=e.status_proto)
        except Exception as e:
            logger.error("RPC ERROR ListDeployments: %s", e)
            return DeleteDeploymentResponse(status=Status.INTERNAL())
Exemplo n.º 9
0
    def delete(self, deployment_pb):
        try:
            deployment_spec = deployment_pb.spec
            sagemaker_config = deployment_spec.sagemaker_operator_config
            sagemaker_client = boto3.client('sagemaker', sagemaker_config.region)
            _, _, sagemaker_endpoint_name = _get_sagemaker_resource_names(deployment_pb)

            try:
                delete_endpoint_response = sagemaker_client.delete_endpoint(
                    EndpointName=sagemaker_endpoint_name
                )
                logger.debug(
                    "AWS delete endpoint response: %s", delete_endpoint_response
                )
            except ClientError as e:
                raise _aws_client_error_to_bentoml_exception(e)

            _try_clean_up_sagemaker_deployment_resource(deployment_pb)

            return DeleteDeploymentResponse(status=Status.OK())
        except BentoMLException as error:
            return DeleteDeploymentResponse(status=error.status_proto)
Exemplo n.º 10
0
    def delete(self, deployment_pb, repo=None):
        state = self.describe(deployment_pb, repo).state
        if state.state != DeploymentState.RUNNING:
            message = ('Failed to delete, no active deployment {name}. '
                       'The current state is {state}'.format(
                           name=deployment_pb.name,
                           state=DeploymentState.State.Name(state.state),
                       ))
            return DeleteDeploymentResponse(status=Status.ABORTED(message))

        deployment_spec = deployment_pb.spec
        aws_config = deployment_spec.aws_lambda_operator_config

        bento_path = repo.get(deployment_spec.bento_name,
                              deployment_spec.bento_version)
        bento_config = load_bentoml_config(bento_path)

        with TemporaryServerlessConfig(
                archive_path=bento_path,
                deployment_name=deployment_pb.name,
                region=aws_config.region,
                stage=deployment_pb.namespace,
                provider_name='aws',
                functions=generate_aws_handler_functions_config(
                    bento_config['apis']),
        ) as tempdir:
            response = call_serverless_command(['remove'], tempdir)
            stack_name = '{name}-{namespace}'.format(
                name=deployment_pb.name, namespace=deployment_pb.namespace)
            if "Serverless: Stack removal finished..." in response:
                status = Status.OK()
            elif "Stack '{}' does not exist".format(stack_name) in response:
                status = Status.NOT_FOUND('Resource not found')
            else:
                status = Status.ABORTED()

        return DeleteDeploymentResponse(status=status)
Exemplo n.º 11
0
    def ListDeployments(self, request, context=None):
        try:
            namespace = request.namespace or self.default_namespace
            deployment_pb_list = self.deployment_store.list(
                namespace=namespace,
                filter_str=request.filter,
                labels=request.labels,
                offset=request.offset,
                limit=request.limit,
            )

            return ListDeploymentsResponse(status=Status.OK(),
                                           deployments=deployment_pb_list)
        except BentoMLException as e:
            logger.error("RPC ERROR ListDeployments: %s", e)
            return DeleteDeploymentResponse(status=e.status_proto)
Exemplo n.º 12
0
    def delete(self, deployment_pb, repo):
        # delete deployment

        return DeleteDeploymentResponse(status=Status.OK())