Ejemplo n.º 1
0
def settings(request, user, project_slug):
    user_permissions = get_permissions(request, project_slug, sett.PROJECT_SETTINGS_PERM)
    print(user_permissions)
    template = 'settings.html'
    project = Project.objects.filter(Q(owner=request.user) | Q(authorized=request.user), Q(slug=project_slug)).first()
    url_domain = sett.DOMAIN
    platform_users = User.objects.filter(~Q(pk=project.owner.pk))
    environments = Environment.objects.all()

    minio_keys = get_minio_keys(project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']

    if request.method == 'POST':
        form = TransferProjectOwnershipForm(request.POST)
        if form.is_valid():
            new_owner_id = int(form.cleaned_data['transfer_to'])
            new_owner = User.objects.filter(pk=new_owner_id).first()
            project.owner = new_owner
            project.save()

            l = ProjectLog(project=project, module='PR', headline='Project owner',
                           description='Transferred Project ownership to {owner}'.format(owner=project.owner.username))
            l.save()

            return HttpResponseRedirect('/projects/')
    else:
        form = TransferProjectOwnershipForm()

    return render(request, template, locals())
Ejemplo n.º 2
0
def settings(request, user, project_slug):
    template = 'settings.html'
    project = Project.objects.filter(
        Q(owner=request.user) | Q(authorized=request.user),
        Q(slug=project_slug)).first()
    url_domain = sett.DOMAIN
    platform_users = User.objects.filter(~Q(pk=project.owner.pk))
    environments = Environment.objects.all()

    minio_keys = get_minio_keys(project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']

    if request.method == 'POST':
        form = TransferProjectOwnershipForm(request.POST)
        if form.is_valid():
            new_owner_id = int(form.cleaned_data['transfer_to'])
            new_owner = User.objects.filter(pk=new_owner_id).first()
            project.owner = new_owner
            project.save()
            return HttpResponseRedirect('/projects/')
    else:
        form = TransferProjectOwnershipForm()

    return render(request, template, locals())
Ejemplo n.º 3
0
def build_definition(instance):
    import uuid
    from projects.helpers import get_minio_keys

    minio_keys = get_minio_keys(instance.project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']

    build_templ = Template(DEPLOY_DEFINITION_TEMPLATE)
    image = 'registry.{}/depdef-{}'.format(settings.DOMAIN, instance.name)
    job = build_templ.substitute(
        bucket=instance.bucket,
        context=instance.filename,
        name=instance.name,
        jobid=uuid.uuid1().hex[0:5],
        image='{}.default.svc.cluster.local:5000/depdef-{}'.format(
            settings.REGISTRY_SVC, instance.name),
        access_key=decrypted_key,
        secret_key=decrypted_secret,
        s3endpoint='http://{}-minio:9000'.format(instance.project.slug))
    import yaml
    from projects.jobs import start_job
    job = yaml.safe_load(job)
    start_job(job)
    instance.image = image
    instance.save()
Ejemplo n.º 4
0
def datasheet(request, user, project, page_index):
    template = 'dataset_datasheet.html'
    project = Project.objects.filter(slug=project).first()
    url_domain = sett.DOMAIN

    minio_keys = get_minio_keys(project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']

    submitbutton = request.POST.get("submit")

    datasheet_info = []

    form = DatasheetForm(request.POST or None)
    if form.is_valid():
        datasheet_info.append(form.cleaned_data.get("q1"))
        datasheet_info.append(form.cleaned_data.get("q2"))
        print(datasheet_info)

    datasets = []
    try:
        minio_repository = MinioRepository('{}-minio:9000'.format(project.slug), decrypted_key,
                                           decrypted_secret)

        objects = minio_repository.client.list_objects_v2('dataset')
        for obj in objects:
            datasets.append({'is_dir': obj.is_dir,
                             # remove '/' after the directory name
                             'name': obj.object_name[:-1] if obj.is_dir else obj.object_name,
                             'datasheet': 'datasheet',
                             'size': round(obj.size / 1000000, 2),
                             'location': 'minio',
                             'modified': obj.last_modified})
    except ResponseError as err:
        print(err)

    previous_page = 1
    next_page = 1
    if len(datasets) > 0:
        import math
        # allow 10 rows per page in the table
        pages = list(map(lambda x: x + 1, range(math.ceil(len(datasets) / 10))))

        datasets = datasets[page_index * 10 - 10:page_index * 10]

        previous_page = page_index if page_index == 1 else page_index - 1
        next_page = page_index if page_index == pages[-1] else page_index + 1

    return render(request, template, locals())
Ejemplo n.º 5
0
def upload_report_json(report_id, client=None):
    report = Report.objects.filter(pk=report_id).first()
    project = report.model.project

    minio_keys = get_minio_keys(project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']

    report_json = {
        'project_id': project.id,
        'model_id': report.model.id,
        'model_uid': report.model.uid,
        'description': report.description,
        'report': report.report
    }

    filename = 'reports/report_{}.json'.format(report_id)
    with open(filename, 'w') as json_file:
        json.dump(report_json, json_file)

    try:
        if not client:
            minio_repository = MinioRepository(
                '{}-minio:9000'.format(project.slug), decrypted_key,
                decrypted_secret)

            client = minio_repository.client

        with open(filename, 'rb') as file_data:
            file_stat = os.stat(filename)
            client.put_object('reports',
                              filename.replace('reports/', ''),
                              file_data,
                              file_stat.st_size,
                              content_type='application/json')

            l = ProjectLog(
                project=project,
                module='RE',
                headline='Metrics',
                description='JSON file {filename} has been uploaded to MinIO'.
                format(filename=filename.replace('reports/', '')))
            l.save()

    except ResponseError as err:
        print(err)

    os.unlink(filename)
Ejemplo n.º 6
0
def pre_delete_model(sender, instance, using, **kwargs):
    # Model is saved in bucket 'model' with filename 'instance.uid'
    minio_url = '{}-minio.{}'.format(instance.project.slug, settings.DOMAIN)
    minio_keys = get_minio_keys(instance.project)
    try:
        client = Minio(minio_url,
                       access_key=minio_keys['project_key'],
                       secret_key=minio_keys['project_secret'],
                       secure=True)
        client.remove_object('models', instance.uid)
    except:
        print('Failed to delete model object {} from minio store.'.format(
            instance.uid))
    # Check if model has been deployed, if so, delete deployment.
    if instance.status == 'DP':
        deployment = DeploymentInstance.objects.get(model=instance)
        deployment.delete()
Ejemplo n.º 7
0
def path_page(request, user, project, path_name, page_index):
    template = 'dataset_path_page.html'
    project = Project.objects.filter(slug=project).first()
    url_domain = sett.DOMAIN

    minio_keys = get_minio_keys(project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']

    datasets = []
    try:
        minio_repository = MinioRepository(
            '{}-minio:9000'.format(project.slug), decrypted_key,
            decrypted_secret)

        objects = minio_repository.client.list_objects_v2('dataset',
                                                          recursive=True)
        for obj in objects:
            if obj.object_name.startswith(path_name + '/'):
                datasets.append({
                    'is_dir':
                    obj.is_dir,
                    'name':
                    obj.object_name.replace(path_name + '/', ''),
                    'size':
                    round(obj.size / 1000000, 2),
                    'modified':
                    obj.last_modified
                })

        import math
        pages = list(map(lambda x: x + 1,
                         range(math.ceil(len(datasets) / 10))))
    except ResponseError as err:
        print(err)

    datasets = datasets[page_index * 10 - 10:page_index * 10]

    previous_page = page_index if page_index == 1 else page_index - 1
    next_page = page_index if page_index == pages[-1] else page_index + 1

    return render(request, template, locals())
Ejemplo n.º 8
0
def get_download_link(project_id, filename, client=None):
    project = Project.objects.filter(pk=project_id).first()

    minio_keys = get_minio_keys(project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']

    download_link = None
    try:
        if not client:
            minio_repository = MinioRepository(
                '{}-minio:9000'.format(project.slug), decrypted_key,
                decrypted_secret)

            client = minio_repository.client

        download_link = client.presigned_get_object('reports',
                                                    filename,
                                                    expires=timedelta(days=2))
    except ResponseError as err:
        print(err)

    return download_link
Ejemplo n.º 9
0
def pre_save_deployment(sender, instance, using, **kwargs):
    model = instance.model

    if model.status == 'DP':
        raise Exception('Model already deployed.')

    model_file = model.uid
    model_bucket = 'models'

    deployment_name = slugify(model.name)
    deployment_version = slugify(model.version)
    deployment_endpoint = '{}-{}.{}'.format(model.name, model.version,
                                            settings.DOMAIN)

    deployment_endpoint = settings.DOMAIN
    deployment_path = '/{}/serve/{}/{}/'.format(model.project.slug,
                                                slugify(model.name),
                                                slugify(model.version))

    instance.endpoint = deployment_endpoint
    instance.path = deployment_path

    context = instance.deployment
    context_image = context.image

    project = model.project
    project_slug = project.slug

    minio_keys = get_minio_keys(project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']
    minio_access_key = decrypted_key
    minio_secret_key = decrypted_secret

    minio_host = project_slug + '-minio:9000'

    global_domain = settings.DOMAIN

    HOST = settings.DOMAIN
    RELEASE_NAME = slugify(
        str(project_slug) + '-' + str(deployment_name) + '-' +
        str(deployment_version))
    burl = os.path.join('https://', HOST)
    eurl = os.path.join(deployment_endpoint, deployment_path)
    URL = burl + eurl

    instance.appname = instance.model.project.slug + '-' + slugify(
        instance.model.name) + '-' + slugify(instance.model.version)

    # Create Keycloak client corresponding to this deployment
    print(URL)
    print(RELEASE_NAME)
    print(instance.created_by.username)
    client_id, client_secret = keylib.keycloak_setup_base_client(
        URL, RELEASE_NAME, instance.created_by.username, ['owner'], ['owner'])

    skip_tls = 0
    if not settings.OIDC_VERIFY_SSL:
        skip_tls = 1
        print("WARNING: Skipping TLS verify.")

    # Default is that access is private.
    rules = """resources:
    - uri: /*
      roles:
      - {}:owner
    """.format(client_id)

    access_rules = {"gatekeeper.rules": rules}

    if 'access' in instance.params:
        print(instance.params['access'])
        if instance.params['access'] == 'public':
            # No rule means open to anyone.
            print("Public endpoint")
            access_rules = {"gatekeeper.rules": "public"}
        del instance.params['access']

    print(instance.params)

    parameters = {
        'release': RELEASE_NAME,
        'chart': 'deploy',
        'namespace': settings.NAMESPACE,
        'appname': instance.appname,
        'replicas': '1',
        'global.domain': global_domain,
        'project.slug': project_slug,
        'deployment.version': deployment_version,
        'deployment.name': deployment_name,
        'deployment.endpoint': deployment_endpoint,
        'deployment.path': deployment_path,
        'context.image': context_image,
        'model.bucket': model_bucket,
        'model.file': model_file,
        'minio.host': minio_host,
        'minio.secret_key': minio_secret_key,
        'minio.access_key': minio_access_key,
        'gatekeeper.realm': settings.KC_REALM,
        'gatekeeper.client_secret': client_secret,
        'gatekeeper.client_id': client_id,
        'gatekeeper.auth_endpoint': settings.OIDC_OP_REALM_AUTH,
        'gatekeeper.skip_tls': str(skip_tls)
    }

    parameters.update(instance.params)
    parameters.update(access_rules)
    print('creating chart')
    helmchart = HelmResource(name=RELEASE_NAME,
                             namespace='Default',
                             chart='deploy',
                             params=parameters,
                             username=instance.created_by.username)
    helmchart.save()
    instance.helmchart = helmchart

    if helmchart.status == 'Failed':
        # If fail, clean up in Keycloak
        kc = keylib.keycloak_init()
        keylib.keycloak_delete_client(kc, RELEASE_NAME)
        scope_id = keylib.keycloak_get_client_scope_id(kc,
                                                       RELEASE_NAME + '-scope')
        keylib.keycloak_delete_client_scope(kc, scope_id)
        raise Exception('Failed to launch deploy job.')
    else:
        instance.release = RELEASE_NAME
        model.status = 'DP'
        model.save()
Ejemplo n.º 10
0
def run(request, user, project):
    project = Project.objects.filter(Q(slug=project), Q(owner=request.user) | Q(authorized=request.user)).first()

    if request.method == "POST":
        uid = uuid.uuid4()
        name = str(project.slug) + str(uid)[0:7]
        flavor_slug = request.POST.get('flavor', None)
        environment_slug = request.POST.get('environment', None)

        if flavor_slug:
            flavor = Flavor.objects.filter(slug=flavor_slug).first()
        else:
            flavor = Flavor.objects.all().first()

        if environment_slug:
            environment = Environment.objects.filter(slug=environment_slug).first()
        else:
            environment = Environment.objects.filter.all().first()

        print("dispatching with {}  {}".format(flavor, name))
        import base64
        if name != '' and flavor is not None:
            # Default values here, because otherwise an old deployment can stop working
            # if the deployment configuration files are not compatible with the latest
            # studio image.
            ingress_secret_name = 'prod-ingress'
            try:
                ingress_secret_name = settings.LABS['ingress']['secretName']
            except:
                pass

            minio_keys = get_minio_keys(project)
            decrypted_key = minio_keys['project_key']
            decrypted_secret = minio_keys['project_secret']

            settings_file = ProjectSerializer(project)

            settings_file = JSONRenderer().render(settings_file.data)
            settings_file = settings_file.decode('utf-8')
            print(settings_file)
            # settings_file = yaml.load(settings_file, Loader=yaml.FullLoader)
            settings_file = json.loads(settings_file)
            settings_file = yaml.dump(settings_file)
            print(settings_file)
            # settings_file = json.dumps(json.loads(settings_file))

            # settings_file = yaml.dump(settings_file)
            user_config_file = create_user_settings(user)
            user_config_file = yaml.dump(json.loads(user_config_file))

            prefs = {'labs.resources.requests.cpu': str(flavor.cpu),
                     'labs.resources.limits.cpu': str(flavor.cpu),
                     'labs.resources.requests.memory': str(flavor.mem),
                     'labs.resources.limits.memory': str(flavor.mem),
                     'labs.resources.requests.gpu': str(flavor.gpu),
                     'labs.resources.limits.gpu': str(flavor.gpu),
                     'labs.gpu.enabled': str("true" if flavor.gpu else "false"),
                     'labs.image': environment.image,
                     'ingress.secretName': ingress_secret_name,
                     # 'labs.setup': environment.setup,
                     'minio.access_key': decrypted_key,
                     'minio.secret_key': decrypted_secret,
                     'settings_file': settings_file,
                     'user_settings_file': user_config_file,
                     'project.slug': project.slug
                     }
            session = Session.objects.create_session(name=name, project=project, chart='lab', settings=prefs)
            from .helpers import create_session_resources

            print("trying to create resources")
            retval = create_session_resources(request, user, session, prefs, project)
            if retval:
                print("saving session!")
                project.save()
                session.save()
                return HttpResponseRedirect(
                    reverse('labs:index', kwargs={'user': request.user, 'project': str(project.slug)}))

    return HttpResponseRedirect(
        reverse('labs:index', kwargs={'user': request.user, 'project': str(project.slug)}))
Ejemplo n.º 11
0
def pre_save_labs(sender, instance, using, **kwargs):

    instance.slug = slugify(instance.name)

    RELEASE_NAME = str(instance.slug)
    HOST = settings.DOMAIN
    URL = 'https://'+RELEASE_NAME+'.'+HOST
    user = instance.lab_session_owner.username
    client_id, client_secret = keylib.keycloak_setup_base_client(URL, RELEASE_NAME, user, ['owner'], ['owner'])
    
    instance.keycloak_client_id = client_id
    instance.appname = '{}-{}-lab'.format(instance.slug, instance.project.slug)
    skip_tls = 0
    if not settings.OIDC_VERIFY_SSL:
        skip_tls = 1
        print("WARNING: Skipping TLS verify.")
    parameters = {'release': RELEASE_NAME,
                  'chart': 'lab',
                  'global.domain': settings.DOMAIN,
                  'project.name': instance.project.slug,
                  'appname': instance.appname,
                  'gatekeeper.realm': settings.KC_REALM,
                  'gatekeeper.client_secret': client_secret,
                  'gatekeeper.client_id': client_id,
                  'gatekeeper.auth_endpoint': settings.OIDC_OP_REALM_AUTH,
                  'gatekeeper.skip_tls': str(skip_tls)
                  }

    ingress_secret_name = 'prod-ingress'
    try:
        ingress_secret_name = settings.LABS['ingress']['secretName']
    except:
        pass
    
    project = instance.project
    minio_keys = get_minio_keys(project)
    decrypted_key = minio_keys['project_key']
    decrypted_secret = minio_keys['project_secret']

    settings_file = ProjectSerializer(project)

    settings_file = JSONRenderer().render(settings_file.data)
    settings_file = settings_file.decode('utf-8')

    settings_file = json.loads(settings_file)
    settings_file = yaml.dump(settings_file)

    user_config_file = create_user_settings(user)
    user_config_file = yaml.dump(json.loads(user_config_file))

    flavor = Flavor.objects.filter(slug=instance.flavor_slug).first()
    environment = Environment.objects.filter(slug=instance.environment_slug).first()

    prefs = {'namespace': settings.NAMESPACE,
              'labs.resources.requests.cpu': str(flavor.cpu),
              'labs.resources.limits.cpu': str(flavor.cpu),
              'labs.resources.requests.memory': str(flavor.mem),
              'labs.resources.limits.memory': str(flavor.mem),
              'labs.resources.requests.gpu': str(flavor.gpu),
              'labs.resources.limits.gpu': str(flavor.gpu),
              'labs.gpu.enabled': str("true" if flavor.gpu else "false"),
              'labs.image': environment.image,
              'ingress.secretName': ingress_secret_name,
              'minio.access_key': decrypted_key,
              'minio.secret_key': decrypted_secret,
              'settings_file': settings_file,
              'user_settings_file': user_config_file,
              'project.slug': project.slug
              }
    
    parameters.update(prefs)
    print(parameters)
    helmchart = HelmResource(name=RELEASE_NAME,
                             namespace='Default',
                             chart='lab',
                             params=parameters,
                             username=user)
    helmchart.save()
    instance.helmchart = helmchart

    l = ProjectLog(project=project, module='LA', headline='Lab Session',
                               description='A new Lab Session {name} has been created'.format(name=RELEASE_NAME))
    l.save()