Commit 5b21051f authored by Daniele Venzano's avatar Daniele Venzano

User status and cluster termination

parent bd21031d
This diff is collapsed.
......@@ -18,6 +18,7 @@ def get_db():
"""
return _db
from caaas.swarm import swarm
import caaas.web
import caaas.api
......@@ -23,3 +23,27 @@ def api_full_status():
data[username]["num_containers"] = db.count_containers(user_id)
data[username]["has_notebook"] = db.has_notebook(user_id)
return jsonify(**data)
@app.route("/api/<username>/status")
def api_user_status(username):
db = get_db()
user_id = get_db().get_user_id(username)
cluster_list = db.get_clusters(user_id)
for clid in cluster_list:
cluster_list[clid]["is_notebook"] = cluster_list[clid]["name"] == "notebook"
cluster_list[clid]["num_containers"] = db.count_containers(user_id, clid)
return jsonify(**cluster_list)
@app.route("/api/<username>/cluster/<cluster_id>/terminate")
def api_terminate_cluster(username, cluster_id):
db = get_db()
user_id = get_db().get_user_id(username)
cluster_list = db.get_clusters(user_id)
ret = {}
if cluster_list[cluster_id]["user_id"] != user_id:
ret["status"] = "unauthorized"
else:
swarm.terminate_cluster(cluster_id)
return jsonify(**ret)
......@@ -58,14 +58,21 @@ class CAaaSSQL:
cursor.close()
return row[0]
def count_containers(self, user_id=None):
def count_containers(self, user_id=None, cluster_id=None):
cursor = self.cnx.cursor()
if user_id is None:
if user_id is None and cluster_id is None:
q = "SELECT COUNT(*) FROM containers"
cursor.execute(q)
else:
elif user_id is not None and cluster_id is None:
q = "SELECT COUNT(*) FROM containers WHERE user_id=%s"
cursor.execute(q, (user_id,))
elif user_id is None and cluster_id is not None:
q = "SELECT COUNT(*) FROM containers WHERE cluster_id=%s"
cursor.execute(q, (cluster_id,))
elif user_id is not None and cluster_id is not None:
q = "SELECT COUNT(*) FROM containers WHERE user_id=%s AND cluster_id=%s"
cursor.execute(q, (user_id, cluster_id))
row = cursor.fetchone()
cursor.close()
return row[0]
......@@ -150,3 +157,76 @@ class CAaaSSQL:
self.cnx.commit()
cursor.close()
return nb_id
def get_clusters(self, user_id=None):
cursor = self.cnx.cursor(dictionary=True)
res = {}
if user_id is None:
q = "SELECT id, user_id, master_address, name FROM clusters"
cursor.execute(q)
else:
q = "SELECT id, user_id, master_address, name FROM clusters WHERE user_id=%s"
cursor.execute(q, (user_id,))
for row in cursor:
res[str(row["id"])] = {
"user_id": row["user_id"],
"master_address": row["master_address"],
"name": row["name"]
}
cursor.close()
return res
def get_containers(self, user_id=None, cluster_id=None):
cursor = self.cnx.cursor(dictionary=True)
res = {}
if user_id is None and cluster_id is None:
q = "SELECT id, docker_id, cluster_id, user_id, ip_address, contents FROM containers"
cursor.execute(q)
elif user_id is not None and cluster_id is None:
q = "SELECT id, docker_id, cluster_id, user_id, ip_address, contents FROM containers WHERE user_id=%s"
cursor.execute(q, (user_id,))
elif user_id is None and cluster_id is not None:
q = "SELECT id, docker_id, cluster_id, user_id, ip_address, contents FROM containers WHERE cluster_id=%s"
cursor.execute(q, (cluster_id,))
elif user_id is not None and cluster_id is not None:
q = "SELECT id, docker_id, cluster_id, user_id, ip_address, contents FROM containers WHERE user_id=%s AND cluster_id=%s"
cursor.execute(q, (user_id, cluster_id))
for row in cursor:
res[str(row["id"])] = {
"docker_id": row["docker_id"],
"cluster_id": row["cluster_id"],
"user_id": row["user_id"],
"ip_address": row["ip_address"],
"contents": row["contents"],
}
cursor.close()
return res
def remove_proxy(self, container_id):
cursor = self.cnx.cursor()
q = "DELETE FROM proxy WHERE container_id=%s"
cursor.execute(q, (container_id,))
self.cnx.commit()
cursor.close()
def remove_notebook(self, container_id):
cursor = self.cnx.cursor()
q = "DELETE FROM notebooks WHERE container_id=%s"
cursor.execute(q, (container_id,))
self.cnx.commit()
cursor.close()
def remove_container(self, container_id):
cursor = self.cnx.cursor()
q = "DELETE FROM containers WHERE id=%s"
cursor.execute(q, (container_id,))
self.cnx.commit()
cursor.close()
def remove_cluster(self, cluster_id):
cursor = self.cnx.cursor()
q = "DELETE FROM clusters WHERE id=%s"
cursor.execute(q, (cluster_id,))
self.cnx.commit()
cursor.close()
......@@ -134,4 +134,20 @@ class Swarm:
}
return info
def _terminate_container(self, container_id, docker_id, contents):
db = get_db()
db.remove_proxy(container_id)
if contents == "spark-notebook":
db.remove_notebook(container_id)
self.cli.remove_container(docker_id, force=True)
db.remove_container(container_id)
def terminate_cluster(self, cluster_id):
db = get_db()
cont_list = db.get_containers(cluster_id=cluster_id)
for cid, cinfo in cont_list.items():
self._terminate_container(cid, cinfo["docker_id"], cinfo["contents"])
db.remove_cluster(cluster_id)
return True
swarm = Swarm()
......@@ -11,7 +11,7 @@
{% endblock %}
</head>
<body>
<div class="header"><em>CAaaS</em> &dash; Available nodes: <span id="num_nodes">0</span> Containers: <span id="num_containers">0</span></div>
<div class="header"><em>CAaaS</em> -- Available nodes: <span id="num_nodes">0</span> Containers: <span id="num_containers">0</span></div>
<script>
function update_status() {
$.getJSON( api_endpoint + "/status")
......
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<h1>DSG CAaaS system - Analytics on demand</h1>
<p>Start an activity:</p>
<ul>
<li><a href="/web/{{ user }}/spark-notebook">Give me a Spark notebook</a></li>
<li>Submit a Spark application</li>
</ul>
<p>Monitor my activities:</p>
<ul>
<li><a href="/web/{{ user }}/status">Running applications</a></li>
</ul>
<p>Cluster status:</p>
<ul>
<li><a href="/web/status">Overview</a></li>
</ul>
{% endblock %}
\ No newline at end of file
{% extends "base.html" %}
{% block title %}Home{% endblock %}
{% block content %}
<script>
function process()
{
var url = "http://" + window.location.hostname + "/web/" + $("#user").val();
location.href = url;
return false;
}
</script>
<h1>DSG CAaaS system - Analytics on demand</h1>
<p>Start an activity:</p>
<ul>
<li><a href="/web/{{ user }}/spark-notebook">Give me a Spark notebook</a></li>
<li>Submit a Spark application</li>
</ul>
<p>Monitor my activities:</p>
<ul>
<li><a href="/web/{{ user }}/status">Running applications</a></li>
</ul>
<form onSubmit="return process();">
<label>Type your username to start:
<input id="user" autofocus required pattern="[a-z]+"></label>
<input type="submit" value="Start">
</form>
<p>Cluster status:</p>
<ul>
<li><a href="/web/status">Overview</a></li>
</ul>
<p>To create a new user, just type a new username in the box above, only lowercase letters are accepted.</p>
{% endblock %}
\ No newline at end of file
{% extends "base.html" %}
{% block title %}{{ user }} status{% endblock %}
{% block content %}
<script type="application/javascript">
function gen_one_cluster(i, item) {
var block = $("<div></div>");
var cluster_name = item.name;
if (item.is_notebook) {
cluster_name += " (<a href=\"/api/{{ user }}/cluster/" + i + "/terminate\">terminate</a>)";
}
block.append("<p></p>").html(cluster_name);
var ul = $("<ul></ul>");
ul.append($("<li></li>").text("Num. containers: " + item.num_containers));
ul.append($("<li></li>").text("Notebook cluster: " + item.is_notebook));
block.append(ul);
return block;
}
(function() {
$.getJSON( api_endpoint + "/{{ user }}/status")
.done(function( data ) {
$.each(data, function(i, item) {
$("#cluster_list").append(gen_one_cluster(i, item))
})
});
})();
</script>
<h1>Status overview for user {{ user }}</h1>
<div id="cluster_list"></div>
{% endblock %}
\ No newline at end of file
......@@ -3,12 +3,26 @@ from flask import render_template
from caaas import app, swarm, get_db
@app.route("/web/")
def index():
return render_template('index.html')
@app.route("/web/<username>")
def web_index(username):
template_vars = {
"user": username
}
return render_template('index.html', **template_vars)
return render_template('home.html', **template_vars)
@app.route("/web/<username>/status")
def web_user_status(username):
user_id = get_db().get_user_id(username)
template_vars = {
"user": username
}
return render_template('user-status.html', **template_vars)
@app.route("/web/<username>/spark-notebook")
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment