diff --git a/spectrum_manager/src/APIServer.cpp b/spectrum_manager/src/APIServer.cpp index 359f6d483a1b9a4c90f61657a449065d3d140bb4..8dd645c3f1cd28bbfbe6c42c15903f157b8914b2 100644 --- a/spectrum_manager/src/APIServer.cpp +++ b/spectrum_manager/src/APIServer.cpp @@ -12,6 +12,12 @@ #include #include +#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); } }