Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

First set of fixes to revive Django-based GUI code #695

6 changes: 3 additions & 3 deletions docker/nwm_gui/app_server/entrypoint.sh
Original file line number Diff line number Diff line change
Expand Up @@ -28,13 +28,13 @@ echo "Starting dmod app"
#python manage.py migrate
#########

# Execute the migration scripts on the designated database
#python manage.py migrate

#Extract the DB secrets into correct ENV variables
POSTGRES_SECRET_FILE="/run/secrets/${DOCKER_SECRET_POSTGRES_PASS:?}"
export SQL_PASSWORD="$(cat ${POSTGRES_SECRET_FILE})"

# Execute the migration scripts on the designated database
python manage.py migrate

# Handle for debugging when appropriate
if [ "$(echo "${PYCHARM_REMOTE_DEBUG_ACTIVE:-false}" | tr '[:upper:]' '[:lower:]' | tr -d '[:space:]')" == "true" ]; then
# Set the timeout to longer when debugging
Expand Down
11 changes: 6 additions & 5 deletions python/gui/MaaS/cbv/DMODProxy.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,8 +11,9 @@
import logging
logger = logging.getLogger("gui_log")

from dmod.communication import Distribution, get_available_models, get_available_outputs, get_request, get_parameters, \
NWMRequestJsonValidator, NWMRequest, ExternalRequest, ExternalRequestResponse, ModelExecRequestClient, Scalar, MessageEventType
from dmod.communication import (Distribution, get_available_models, get_available_outputs, get_request, get_parameters,
NWMRequestJsonValidator, NWMRequest, ExternalRequest, ExternalRequestClient,
ExternalRequestResponse, Scalar, MessageEventType)
from pathlib import Path
from typing import List, Optional, Tuple, Type

Expand Down Expand Up @@ -200,7 +201,7 @@ def maas_request(self) -> ExternalRequest:
return self._maas_request


