Example #1
0
def commit_project(project_id, message, author, changes):
    channel = grpc.insecure_channel(config.PROJECTS_SERVICES_ENDPOINT)
    stub = project_pb2_grpc.ProjectServicesStub(channel=channel)

    project = stub.Retrieve(project_pb2.ID(id=project_id))

    etcd = etcd3.client(host=config.ETCD_HOST, port=config.ETCD_PORT)

    # acquire lock
    with etcd.lock(project_id, ttl=1800) as lock:
        # copy data to repo_bucket
        minio_client = get_minio_client()
        for change in changes:
            key = os.path.relpath(change["path"],
                                  config.ILYDE_WORKING_DIR).replace('\\', '/')
            if change['action'] == "deleted":
                minio_client.remove_object(bucket_name=project.repo_bucket,
                                           object_name=key)
            else:
                file_type, _ = mimetypes.guess_type(change["path"])
                if file_type is None:
                    file_type = 'application/octet-stream'
                minio_client.fput_object(project.repo_bucket,
                                         key,
                                         change["path"],
                                         content_type=file_type)

        # create new revision
        payload = {'project': project_id, 'commit': message, 'author': author}
        response = stub.CreateRevision(project_pb2.Revision(**payload))
        return response
def check_modelapi_permission(obj, token_info):
    stub = get_projects_services_stub()
    project = stub.Retrieve(project_pb2.ID(id=obj.metadata.project))
    if not permissions.IsProjectMember.has_object_permission(
            token_info, project):
        raise connexion.ProblemException(
            status=403,
            title="Permission Denied",
            detail="Doesn't have enough permissions to take this action")
def create_model(body, **kwargs):
    """Create a model

    :param body: Request payload to create a model
    :type body: dict | bytes

    :rtype: ModelSerializer
    """
    serializer = ModelSerializer.from_dict(body)
    description = serializer.description if serializer.description else ""
    project_id = serializer.tags.get("ilyde.project")
    if not project_id:
        raise connexion.ProblemException(
            status=400,
            title="Bad Request",
            detail=
            "ilyde.project tag should be provided with the id of the project.")

    stub = get_projects_services_stub()
    project = stub.Retrieve(project_pb2.ID(id=project_id))
    if not permissions.IsProjectMember.has_object_permission(
            kwargs["token_info"], project):
        raise connexion.ProblemException(
            status=403,
            title="Permission Denied",
            detail="Doesn't have enough permissions to take this action")

    model_name = util.safe_model_name(serializer.name)
    if not model_name.startswith(util.safe_model_name(project.name)):
        model_name = "{}-{}".format(util.safe_model_name(project.name),
                                    model_name)

    mlflow_client = get_mlflow_client()
    model = mlflow_client.create_registered_model(name=model_name,
                                                  description=description,
                                                  tags=serializer.tags)

    return ModelSerializer(
        name=model.name,
        description=model.description,
        tags=model.tags,
        latest_versions=[
            ModelVersionSerializer(
                creation_timestamp=version.creation_timestamp,
                current_stage=version.current_stage,
                description=version.description,
                last_updated_timestamp=version.last_updated_timestamp,
                name=version.name,
                run_id=version.run_id,
                source=version.source,
                status=version.status,
                status_message=version.status_message,
                tags=version.tags,
                version=version.version) for version in model.latest_versions
        ],
        last_updated_timestamp=model.last_updated_timestamp,
        creation_timestamp=model.creation_timestamp)
Example #4
0
def copy_project(project_id, revision_id):
    channel = grpc.insecure_channel(config.PROJECTS_SERVICES_ENDPOINT)
    stub = project_pb2_grpc.ProjectServicesStub(channel=channel)

    project = stub.Retrieve(project_pb2.ID(id=project_id))
    revision = stub.RetrieveRevision(project_pb2.ID(id=revision_id))

    # get minio client
    minio_client = get_minio_client()
    for file in revision.file_tree:
        destination = os.path.join(config.ILYDE_WORKING_DIR, file.name)
        try:
            obj = minio_client.fget_object(bucket_name=project.repo_bucket,
                                           object_name=file.name,
                                           file_path=destination,
                                           version_id=file.version)
            # add modification time
            os.utime(destination, (time.mktime(
                time.localtime()), time.mktime(obj.last_modified)))
        except MinioError as e:
            pass
        except Exception as e:
            pass
