-
Notifications
You must be signed in to change notification settings - Fork 2
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge branch 'master' of github.com:mila-iqia/clockwork into update-u…
…ser-page
- Loading branch information
Showing
51 changed files
with
8,127 additions
and
6,324 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
BSD License | ||
|
||
Copyright (c) 2023, Mila | ||
All rights reserved. | ||
|
||
Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met: | ||
|
||
* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer. | ||
* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution. | ||
* Neither the name of Mila nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission. | ||
|
||
THIS SOFTWARE IS PROVIDED BY MILA "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL MILA BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,78 @@ | ||
""" | ||
Browser routes dealing with the "cluster" entity | ||
""" | ||
import logging | ||
|
||
from flask import Blueprint, request | ||
from flask_login import current_user, login_required | ||
from flask_babel import gettext | ||
|
||
from clockwork_web.core.clusters_helper import get_all_clusters | ||
from clockwork_web.core.jobs_helper import get_jobs | ||
from clockwork_web.core.users_helper import ( | ||
render_template_with_user_settings, | ||
get_users, | ||
) | ||
|
||
flask_api = Blueprint("status", __name__) | ||
|
||
|
||
@flask_api.route("/") | ||
@login_required | ||
def route_status(): | ||
"""Display status about clusters available for connected user.""" | ||
logging.info( | ||
f"clockwork_web route: /clusters/status - current_user={current_user.mila_email_username}" | ||
) | ||
|
||
users = get_users() | ||
|
||
# Count users. | ||
nb_users = len(users) | ||
|
||
# Count enabled users. | ||
nb_enabled_users = sum( | ||
(1 for user in users if user["status"] == "enabled"), start=0 | ||
) | ||
|
||
# Count users that have a DRAC account. | ||
# User has a DRAC account if user dict contains a valid value for field "cc_account_username". | ||
nb_drac_users = sum( | ||
(1 for user in users if user.get("cc_account_username", None)), start=0 | ||
) | ||
|
||
# Collect clusters status: | ||
# - Count number of jobs per cluster. | ||
# - Get oldest and latest job modification dates in each cluster. | ||
D_all_clusters = get_all_clusters() | ||
clusters = {} | ||
for current_cluster_name in D_all_clusters: | ||
jobs, _ = get_jobs(cluster_names=[current_cluster_name]) | ||
job_dates = [ | ||
job["cw"]["last_slurm_update"] | ||
for job in jobs | ||
if "last_slurm_update" in job["cw"] | ||
] | ||
clusters[current_cluster_name] = { | ||
"display_order": D_all_clusters[current_cluster_name]["display_order"], | ||
"nb_jobs": len(jobs), | ||
} | ||
if job_dates: | ||
clusters[current_cluster_name]["job_dates"] = { | ||
"min": min(job_dates), | ||
"max": max(job_dates), | ||
} | ||
|
||
server_status = { | ||
"nb_users": nb_users, | ||
"nb_enabled_users": nb_enabled_users, | ||
"nb_drac_users": nb_drac_users, | ||
"clusters": clusters or None, | ||
} | ||
|
||
return render_template_with_user_settings( | ||
"status.html", | ||
server_status=server_status, | ||
mila_email_username=current_user.mila_email_username, | ||
previous_request_args={}, | ||
) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -2,6 +2,7 @@ | |
Helper functions related to the User entity and the users entries from the databas. | ||
""" | ||
|
||
from datetime import datetime, timedelta | ||
from flask_login import current_user | ||
from flask import render_template | ||
import json | ||
|
@@ -17,7 +18,7 @@ | |
string as valid_string, | ||
) | ||
from clockwork_web.core.clusters_helper import get_all_clusters, get_account_fields | ||
from clockwork_web.core.jobs_helper import get_jobs_properties_list_per_page | ||
from clockwork_web.core.jobs_helper import get_jobs_properties_list_per_page, get_jobs | ||
|
||
from clockwork_web.core.utils import ( | ||
get_available_date_formats, | ||
|
@@ -300,6 +301,19 @@ def get_users_one(mila_email_username): | |
return user | ||
|
||
|
||
def get_users(): | ||
""" | ||
Retrieve all users from the database. | ||
Returns: | ||
A list of dictionaries presenting users. | ||
""" | ||
# Retrieve the users collection from the database | ||
users_collection = get_db()["users"] | ||
users = users_collection.find({}) | ||
return list(users) | ||
|
||
|
||
def get_available_clusters_from_user_dict(D_user): | ||
""" | ||
Retrieve the clusters a user can access. | ||
|
@@ -567,5 +581,43 @@ def render_template_with_user_settings(template_name_or_list, **context): | |
|
||
# Send the clusters infos to the template | ||
context["clusters"] = get_all_clusters() | ||
# List clusters available for connected user, | ||
# or set an empty list for anon user. | ||
context["user_clusters"] = ( | ||
[] | ||
if current_user.mila_email_username == "[email protected]" | ||
else current_user.get_available_clusters() | ||
) | ||
|
||
# Get cluster status (if jobs are old and cluster has error). | ||
for cluster_name in context["clusters"]: | ||
# Default status values. | ||
jobs_are_old = False | ||
cluster_has_error = False | ||
|
||
# Check if jobs are old. | ||
jobs, _ = get_jobs(cluster_names=[cluster_name]) | ||
job_dates = [ | ||
job["cw"]["last_slurm_update"] | ||
for job in jobs | ||
if "last_slurm_update" in job["cw"] | ||
] | ||
if job_dates: | ||
most_recent_job_edition = max(job_dates) | ||
current_timestamp = datetime.now().timestamp() | ||
elapsed_time = timedelta( | ||
seconds=current_timestamp - most_recent_job_edition | ||
) | ||
# Let's say the latest jobs edition must not be older than 30 days ago. | ||
max_delay = timedelta(days=30) | ||
jobs_are_old = elapsed_time > max_delay | ||
|
||
# Cluster error cannot yet be checked, so | ||
# cluster_has_error is always False for now. | ||
|
||
context["clusters"][cluster_name]["status"] = { | ||
"jobs_are_old": jobs_are_old, | ||
"cluster_has_error": cluster_has_error, | ||
} | ||
|
||
return render_template(template_name_or_list, **context) |
Oops, something went wrong.