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

Egi brand v2 #624

Merged
merged 64 commits into from
Feb 27, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
64 commits
Select commit Hold shift + click to select a range
b8830fd
Show stats
micafer Mar 29, 2022
f8e76b9
Show stats
micafer Mar 29, 2022
e8a97e0
Show stats
micafer Mar 29, 2022
cf2341b
Show stats
micafer Mar 29, 2022
a3da808
Merge branch 'devel' into stats
micafer Mar 30, 2022
6bb4a66
Fix stats
micafer Mar 30, 2022
db74f65
Set init date to 1 year
micafer Mar 31, 2022
e927028
Set init date to 1 year
micafer Mar 31, 2022
760cc1b
Add cloud site filter
micafer Mar 31, 2022
60320d1
Add dynamic site filter
micafer Mar 31, 2022
980ff67
Add dynamic site filter
micafer Mar 31, 2022
d9be64e
fix style
micafer Mar 31, 2022
b60f14d
Add dynamic site filter
micafer Mar 31, 2022
f5d01e9
Add dynamic site filter
micafer Mar 31, 2022
e808932
Add dynamic site filter
micafer Mar 31, 2022
dea915a
Add dynamic site filter
micafer Mar 31, 2022
3c29f0c
Add dynamic site filter
micafer Mar 31, 2022
3ed2534
Add dynamic site filter
micafer Mar 31, 2022
6bb61fd
Add empty element at init and end date
micafer Apr 1, 2022
bb32e82
Improve code
micafer Apr 1, 2022
9cc7e3f
show active infras
micafer Apr 11, 2022
1e6e2ae
Merge pull request #286 from grycap/devel
micafer Apr 12, 2022
6da8e79
Improve performance
micafer May 2, 2022
ca62cc0
Update dockerfile
micafer May 6, 2022
e0e1667
Download big outputs
micafer May 6, 2022
7ccc063
Implements #288
micafer May 9, 2022
74698b2
Merge branch 'stats' of github.com:grycap/im-dashboard into stats
micafer May 9, 2022
669e960
Enable to add multiple ssh keys
micafer May 12, 2022
af785e6
Show Cloud provider in inf list
micafer May 12, 2022
fb39869
Fix error
micafer May 12, 2022
fa2afd0
Fix error
micafer May 12, 2022
656374c
Minor change
micafer May 12, 2022
6f19105
Minor change
micafer May 13, 2022
76c9545
Merge branch 'stats' of github.com:grycap/im-dashboard into stats
micafer May 13, 2022
c904660
Minor change
micafer May 13, 2022
5818fe9
Minor change
micafer May 13, 2022
a54b846
Merge pull request #568 from grycap/devel
micafer Aug 26, 2024
eeac635
Merge pull request #571 from grycap/devel
micafer Sep 2, 2024
1388a60
Merge pull request #573 from grycap/devel
micafer Sep 4, 2024
f091fc5
Merge pull request #575 from grycap/devel
micafer Sep 4, 2024
d5d341a
Implements: #578
micafer Sep 5, 2024
7a03354
Merge pull request #579 from grycap/devel
micafer Sep 5, 2024
99d8834
Add support to greater_than and less_than TOSCA constaints
micafer Oct 28, 2024
4d738c4
Merge pull request #582 from grycap/devel
micafer Oct 28, 2024
805878d
Implements #581
micafer Oct 28, 2024
191e7a7
Merge pull request #585 from grycap/devel
micafer Oct 28, 2024
c03bf4f
Implements #586
micafer Oct 28, 2024
7ff63c6
Update Werkzeug version
micafer Oct 28, 2024
1529465
Merge pull request #587 from grycap/devel
micafer Oct 28, 2024
4382ba2
Unable set float sizes
micafer Oct 28, 2024
c35d241
Maintain IM inf list order
micafer Oct 28, 2024
a1da3f5
Fix style
micafer Oct 28, 2024
7eab15c
Merge pull request #588 from grycap/devel
micafer Oct 28, 2024
543c5d8
Add volume type
micafer Oct 28, 2024
e25d2d4
Merge pull request #590 from grycap/devel
micafer Oct 28, 2024
44de867
merge master
micafer Oct 31, 2024
387580d
Fix order
micafer Oct 31, 2024
7c5be99
Fix style
micafer Oct 31, 2024
2160fae
Fix test
micafer Oct 31, 2024
c707610
Update chart js version
micafer Nov 4, 2024
c76fb46
Fix update button
micafer Jan 17, 2025
f5c7836
Update cryptography ver
micafer Feb 26, 2025
1b63c5b
merge stats
micafer Feb 27, 2025
1e2ea99
merge master
micafer Feb 27, 2025
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
114 changes: 110 additions & 4 deletions app/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@
# under the License.
"""Main Flask App file."""

import datetime
import yaml
import io
import os
Expand Down Expand Up @@ -129,7 +130,9 @@ def authorized_with_valid_token(f):
@wraps(f)
def decorated_function(*args, **kwargs):

if settings.debug_oidc_token:
if 'token' in session:
oidc_blueprint.session.token = {'access_token': session['token']}
elif settings.debug_oidc_token:
oidc_blueprint.session.token = {'access_token': settings.debug_oidc_token}
else:
try:
Expand Down Expand Up @@ -190,7 +193,11 @@ def home():
if v['description'].find(template_filter) != -1 and "parents" not in tosca["metadata"]:
templates[k] = v

if settings.debug_oidc_token:
# To make easier test endpoints
if 'token' in request.args:
session["token"] = request.args['token']
oidc_blueprint.session.token = {'access_token': request.args['token']}
elif settings.debug_oidc_token:
oidc_blueprint.session.token = {'access_token': settings.debug_oidc_token}
else:
if not oidc_blueprint.session.authorized:
Expand Down Expand Up @@ -408,7 +415,7 @@ def managevm(op=None, infid=None, vmid=None):
vminfo.systems[0].addFeature(Feature("cpu.count", ">=", cpu),
conflict="other", missing="other")
vminfo.systems[0].delValue("memory.size")
vminfo.systems[0].addFeature(Feature("memory.size", ">=", memory, "GB"),
vminfo.systems[0].addFeature(Feature("memory.size", ">=", memory, "GiB"),
conflict="other", missing="other")
if gpu > 0:
vminfo.systems[0].delValue("gpu.count")
Expand All @@ -417,7 +424,7 @@ def managevm(op=None, infid=None, vmid=None):
if disk_size > 0:
vminfo.systems[0].delValue("disks.free_size")
vminfo.systems[0].delValue("disks.0.free_size")
vminfo.systems[0].addFeature(Feature("disks.free_size", ">=", disk_size, "GB"),
vminfo.systems[0].addFeature(Feature("disks.free_size", ">=", disk_size, "GiB"),
conflict="other", missing="other")
response = im.resize_vm(infid, vmid, str(vminfo), auth_data)
else:
Expand Down Expand Up @@ -1622,6 +1629,105 @@ def get_cred_id():
else:
return session['userid']

@app.route('/stats')
@authorized_with_valid_token
def show_stats():
init_date = request.args.get('init_date')
end_date = request.args.get('end_date')
active = request.args.get('active')
today = datetime.datetime.today().date()

if not end_date:
end_date = str(today)

if not init_date:
init_date = str(today - datetime.timedelta(days=180))

access_token = oidc_blueprint.session.token['access_token']

auth_data = utils.getIMUserAuthData(access_token, cred, get_cred_id())
fedcloud_sites = None
inf_actives = []
# Add an element in the first date
infs = [0]
vms = [0]
cpus = [0]
mems = [0]
labels = ["%s 00:00:00" % init_date]
cloud_hosts = []
clouds = [""]
site_name = None
try:
for inf_stat in sorted(im.get_stats(auth_data, init_date, end_date),
key=lambda stat: stat['creation_date']):
if inf_stat['cloud_host']:
# only load this data if a EGI Cloud site appears
if fedcloud_sites is None:
fedcloud_sites = {}
for site in list(utils.getCachedSiteList().values()):
site_host = urlparse(site['url'])[1].split(":")[0]
fedcloud_sites[site_host] = site["name"]

site_name = inf_stat['cloud_host']
if site_name in fedcloud_sites:
site_name = fedcloud_sites[site_name]
elif inf_stat['cloud_type']:
site_name = inf_stat['cloud_type']

if site_name not in cloud_hosts:
cloud_hosts.append(site_name)

if active:
curr_date = datetime.datetime.strptime(inf_stat['creation_date'], "%Y-%m-%d %H:%M:%S")
inf_list = list(inf_actives)
for inf in inf_list:
del_time = datetime.datetime.strptime(inf[4], "%Y-%m-%d %H:%M:%S")
if del_time <= curr_date:
infs.append(-1)
vms.append(inf[0] * -1)
mems.append(inf[1] * -1.0)
cpus.append(inf[2] * -1)
clouds.append(inf[3])
labels.append(inf[4])
inf_actives.remove(inf)

inf_actives.append((inf_stat['vm_count'], (inf_stat['memory_size'] / 1024),
inf_stat['cpu_count'], site_name, "%s 12:00:00" % inf_stat['last_date']))

infs.append(1)
vms.append(inf_stat['vm_count'])
mems.append((inf_stat['memory_size'] / 1024))
cpus.append(inf_stat['cpu_count'])
labels.append(inf_stat['creation_date'])
clouds.append(site_name)

if active:
curr_date = datetime.datetime.strptime("%s 23:59:59" % end_date, "%Y-%m-%d %H:%M:%S")
for inf in inf_actives:
del_time = datetime.datetime.strptime(inf[4], "%Y-%m-%d %H:%M:%S")
if del_time <= curr_date:
infs.append(-1)
vms.append(inf[0])
mems.append(inf[1])
cpus.append(inf[2])
clouds.append(inf[3])
labels.append(inf[4])

# Add an element in the last date
infs.append(0)
vms.append(0)
mems.append(0)
cpus.append(0)
labels.append("%s 23:59:59" % end_date)
clouds.append("")

except Exception as ex:
flash("Error Getting Stats: %s." % ex, 'error')

return render_template('stats.html', infs=infs, vms=vms, cpus=cpus, mems=mems, labels=labels,
today=str(today), init_date=init_date or "", end_date=end_date or "",
cloud_hosts=cloud_hosts, clouds=clouds)

return app


Expand Down
2 changes: 1 addition & 1 deletion app/cred.py
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ def validate_cred(self, userid, new_cred):
if isequal:
return 1, "Credentials already available."

if new_cred["type"] == "EUNode":
if new_cred["type"] in ["EUNode", "EUNodeCont"]:
if new_cred["node"] == cred["node"]:
return 2, ("This site has already a Credential with the same EU Node site." +
" This may cause problems authenticating with the site." +
Expand Down
18 changes: 17 additions & 1 deletion app/im.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@

class InfrastructureManager():

def __init__(self, im_url, timeout=60):
def __init__(self, im_url, timeout=120):
self.im_url = im_url
self.timeout = timeout

Expand Down Expand Up @@ -160,6 +160,22 @@ def change_user(self, infid, token, overwrite, auth_data):

return requests.post(url, headers=headers, timeout=self.timeout, data=new_auth)

def get_stats(self, auth_data, init_date=None, end_date=None):
headers = {"Authorization": auth_data}
url = "%s/stats" % self.im_url
if init_date:
url += "?init_date=%s" % init_date
if end_date:
if init_date:
url += "&"
else:
url += "?"
url += "end_date=%s" % end_date
response = requests.get(url, headers=headers, timeout=self.timeout)
response.raise_for_status()
stats = response.json()
return stats['stats']

def remove_resources(self, infid, vm_list, auth_data):
headers = {"Authorization": auth_data}
url = "%s/infrastructures/%s/vms/%s" % (self.im_url, infid, vm_list)
Expand Down
2 changes: 1 addition & 1 deletion app/settings.py
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ def __init__(self, config):
self.static_sites_url = config.get('STATIC_SITES_URL', "")
self.appdb_cache_timeout = config.get('APPDB_CACHE_TIMEOUT', 3600)
self.debug_oidc_token = config.get('DEBUG_OIDC_TOKEN', None)
self.imTimeout = config.get('IM_TIMEOUT', 60)
self.imTimeout = config.get('IM_TIMEOUT', 120)
self.checkToscaChangesTime = config.get('CHECK_TOSCA_CHANGES_TIME', 120)
self.vault_url = config.get('VAULT_URL', None)
self.im_auth = config.get('IM_AUTH', None)
Expand Down
7 changes: 0 additions & 7 deletions app/static/chart/Chart.min.js

This file was deleted.

13 changes: 13 additions & 0 deletions app/static/chart/chart.min.js

Large diffs are not rendered by default.

7 changes: 7 additions & 0 deletions app/static/chart/chartjs-adapter-date-fns.bundle.min.js

Large diffs are not rendered by default.

30 changes: 16 additions & 14 deletions app/templates/advanced_config.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ <h5>Cloud Provider:</h5>
</div>


<script src="{{ url_for('static', filename='chart/Chart.min.js') }}"></script>
<script src="{{ url_for('static', filename='chart/chart.min.js') }}"></script>
<script src="{{ url_for('static', filename='chart/utils.js') }}"></script>

<script>
Expand All @@ -29,15 +29,17 @@ <h5>Cloud Provider:</h5>
borderWidth: 0
}
},
legend: {
display: false
},
responsive: false,
title: {
display: true,
text: 'VCPUs',
padding: 0
}
plugins: {
legend: {
display: false
},
title: {
display: true,
text: 'VCPUs',
padding: 0
}
}
}
};