Example #5
0
def delete_project(id_, **kwargs):
    """Delete a project
    :param id_: The ID of the project object to be deleted
    :type id_: str

    :rtype: StatusSerializer
    """
    proj = get_project_object(id_)
    check_project_permission(proj, kwargs["token_info"])
    stub = get_projects_services_stub()
    response = stub.Delete(project_pb2.ID(id=proj.id))

    if response.status != 200:
        return ErrorSerializer(status=response.status,
                               title="Api Error",
                               detail=response.message), response.status

    return StatusSerializer.from_dict(util.deserialize_protobuf(response))
Example #6
0
def get_experiment_artifact(id_, path, **kwargs):  # noqa: E501
    """Download experiment artifact

    Download experiment artifact

    :param id_: The ID of the experiment resource
    :type id_: str
    :param path: File's path to download
    :type path: str

    :rtype: file
    """
    stub = get_experiments_services_stub()
    experiment = stub.Get(job_pb2.ID(id=id_))

    stub = get_projects_services_stub()
    project = stub.Retrieve(project_pb2.ID(id=experiment.metadata.project))
    if not IsProjectMember.has_object_permission(kwargs["token_info"], project):
        return ErrorSerializer(status=403,
                               title="Permission Denied",
                               detail="Doesn't have enough permissions to take this action"), 403

    mlflow_client = get_mlflow_client()

    all_experiments = [exp.experiment_id for exp in mlflow_client.list_experiments()]
    run = mlflow_client.search_runs(experiment_ids=all_experiments,
                                    filter_string="tags.`ilyde.job` = '{}'".format(experiment.id),
                                    run_view_type=ViewType.ALL)[0]

    local_dir = os.path.dirname(os.path.join(current_app.config.get("BASE_DIR"), "media", run.info.run_id, path))
    if not os.path.exists(local_dir):
        os.makedirs(local_dir, exist_ok=True)

    local_path = mlflow_client.download_artifacts(run.info.run_id, path, local_dir)
    file_type, _ = mimetypes.guess_type(local_path)
    if file_type is None:
        file_type = 'application/octet-stream'

    with open(local_path, 'rb') as f:
        response = make_response(f.read())
        response.headers.set('Content-Type', file_type)
        return response, 200
Example #7
0
def get_project_file(id_, path, version, **kwargs):
    """Download project's file

    Download project's file

    :param id_: The ID of the project resource
    :type id_: str
    :param path: File's path to download
    :type version: str
    :param version: File's version to download
    :type version: str

    :rtype: file
    """
    stub = get_projects_services_stub()
    project = stub.Retrieve(project_pb2.ID(id=id_))
    if not IsProjectMember.has_object_permission(kwargs["token_info"], project):
        return ErrorSerializer(status=403,
                               title="Permission Denied",
                               detail="Doesn't have enough permissions to take this action"), 403

    extra_params = {}
    if version is not None:
        extra_params['version_id'] = version

    client = services.get_minio_client()

    data = client.get_object(project.repo_bucket, path, **extra_params)

    if int(data.getheader('Content-Length')) > 1024 * 1024 * 30:
        return ErrorSerializer(status=400, title="Bad Request",
                               detail="File is too large."), 400

    response = make_response(data.read())
    response.headers.set('Content-Type', data.getheader('Content-Type'))

    return response, 200
Example #8
0
def retrieve_project_revision(revision_id):
    channel = grpc.insecure_channel(config.PROJECTS_SERVICES_ENDPOINT)
    stub = project_pb2_grpc.ProjectServicesStub(channel=channel)

    return stub.RetrieveRevision(project_pb2.ID(id=revision_id))
Example #9
0
def get_project_object(project_id):
    stub = get_projects_services_stub()
    return stub.Retrieve(project_pb2.ID(id=project_id))