async def module_info(request): module = request.match_info["module"].lower() if not await request.app.cache.modules.exists(module): flash.flash(request, ("danger", f"Module does not exist: {module}.")) return web.HTTPFound("/modules") module_meta = await request.app.cache.modules.get(module) request.context["modulename"] = module request.context["module_meta"] = copy.deepcopy(module_meta) description = module_meta.get("description") if description: description = "\n".join(description) else: description = "No description provided." description = markdown.markdown(description) request.context["module_meta"]["description"] = description request.context["breadcrumbs"] = [ ("Home", False, "/"), ("Modules", False, "/modules"), # FIXME(aloga): use url (module, True, f"/modules/{module}"), # FIXME(aloga): use url ] return request.context
async def get_deployment_template(request): request.context["deployments"] = [] uuid = request.match_info['uuid'] request.context["breadcrumbs"] = [ ("Home", False, "/"), ("Deployments", False, "/deployments"), # FIXME(aloga): use url (uuid, False, f"/deployments/{uuid}"), # FIXME(aloga): use url ("template", True, f"/deployments/{uuid}/template"), # FIXME(aloga) ] cli = await orchestrator.get_client(CONF.orchestrator.url, request) try: template = cli.deployments.get_template(uuid).template request.context["template"] = template except orpy.exceptions.ClientException as e: flash.flash( request, ("danger", f"Error retrieving deployment {uuid} template: " f"{e.message}"), ) return web.HTTPFound("/deployments") else: return request.context
async def create_module_training(request): form_data = await request.post() LOG.debug(f"Received form data: {form_data}") tosca_template = form_data.get('template') LOG.debug(f"Selected template file: {tosca_template}") if not await request.app.cache.tosca_templates.exists(tosca_template): flash.flash( request, ("danger", f"TOSCA template does not exist: {tosca_template}.")) return web.HTTPFound("/modules") aux = await request.app.cache.tosca_templates.get(tosca_template) template = aux["original tosca"] params = {} if 'extra_opts.keepLastAttempt' in form_data: params["keepLastAttempt"] = "true" else: params["keepLastAttempt"] = "false" if form_data['extra_opts.schedtype'] == "manual": if sla := form_data.get('extra_opts.selectedSLA', None): LOG.debug(f"Adding SLA to deployment request {sla}") template['topology_template']['policies'] = [{ "deploy_on_specific_site": { "type": "tosca.policies.indigo.SlaPlacement", "properties": { "sla_id": sla } } }] else: flash.flash(request, ("danger", "SLA does not exist."))
async def delete_deployment(request): uuid = request.match_info['uuid'] cli = await orchestrator.get_client(CONF.orchestrator.url, request) try: cli.deployments.delete(uuid) except orpy.exceptions.ClientException as e: flash.flash( request, ("danger", f"Error deleting deployment {uuid}: {e.message}")) finally: return web.HTTPFound("/deployments")
async def error_middleware(request, handler): try: response = await handler(request) if response.status != 404: return response message = response.message except web.HTTPServerError as e: LOG.exception(e) message = "Internal server error. " except web.HTTPException as e: message = f"Error {e.status_code}: {e.reason}" aiohttp_session_flash.flash(request, ("danger", message)) response = web.HTTPFound("/") return response
async def middleware_handler(request): try: response = await handler(request) if response.status in [400, 403, 404, 405]: if response.status == 400: message = "Bad request" elif response.status == 403: message = "Forbidden" elif response.status == 404: message = "Not found" else: message = "Method not allowed" flash(request, ("danger", message)) return render_template("error.html", request, {}) return response except web.HTTPException as e: flash(request, ("danger", str(e))) return render_template("error.html", request, {})
async def get_deployments(request): request.context["deployments"] = [] cli = await orchestrator.get_client(CONF.orchestrator.url, request) request.context["breadcrumbs"] = [ ("Home", False, "/"), ("Deployments", True, "/deployments"), # FIXME(aloga): use url ] try: request.context["deployments"] = cli.deployments.list() except orpy.exceptions.ClientException as e: flash.flash( request, ("danger", f"Error retrieving deployment list: {e.message}"), ) finally: return request.context
async def show_deployment_history(request): uuid = request.match_info['uuid'] request.context["breadcrumbs"] = [ ("Home", False, "/"), ("Deployments", False, "/deployments"), # FIXME(aloga): use url (uuid, False, f"/deployments/{uuid}"), # FIXME(aloga): use url ("history", True, f"/deployments/{uuid}/history"), # FIXME(aloga) ] cli = await orchestrator.get_client(CONF.orchestrator.url, request) try: deployment = cli.deployments.show(uuid) except orpy.exceptions.ClientException as e: flash.flash( request, ("danger", f'Error getting deployment {uuid}: {e.message}')) return web.HTTPFound("/deployments") # Check if deployment is still in 'create_in_progress' if 'deepaas_endpoint' not in deployment.outputs: flash.flash(request, ("warning", 'Wait until creation is completed before you access the ' 'training history.')) return web.HTTPFound("/deployments") session = aiohttp.ClientSession() # Check if deployment has DEEPaaS V2 deepaas_url = deployment.outputs['deepaas_endpoint'] try: async with session.get(deepaas_url, raise_for_status=True) as r: data = await r.json() versions = data['versions'] if 'v2' not in [v['id'] for v in versions]: raise Exception except Exception: flash.flash(request, ("warning", "You need to be running DEEPaaS V2 inside the deployment " "to be able to access the training history.")) return web.HTTPFound("/deployments") # Get info async with session.get(deepaas_url + '/v2/models', raise_for_status=False) as r: r = await r.json() training_info = {} for model in r['models']: async with session.get(f'{deepaas_url}/v2/models/{model["id"]}/train/', raise_for_status=False) as r: training_info[model['id']] = await r.json() request.context["deployment"] = deployment request.context["training_info"] = training_info return request.context
async def delete_training(request): dep_uuid = request.match_info["uuid"] model = request.match_info["model"] training_uuid = request.match_info["training_uuid"] cli = await orchestrator.get_client(CONF.orchestrator.url, request) try: deployment = cli.deployments.show(dep_uuid) except orpy.exceptions.ClientException as e: flash.flash( request, ("danger", f'Error getting deployment {dep_uuid}: {e.message}')) return web.HTTPFound("/deployments") # Check if deployment is still in 'create_in_progress' if 'deepaas_endpoint' not in deployment.outputs: flash.flash(request, ("warning", 'Wait until creation is completed before you access the ' 'training history.')) return web.HTTPFound(f"/deployments/{dep_uuid}/history") # Check if deployment has DEEPaaS V2 deepaas_url = deployment.outputs['deepaas_endpoint'] training_url = f"{deepaas_url}/v2/models/{model}/train/{training_uuid}" session = aiohttp.ClientSession() try: async with session.delete(training_url, raise_for_status=True) as r: if r.status not in [200, 201]: raise Exception except Exception as e: flash.flash( request, ("warning", f"Could not delete training!! (reason: {e.message})")) finally: return web.HTTPFound(f"/deployments/{dep_uuid}/history")
async def configure_module_training(request): module = request.match_info["module"].lower() if not await request.app.cache.modules.exists(module): flash.flash(request, ("danger", f"Module does not exist: {module}.")) return web.HTTPFound("/modules") request.context["selected_module"] = module module_meta = await request.app.cache.modules.get(module) selected_tosca = request.query.get( "selected_tosca", list(module_meta["tosca_templates"].keys())[0]) template_name = module_meta["tosca_templates"][selected_tosca] hardware_configuration = request.query.get("hardware_configuration", "CPU").lower() docker_tag = request.query.get("docker_tag", module_meta["docker_tags"][0]).lower() run_command = request.query.get("run_command", "DEEPaaS") general_configuration = { "tosca_templates": { "available": module_meta["tosca_templates"].keys(), "selected": selected_tosca, }, "docker_tags": { "available": module_meta["docker_tags"], "selected": docker_tag, }, "hardware_configuration": { "available": ["CPU", "GPU"], "selected": hardware_configuration, }, "run_command": { "available": ["DEEPaaS", "JupyterLab", "Custom command"], "selected": run_command, }, } tosca_template = module_meta["tosca_templates"].get(selected_tosca) if tosca_template is None: flash.flash( request, ("danger", f"TOSCA template does not exist: {tosca_template}.")) return web.HTTPFound("/modules") aux = await request.app.cache.tosca_templates.get(tosca_template) inputs = copy.deepcopy(aux["inputs"]) inputs['docker_image'].setdefault( 'default', module_meta['sources']['docker_registry_repo']) docker_tags = module_meta['docker_tags'] if docker_tag not in docker_tags: docker_tag = docker_tags[0] if run_command == 'deepaas': inputs['run_command']['default'] = 'deepaas-run --listen-ip=0.0.0.0' if hardware_configuration == 'gpu': inputs['run_command']['default'] += ' --listen-port=$PORT0' elif run_command == 'jupyterlab': flash.flash(request, ("warning", 'Remember to set a Jupyter password.')) inputs['run_command']['default'] = ( '/srv/.jupyter/run_jupyter.sh --allow-root') if hardware_configuration == 'gpu': inputs['run_command']['default'] = ( "jupyterPORT=$PORT2 " + inputs['run_command']['default']) if hardware_configuration == 'cpu': inputs['num_cpus']['default'] = 1 inputs['num_gpus']['default'] = 0 inputs['run_command']['default'] = ("monitorPORT=6006 " + inputs['run_command']['default']) elif hardware_configuration == 'gpu': inputs['num_cpus']['default'] = 1 inputs['num_gpus']['default'] = 1 inputs['run_command']['default'] = ("monitorPORT=$PORT1 " + inputs['run_command']['default']) # FIXME(aloga): improve conditions here if run_command == "custom command": inputs['run_command']['default'] = '' inputs['docker_image']['default'] += ':{}'.format(docker_tag) grouped = { "docker": {}, "jupyter": {}, "storage": {}, "hardware": {}, "other": {}, } for k, v in inputs.items(): if k.startswith("docker_"): grouped["docker"][k] = v elif k.startswith("jupyter_"): grouped["jupyter"][k] = v elif any([ k.startswith("rclone_"), k.startswith("onedata_"), k.startswith("oneclient_"), k == "app_in_out_base_dir" ]): grouped["storage"][k] = v elif k in ["mem_size", "num_cpus", "num_gpus"]: grouped["hardware"][k] = v else: grouped["other"][k] = v template_meta = { "inputs": inputs, "grouped": grouped, } request.context["general_configuration"] = general_configuration request.context["template_meta"] = template_meta request.context["template_name"] = template_name request.context["slas"] = request.app.slas request.context["module_meta"] = module_meta request.context["breadcrumbs"] = [ ("Home", False, "/"), ("Modules", False, "/modules"), # FIXME(aloga): use url (module, False, f"/modules/{module}"), # FIXME(aloga): use url ("train", True, f"/modules/{module}/train"), # FIXME(aloga): use url ] return request.context
async def save_array(request): flash(request, ["This", "works", "too"]) return web.Response(body=b'OK')
async def save_redirect(request): flash(request, "Redirect") raise web.HTTPFound('/')
async def save(request): flash(request, "Hello") return web.Response(body=b'OK')
async def post(self): form = self.RecordingForm(await self.request.post()) form.adapter.choices = self.adapters_choices form.channel.choices = self.channels_choices if form.data["submit"]: if form.validate(): data = remove_special_data(form.data) error = False begin_date = data["begin_date"] if begin_date is None: immediate = True begin_date = datetime.now() else: immediate = False if begin_date <= datetime.now(): error = True message = _( "La date de début doit être dans le futur.") end_date = data["end_date"] if begin_date >= end_date: error = True message = _( "La date de début doit être antérieure à la date de fin." ) duration = (end_date - begin_date).total_seconds() if duration > int(self.recorder.max_duration): error = True message = _( "La durée de l'enregistrement est trop longue.") if error: flash(self.request, ("danger", message)) else: adapter = data["adapter"] shutdown = data["shutdown"] channel = self.channels_choices[data["channel"]][1] program_name = data["program_name"] self.recorder.record(adapter, channel, program_name, immediate, begin_date, end_date, duration, shutdown) message = _("L'enregistrement de \"{}\" est programmé " "pour le {} à {} pendant {} minutes de \"{}\" " "sur l'enregistreur {}").format( program_name, begin_date.strftime("%d/%m/%Y"), begin_date.strftime("%H:%M"), round(duration / 60), channel, adapter) flash(self.request, ("info", message)) return web.HTTPFound( self.request.app.router["index"].url_for()) else: flash(self.request, ("danger", _("Le formulaire contient des erreurs."))) form2 = self.AwakeningForm(await self.request.post()) if form2.data["submit2"]: if form2.validate(): data = remove_special_data(form2.data) awakening_date = data["awakening_date"] self.wakeup.add_awakening(awakening_date) return web.HTTPFound( self.request.app.router["index"].url_for()) else: flash(self.request, ("danger", _("Le formulaire contient des erreurs."))) form3 = self.ToolsForm(await self.request.post()) if form3.data["submit3"]: if form3.validate(): data = remove_special_data(form3.data) if data["shutdown"]: halt() else: flash(self.request, ("danger", _("Le formulaire contient des erreurs."))) return { "form": form, "recordings": self.recorder.get_recordings(), "form2": form2, "awakenings": self.wakeup.get_awakenings(), "form3": form3 }