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())
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())
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()
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())
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)
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()
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())
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
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()
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)}))
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()