class PostFormRequestClient(ModelExecRequestClient):
class PostFormRequestClient(ExternalRequestClient):
"""
A client for websocket interaction with the MaaS request handler as initiated by a POST form HTTP request.
"""
Expand Down Expand Up @@ -251,15 +252,15 @@ def _acquire_session_info(self, use_current_values: bool = True, force_new: bool
return self._session_id and self._session_secret and self._session_created
else:
logger.info("Session from {}: force_new={}".format(self.__class__.__name__, force_new))
tmp = self._acquire_new_session()
tmp = self._auth_client._acquire_session()
logger.info("Session Info Return: {}".format(tmp))
return tmp

def _init_maas_job_request(self):
pass

def generate_request(self, form_proc_class: Type[RequestFormProcessor]) -> ExternalRequest:
self.form_proc = form_proc_class(post_request=self.http_request, maas_secret=self.session_secret)
self.form_proc = form_proc_class(post_request=self.http_request, maas_secret=self._auth_client._session_secret)
return self.form_proc.maas_request

@property
Expand Down
40 changes: 21 additions & 19 deletions python/gui/MaaS/cbv/EditView.py
Original file line number Diff line number Diff line change
Expand Up @@ -42,30 +42,32 @@ def humanize(words: str) -> str:

models = list(communication.get_available_models().keys())
domains = ['example-domain-A', 'example-domain-B'] #FIXME map this from supported domains
outputs = list()
distribution_types = list()

# Create a mapping between each output type and a friendly representation of it
for output in maas_request.get_available_outputs():
output_definition = dict()
output_definition['name'] = humanize(output)
output_definition['value'] = output
outputs.append(output_definition)

# Create a mapping between each distribution type and a friendly representation of it
for distribution_type in maas_request.get_distribution_types():
type_definition = dict()
type_definition['name'] = humanize(distribution_type)
type_definition['value'] = distribution_type
distribution_types.append(type_definition)
#outputs = list()
#distribution_types = list()

### Note that these are now broken, and also probably no longer applicable
#
# # Create a mapping between each output type and a friendly representation of it
# for output in maas_request.get_available_outputs():
# output_definition = dict()
# output_definition['name'] = humanize(output)
# output_definition['value'] = output
# outputs.append(output_definition)
#
# # Create a mapping between each distribution type and a friendly representation of it
# for distribution_type in maas_request.get_distribution_types():
# type_definition = dict()
# type_definition['name'] = humanize(distribution_type)
# type_definition['value'] = distribution_type
# distribution_types.append(type_definition)

# Package everything up to be rendered for the client
payload = {
'models': models,
'domains': domains,
'outputs': outputs,
'parameters': maas_request.get_parameters(),
'distribution_types': distribution_types,
#'outputs': outputs,
#'parameters': maas_request.get_parameters(),
#'distribution_types': distribution_types,
'errors': errors,
'info': info,
'warnings': warnings
Expand Down
8 changes: 4 additions & 4 deletions python/gui/MaaS/client.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@

from dmod.communication import ExternalRequest
from dmod.communication import ExternalRequestResponse
from dmod.communication import ModelExecRequestClient
from dmod.communication import ExternalRequestClient

from . import utilities
from .processors.processor import BaseProcessor

logger = logging.getLogger("gui_log")


class JobRequestClient(ModelExecRequestClient):
class JobRequestClient(ExternalRequestClient):
"""
A client for websocket interaction with the MaaS request handler, specifically for performing a job request based on
details provided in a particular HTTP POST request (i.e., with form info on the parameters of the job execution).
Expand All @@ -36,7 +36,7 @@ def __init__(
if ssl_dir is None:
ssl_dir = Path(__file__).resolve().parent.parent.parent.joinpath('ssl')
ssl_dir = Path('/usr/maas_portal/ssl') #Fixme
logger.debug("endpoing_uri: {}".format(endpoint_uri))
logger.debug("endpoint_uri: {}".format(endpoint_uri))
super().__init__(endpoint_uri=endpoint_uri, ssl_directory=ssl_dir)
self._processor = processor
self._cookies = None
Expand Down Expand Up @@ -74,7 +74,7 @@ def _acquire_session_info(self, use_current_values: bool = True, force_new: bool
return self._session_id and self._session_secret and self._session_created
else:
logger.info("Session from JobRequestClient: force_new={}".format(force_new))
tmp = self._acquire_new_session()
tmp = self._auth_client._acquire_session()
logger.info("Session Info Return: {}".format(tmp))
return tmp

Expand Down
6 changes: 3 additions & 3 deletions python/gui/MaaS/migrations/0001_initial.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,9 @@ class Migration(migrations.Migration):
def create_superuser(apps, schema_editor):
from django.contrib.auth.models import User

SU_NAME = os.environ.get('DMOD_SU_NAME')
SU_EMAIL = os.environ.get('DMOD_SU_EMAIL')
SU_PASSWORD = os.environ.get('DMOD_SU_PASSWORD')
SU_NAME = os.environ.get('DMOD_SU_NAME', "dmod_admin")
SU_EMAIL = os.environ.get('DMOD_SU_EMAIL', "[email protected]")
SU_PASSWORD = os.environ.get('DMOD_SU_PASSWORD', f"{SU_NAME}{os.environ.get('SQL_PASSWORD')}")

superuser = User.objects.create_superuser(
username=SU_NAME,
Expand Down
4 changes: 2 additions & 2 deletions python/gui/MaaS/templates/base.html
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
{% load static %}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>{{ title|default:"Distributed Model on Demand" }}</title>
{% load static %}
<link rel="shortcut icon" type="image/png" href="{% static 'common/img/favicon.png' %}"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<link rel="stylesheet" href="{% static 'common/css/base.css' %}"/>
<link rel="stylesheet" href="{% static 'css/master.css' %}"/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

be careful - this is mixing and matching resources. css/master.css is the stylesheet for the root level master.html template. common/css/base.css is the stylesheet for base.html.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think in this case that is what I wanted to do here, though I appreciate the cautious eye. I felt like we should start from the same styling throughout, so I was trying to move to that in this template base. That said, I could be talked into deferring on this if we think it's problematic to do it until it's also time to clean up some of the redundant files (which I was avoiding at the moment).

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You might be better off changing to base template to master.html on the other templates rather than altering what css base.html is referencing. I haven't made the switch, so it might be fine, but both css files and templates are making assumptions based on what page elements are present.

You have the right idea, though. Switching what template you're inheriting from might work better here, though.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, if I'm remembering correctly, I started off by switching the base template, but moving from base.html caused some problem with pages' scripts. Swapping in the CSS change ended up being easier to follow along with and appeared to have fewer immediate side effects than carefully tweaking what seemed to be a good chunk of the Javascript setup (and hoping there wasn't something else needed after that).

Regardless, there isn't going to be a clean fix until we overhaul a good chunk of things. My goal at moment is to be minimalist and do just enough to get things working again, albeit with some attention paid to not laying any seriously traps for us to fall into later.

{% block styles %}{% endblock styles %}
<script>
var startup_scripts = [];
Expand Down
4 changes: 4 additions & 0 deletions python/gui/MaaS/templates/maas/configuration/ngen.html
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,10 @@
<link rel="stylesheet" href="{% static 'maas/css/configuration/ngen.css' %}"/>
{% endblock styles %}

{% block bannercontent %}
<h1>Configuration</h1>
{% endblock bannercontent %}

{% block content %}
<div id="content" style="padding: 5px;">
<form id="configuration-wrapper" method="post" action="{% url 'MaaS:execute' %}">
Expand Down
6 changes: 3 additions & 3 deletions python/gui/MaaS/urls.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,12 @@
from maas_experiment import application_values

from django.urls import re_path
#from .cbv.EditView import EditView
from .cbv.EditView import EditView
from .cbv.MapView import MapView, Fabrics, FabricNames, FabricTypes, ConnectedFeatures
from .cbv.evaluation import ReadyListenEvaluation
from .cbv.evaluation import EvaluationListing
from .cbv.configuration import CreateConfiguration
#from .cbv.execution import Execute
from .cbv.execution import Execute
from .cbv.crosswalk import Crosswalk
from .cbv.prototyping import RuntimePrototype

Expand All @@ -22,7 +22,7 @@
re_path(r'fabric/types$', FabricTypes.as_view(), name='fabric-types'),
re_path(r'fabric/(?P<fabric>[a-zA-Z0-9_-]+(\s\([a-zA-Z0-9_-]+\))*)?', Fabrics.as_view(), name='fabrics'),
re_path(r'config/edit', CreateConfiguration.as_view(), name='create_config'),
#re_path(r'config/execute', Execute.as_view(), name='execute'),
re_path(r'config/execute', Execute.as_view(), name='execute'),
re_path(r'crosswalk/(?P<crosswalk>[a-zA-Z0-9_-]+(\s\([a-zA-Z0-9_-]+\))*)?', Crosswalk.as_view(), name='crosswalk')
]

Expand Down
1 change: 1 addition & 0 deletions python/gui/dependencies.txt
Original file line number Diff line number Diff line change
Expand Up @@ -18,3 +18,4 @@ channels-redis
djangorestframework
psycopg2-binary # TODO: get source package in future. Note that psycopg2 cannot be used on Mac; psycopg2-binary must be used
numpy
daphne
2 changes: 2 additions & 0 deletions python/gui/maas_experiment/application_values.py
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,8 @@ def get_full_localtimezone():
BASE_DIRECTORY = Path(__file__).resolve().parent.parent
"""The path to the base directory of the service"""

STATIC_ROOT = BASE_DIRECTORY / "static"

STATIC_RESOURCE_DIRECTORY = BASE_DIRECTORY / "static" / "resources"

APPLICATION_NAME = os.environ.get("APPLICATION_NAME", "Model as a Service")
Expand Down
1 change: 0 additions & 1 deletion python/gui/maas_experiment/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -134,5 +134,4 @@

STATIC_URL = '/static/'
STATICFILES_DIRS = [
BASE_DIRECTORY / "static"
]
2 changes: 1 addition & 1 deletion python/lib/communication/dmod/communication/_version.py
Original file line number Diff line number Diff line change
@@ -1 +1 @@
__version__ = '0.21.0'
__version__ = '0.21.1'
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
from .model_exec_request import ModelExecRequest, get_available_models
from deprecated import deprecated


@deprecated("Avoid broken util functions not updated for recent message changes")
def get_available_outputs() -> set:
"""
:return: A collection of all valid outputs across any model
Expand All @@ -13,6 +15,7 @@ def get_available_outputs() -> set:
return all_outputs


@deprecated("Avoid broken util functions not updated for recent message changes")
def get_distribution_types() -> set:
"""
:return: The distribution types used across any model
Expand All @@ -25,6 +28,7 @@ def get_distribution_types() -> set:
return all_types


@deprecated("Avoid broken util functions not updated for recent message changes")
def get_parameters() -> dict:
"""
Maps each model to the natural and human readable forms of all of their parameters
Expand Down
Loading