Changeset - b8926b4f0c3b
[Not reviewed]
0 4 2
Jan Kaluza - 10 years ago 2016-01-19 14:33:45
jkaluza@redhat.com
Web interface: first try of API server + javascript based starting/stopping of instances
6 files changed with 100 insertions and 5 deletions:
0 comments (0 inline, 0 general)
spectrum_manager/src/APIServer.cpp
Show inline comments
 
@@ -12,6 +12,12 @@
 
#include <string>
 
#include <cerrno>
 

	
 
#define ALLOW_ONLY_ADMIN() 	if (!session->admin) { \
 
		std::string _json = "{\"error\":1, \"message\": \"Only administrators can do this API call.\"}"; \
 
		send_json(conn, _json); \
 
		return; \
 
	}
 

	
 
static std::string get_http_var(const struct http_message *hm, const char *name) {
 
	char data[4096];
 
	data[0] = '\0';
 
@@ -29,6 +35,11 @@ static std::string get_http_var(const struct http_message *hm, const char *name)
 
	return "";
 
}
 

	
 
static int has_prefix(const struct mg_str *uri, const char *prefix) {
 
	size_t prefix_len = strlen(prefix);
 
	return uri->len >= prefix_len && memcmp(uri->p, prefix, prefix_len) == 0;
 
}
 

	
 
