Skip to content

Commit 145cebd

Browse files
committed
Add url to send a simulation to the eesyplanserver
1 parent b0179db commit 145cebd

4 files changed

Lines changed: 155 additions & 0 deletions

File tree

app/epa/settings.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -215,6 +215,10 @@
215215
MVS_SA_POST_URL = f"{MVS_API_HOST}/sendjson/openplan/sensitivity-analysis"
216216
MVS_SA_GET_URL = f"{MVS_API_HOST}/check-sensitivity-analysis/"
217217

218+
EZP_API_HOST = env("EZP_API_HOST", default="")
219+
EZP_POST_URL = f"{EZP_API_HOST}/sendjson/"
220+
EZP_GET_URL = f"{EZP_API_HOST}/check/"
221+
218222
# Allow iframes to show in page
219223
X_FRAME_OPTIONS = "SAMEORIGIN"
220224

app/projects/requests.py

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@
1010
MVS_GET_URL,
1111
MVS_SA_POST_URL,
1212
MVS_SA_GET_URL,
13+
EZP_POST_URL,
14+
EZP_GET_URL,
1315
)
1416
from dashboard.models import (
1517
FancyResults,
@@ -24,6 +26,83 @@
2426
logger = logging.getLogger(__name__)
2527

2628

29+
def ezp_simulation_request(data: str):
30+
headers = {"content-type": "application/json"}
31+
payload = data
32+
33+
try:
34+
response = requests.post(
35+
EZP_POST_URL,
36+
data=payload,
37+
headers=headers,
38+
proxies=PROXY_CONFIG,
39+
verify=False,
40+
)
41+
42+
# If the response was successful, no Exception will be raised
43+
response.raise_for_status()
44+
except requests.HTTPError as http_err:
45+
logger.error(f"HTTP error occurred: {http_err}")
46+
return None
47+
except Exception as err:
48+
logger.error(f"Other error occurred: {err}")
49+
return None
50+
else:
51+
logger.info("The simulation was sent successfully to MVS API.")
52+
return json.loads(response.text)
53+
54+
55+
def ezp_simulation_check_status(token):
56+
try:
57+
response = requests.get(EZP_GET_URL + token, proxies=PROXY_CONFIG, verify=False)
58+
response.raise_for_status()
59+
except requests.HTTPError as http_err:
60+
logger.error(f"HTTP error occurred: {http_err}")
61+
return None
62+
except Exception as err:
63+
logger.error(f"Other error occurred: {err}")
64+
return None
65+
else:
66+
logger.info("Success!")
67+
return json.loads(response.text)
68+
69+
70+
def fetch_ezp_simulation_results(simulation):
71+
if simulation.status == PENDING:
72+
response = ezp_simulation_check_status(token=simulation.mvs_token)
73+
try:
74+
simulation.status = response["status"]
75+
simulation.errors = (
76+
json.dumps(response["results"][ERROR])
77+
if simulation.status == ERROR
78+
else None
79+
)
80+
simulation.results = (
81+
response["results"] if simulation.status == DONE else None
82+
)
83+
84+
# simulation.mvs_version = response["mvs_version"]
85+
logger.info(f"The simulation {simulation.id} is finished")
86+
except:
87+
simulation.status = ERROR
88+
simulation.results = None
89+
90+
simulation.elapsed_seconds = (datetime.now() - simulation.start_date).seconds
91+
92+
# Cancel simulation if it has been going on > 48h
93+
max_simulation_seconds = 48 * 60 * 60
94+
if simulation.elapsed_seconds > max_simulation_seconds:
95+
simulation.status = ERROR
96+
simulation.results = None
97+
98+
simulation.end_date = (
99+
datetime.now() if simulation.status in [ERROR, DONE] else None
100+
)
101+
simulation.save()
102+
103+
return simulation.status != PENDING
104+
105+
27106
def mvs_simulation_request(data: dict):
28107
headers = {"content-type": "application/json"}
29108
payload = json.dumps(data)

app/projects/urls.py

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -265,6 +265,11 @@
265265
request_mvs_simulation,
266266
name="request_mvs_simulation",
267267
),
268+
path(
269+
"topology/ezp_simulation/<int:scen_id>",
270+
request_ezp_simulation,
271+
name="request_ezp_simulation",
272+
),
268273
path(
269274
"topology/update_simulation_rating/",
270275
update_simulation_rating,

app/projects/views.py

Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,8 @@
3535
from .requests import (
3636
mvs_simulation_request,
3737
fetch_mvs_simulation_results,
38+
ezp_simulation_request,
39+
fetch_ezp_simulation_results,
3840
mvs_sensitivity_analysis_request,
3941
fetch_mvs_sa_results,
4042
parse_mvs_results,
@@ -2047,6 +2049,71 @@ def request_mvs_simulation(request, scen_id=0):
20472049
return answer
20482050

20492051

2052+
@login_required
2053+
@require_http_methods(["GET", "POST"])
2054+
def request_ezp_simulation(request, scen_id=0):
2055+
if scen_id == 0:
2056+
answer = JsonResponse(
2057+
{"status": "error", "error": "No scenario id provided"},
2058+
status=500,
2059+
content_type="application/json",
2060+
)
2061+
# Load scenario
2062+
scenario = Scenario.objects.get(pk=scen_id)
2063+
json_dp = scenario_export_as_jsonified_datapackage(request, scen_id)
2064+
2065+
# if request.method == "POST":
2066+
# output_lp_file = request.POST.get("output_lp_file", None)
2067+
# if output_lp_file == "on":
2068+
# data_clean["simulation_settings"]["output_lp_file"] = "true"
2069+
2070+
# Make simulation request to eesyplan server
2071+
results = ezp_simulation_request(json_dp.text)
2072+
2073+
if results is None:
2074+
error_msg = "Could not communicate with the simulation server."
2075+
logger.error(error_msg)
2076+
messages.error(request, error_msg)
2077+
# TODO redirect to prefilled feedback form / bug form
2078+
answer = JsonResponse(
2079+
{"status": "error", "error": error_msg},
2080+
status=407,
2081+
content_type="application/json",
2082+
)
2083+
else:
2084+
# delete existing simulation
2085+
Simulation.objects.filter(scenario_id=scen_id).delete()
2086+
2087+
# Create empty Simulation model object
2088+
simulation = Simulation(start_date=datetime.datetime.now(), scenario_id=scen_id)
2089+
2090+
simulation.mvs_token = (
2091+
results["id"] if results["id"] else None
2092+
) # TODO change token
2093+
2094+
if "status" in results.keys() and (
2095+
results["status"] == DONE or results["status"] == ERROR
2096+
):
2097+
simulation.status = results["status"]
2098+
simulation.results = results["results"]
2099+
simulation.end_date = datetime.datetime.now()
2100+
else: # PENDING
2101+
simulation.status = results["status"]
2102+
# create a task which will update simulation status
2103+
# create_or_delete_simulation_scheduler(mvs_token=simulation.mvs_token)
2104+
2105+
simulation.elapsed_seconds = (
2106+
datetime.datetime.now() - simulation.start_date
2107+
).seconds
2108+
simulation.save()
2109+
2110+
answer = HttpResponseRedirect(
2111+
reverse("scenario_review", args=[scenario.project.id, scen_id])
2112+
)
2113+
2114+
return answer
2115+
2116+
20502117
@json_view
20512118
@login_required
20522119
@require_http_methods(["POST"])

0 commit comments

Comments
 (0)