Expand All @@ -47,10 +49,10 @@ <h5>Cloud Provider:</h5>
config[resource_types[i]] = JSON.parse(JSON.stringify(config["gen"]));;
}

config["ram"].options.title.text = "RAM (GB)"
config["instances"].options.title.text = "Instances"
config["floating_ips"].options.title.text = "Float IPs"
config["security_groups"].options.title.text = "SGs"
config["ram"].options.plugins.title.text = "RAM (GB)"
config["instances"].options.plugins.title.text = "Instances"
config["floating_ips"].options.plugins.title.text = "Float IPs"
config["security_groups"].options.plugins.title.text = "SGs"

window.onload = function() {
window.myPies = {};
Expand Down Expand Up @@ -119,7 +121,7 @@ <h5>Cloud Provider:</h5>
} else {
document.getElementById('imageID').setAttribute("placeholder", "Image ID");
}
if (cred_type == 'OSCAR' || cred_type == 'Kubernetes' ) {
if (cred_type == 'OSCAR' || cred_type == 'Kubernetes' || cred_type == 'EUNodeCont') {
// OSCAR or K8s do not set images
$('#cloudImages').hide();
activateSubmit();
Expand Down
1 change: 1 addition & 0 deletions app/templates/base.html
Original file line number Diff line number Diff line change
Expand Up @@ -140,6 +140,7 @@
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">Advanced</a>
<div class="dropdown-menu">
<a class="dropdown-item" href="{{ url_for("show_settings") }}">Settings</a>
<a class="dropdown-item" href="{{ url_for("show_stats") }}">Stats</a>
</div>
</li>
{% if session["external_links"]|length > 0 %}
Expand Down
20 changes: 20 additions & 0 deletions app/templates/modal_creds.html
Original file line number Diff line number Diff line change
Expand Up @@ -314,6 +314,26 @@
</select>
</div>
</div>
{% elif cred_type == "EUNodeCont" %}
<div class="row form-group">
<div class="col">
<input placeholder="Token" name="token" class="col-sm-12 form-control my-1" type="text" id="token" value="{{ creds['token'] if creds else '' }}" required/>
</div>
<div class="col">
<select class="js-example-basic-single js-states form-control" id="node" name="node" required>
<option name="node" value="">-- Set EU Node Provider --</option>
<option name="node" value="eu-1" {{ "selected" if creds and creds['node'] == "eu-1" else '' }}>eu-1</option>
<option name="node" value="eu-2" {{ "selected" if creds and creds['node'] == "eu-2" else '' }}>eu-2</option>
</select>
</div>
</div>
<div class="row form-group">
<div class="col">
<input placeholder="Project ID" name="namespace" class="col-sm-12 form-control my-1" type="text" id="namespace" value="{{ creds['namespace'] if creds else '' }}" required/>
</div>
<div class="col">
</div>
</div>
{% else %}


Expand Down
19 changes: 12 additions & 7 deletions app/templates/service_creds.html
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ <h4 class="font-weight-bold text-primary">Cloud Credentials</h4>
<a class="dropdown-item" data-id="" data-type="OSCAR" data-bs-toggle="modal" data-bs-target="#newModal" href="#"><img src="{{ url_for('static', filename='images/OSCARRow.png') }}"/></a>
<a class="dropdown-item" data-id="" data-type="CH" data-bs-toggle="modal" data-bs-target="#newModal" href="#"><img src="{{ url_for('static', filename='images/CHRow.png') }}"/></a>
<a class="dropdown-item" data-id="" data-type="EUNode" data-bs-toggle="modal" data-bs-target="#newModal" href="#"><img src="{{ url_for('static', filename='images/EUNodeRow.png') }}"/></a>
<!--
<a class="dropdown-item" data-id="" data-type="EUNodeCont" data-bs-toggle="modal" data-bs-target="#newModal" href="#"><img src="{{ url_for('static', filename='images/EUNodeContRow.png') }}"/></a>
-->
</div>
</div>
</div> <!-- / .row -->
Expand Down Expand Up @@ -200,13 +203,15 @@ <h5 class="modal-title">Vault Info</h5>
$(".updateBtn").click(function () {
var button = $(event.relatedTarget) // Button that triggered the modal
var cred_id = button.data('id')
// add spinner to button
$(this).parent().find(".updateBtn").addClass("disabled", true);
$(this).addClass("updateBtn", true);
if (cred_id == "") {
$(this).html( `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Adding ...` );
} else {
$(this).html( `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Updating...` );
if ($('#credForm')[0].checkValidity()) {
// add spinner to button
$(this).parent().find(".updateBtn").addClass("disabled", true);
$(this).addClass("updateBtn", true);
if (cred_id == "") {
$(this).html( `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Adding ...` );
} else {
$(this).html( `<span class="spinner-border spinner-border-sm" role="status" aria-hidden="true"></span> Updating...` );
}
}
});
});
Expand Down
1 change: 0 additions & 1 deletion app/templates/ssh_keys.html
Original file line number Diff line number Diff line change
Expand Up @@ -120,4 +120,3 @@ <h5 class="modal-title">Confirm SSH Key deletion</h5>

</script>
{% endblock %}

Loading
Loading