APIServer::APIServer(ManagerConfig *config, StorageBackend *storage) {
 
	m_config = config;
 
	m_storage = storage;
 
@@ -37,7 +48,15 @@ APIServer::APIServer(ManagerConfig *config, StorageBackend *storage) {
 
APIServer::~APIServer() {
 
}
 

	
 
std::string &APIServer::safe_arg(std::string &arg) {
 
	boost::replace_all(arg, "\n", "");
 
	boost::replace_all(arg, "\"", "'");
 
	return arg;
 
}
 

	
 
void APIServer::send_json(struct mg_connection *conn, const std::string &json) {
 
	std::cout << "Sending JSON:\n";
 
	std::cout << json << "\n";
 
	mg_printf(conn,
 
			"HTTP/1.1 200 OK\r\n"
 
			"Content-Type: text/json\r\n"
 
@@ -70,7 +89,13 @@ void APIServer::serve_instances(Server *server, Server::session *session, struct
 
		else if (*(status.end() - 1) == '\n') {
 
			status.erase(status.end() - 1);
 
		}
 
		json += "\"status\":\"" + status + "\"";
 
		json += "\"status\":\"" + safe_arg(status) + "\",";
 

	
 
		bool running = true;
 
		if (status.find("Running") == std::string::npos) {
 
			running = false;
 
		}
 
		json += "\"running\":" + (running ? std::string("1") : std::string("0"));
 
		json += "},";
 
	}
 
	json.erase(json.end() - 1);
 
@@ -79,8 +104,42 @@ void APIServer::serve_instances(Server *server, Server::session *session, struct
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::serve_instances_start(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	ALLOW_ONLY_ADMIN();
 

	
 
	std::string uri(hm->uri.p, hm->uri.len);
 
	std::string instance = uri.substr(uri.rfind("/") + 1);
 
	start_instances(m_config, instance);
 
	std::string response = get_response();
 
	std::string error = response.find("OK") == std::string::npos ? "1" : "0";
 
	std::string json = "{\"error\":" + error + ", \"message\": \"" + safe_arg(response) + "\"}";
 

	
 
	// TODO: So far it needs some time to reload Spectrum 2, so just sleep here.
 
	sleep(1);
 

	
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::serve_instances_stop(Server *server, Server::session *session, struct mg_connection *conn, struct http_message *hm) {
 
	ALLOW_ONLY_ADMIN();
 

	
 
	std::string uri(hm->uri.p, hm->uri.len);
 
	std::string instance = uri.substr(uri.rfind("/") + 1);
 
	stop_instances(m_config, instance);
 
	std::string response = get_response();
 
	std::string error = response.find("OK") == std::string::npos ? "1" : "0";
 
	std::string json = "{\"error\":" + error + ", \"message\": \"" + safe_arg(response) + "\"}"; \
 
	send_json(conn, json);
 
}
 

	
 
void APIServer::handleRequest(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm) {
 
	if (mg_vcmp(&hm->uri, "/api/v1/instances") == 0) {
 
	if (has_prefix(&hm->uri, "/api/v1/instances/start/")) {
 
		serve_instances_start(server, sess, conn, hm);
 
	}
 
	else if (has_prefix(&hm->uri, "/api/v1/instances/stop/")) {
 
		serve_instances_stop(server, sess, conn, hm);
 
	}
 
	else if (mg_vcmp(&hm->uri, "/api/v1/instances") == 0) {
 
		serve_instances(server, sess, conn, hm);
 
	}
 
}
spectrum_manager/src/APIServer.h
Show inline comments
 
@@ -50,6 +50,9 @@ class APIServer {
 

	
 
	private:
 
		void serve_instances(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		void serve_instances_start(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		void serve_instances_stop(Server *server, Server::session *sess, struct mg_connection *conn, struct http_message *hm);
 
		std::string &safe_arg(std::string &);
 
		void send_json(struct mg_connection *conn, const std::string &json);
 

	
 
	private:
spectrum_manager/src/html/header.html
Show inline comments
 
@@ -7,7 +7,10 @@
 

	
 
    <link href="/style.css" rel="stylesheet" type="text/css" media="all">
 
    <link href="/form.css" rel="stylesheet" type="text/css" media="all">
 

	
 
    <link href="https://code.jquery.com/ui/1.11.4/themes/smoothness/jquery-ui.css" rel="stylesheet" type="text/css" media="all">
 
    <script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
 
    <script src="https://code.jquery.com/ui/1.11.4/jquery-ui.min.js"></script>
 
    <script src="/js/app.js"></script>
 
    <title>Spectrum 2</title>
 
  </head>
 

	
 
@@ -20,7 +23,7 @@
 
            <img id="logo" src="/logo.png" style="width:250px; margin-left: auto;margin-right: auto; display:block;">
 

	
 
            <section id="menu" style="text-align: center;">
 
            <a class="menuitem" href="/">Instances</a>
 
            <a class="menuitem" href="/instances">Instances</a>
 
            <a class="menuitem" href="/users">Users</a>
 
            <a class="menuitem" href="/logout">Logout</a>
 
            </section>
 
@@ -30,3 +33,4 @@
 
    <!-- MAIN CONTENT -->
 
    <div id="main_content_wrap" class="outer">
 
      <section id="main_content" class="inner">
 
 
 
\ No newline at end of file
spectrum_manager/src/html/instances/index.shtml
Show inline comments
 
new file 100644
 
<!--#include virtual="/header.html" -->
 

	
 
<script type="text/javascript">
 
$(function() {
 
	show_instances();
 
});
 
</script>
 

	
 
<!--#include virtual="/footer.html" -->
spectrum_manager/src/html/js/app.js
Show inline comments
 
new file 100644
 
function show_instances() {
 
    $.get("/api/v1/instances", function(data) {
 
	$("#main_content").html("<h2>List of Spectrum 2 instances</h2><table id='main_result'><tr><th>Hostname<th>Status</th><th>Command</th></tr>");
 
        $.each(data.instances, function(i, instance) {
 
		var command = instance.running ? "stop" : "start";
 
		var row = '<tr><td>'+ instance.name + '</td><td>' + 
 
		instance.status + '</td><td><a class="button_command" href="/api/v1/instances/' + 
 
		command + '/' + instance.id + '">' + command + '</a>' + '</td></tr>';
 
		$("#main_result  > tbody:last-child").append(row);
 
		$(".button_command").click(function(e) {
 
			e.preventDefault();
 
			$(this).parent().empty().progressbar( {value: false} ).css('height', '1em');
 
			var url = $(this).attr('href');
 
			$.get(url, function(data) {
 
			show_instances();				
 
			});
 
		})
 
        });
 
});
 
}
spectrum_manager/src/server.cpp
Show inline comments
 
@@ -180,7 +180,7 @@ void Server::authorize(struct mg_connection *conn, struct http_message *hm) {
 
			"Set-Cookie: user=%s\r\n"  // Set user, needed by Javascript code
 
			"Set-Cookie: admin=%s\r\n"  // Set user, needed by Javascript code
 
			"Set-Cookie: original_url=/; max-age=0\r\n"  // Delete original_url
 
			"Location: /\r\n\r\n",
 
			"Location: /instances\r\n\r\n",
 
			session->session_id, session->user, session->admin ? "1" : "0");
 
	} else {
 
		// Authentication failure, redirect to login.
0 comments (0 inline, 0 general)