summaryrefslogtreecommitdiffstats
path: root/src/rest.c
diff options
context:
space:
mode:
authorJose M. Guisado <jguisado@soleta.eu>2021-06-09 11:25:29 +0000
committerOpenGnSys Support Team <soporte-og@soleta.eu>2021-06-09 13:41:28 +0200
commit141b0797e17f616d633704a4b011fde515496ab3 (patch)
tree48b875bd0d52009a4eb7a681065bda082c59409d /src/rest.c
parentcb7fa569b2f79e8c767b3969394839a96f241298 (diff)
#915 Add schedule/command
Enables ogserver to schedule commands (also referred as actions in legacy web console jargon). This feature enables ogserver to write in the "acciones" table in order to have full capabilities for command scheduling purposes, thus not depending in the legacy web console to insert into "acciones" table.
Diffstat (limited to 'src/rest.c')
-rw-r--r--src/rest.c219
1 files changed, 210 insertions, 9 deletions
diff --git a/src/rest.c b/src/rest.c
index e9eb7ca..feeb306 100644
--- a/src/rest.c
+++ b/src/rest.c
@@ -15,6 +15,7 @@
#include "wol.h"
#include "cfg.h"
#include "schedule.h"
+#include "legacy.h"
#include <ev.h>
#include <syslog.h>
#include <sys/ioctl.h>
@@ -162,8 +163,7 @@ static int og_json_parse_clients(json_t *element, struct og_msg_params *params)
return 0;
}
-static int og_json_parse_partition_setup(json_t *element,
- struct og_msg_params *params)
+int og_json_parse_partition_setup(json_t *element, struct og_msg_params *params)
{
unsigned int i;
json_t *k;
@@ -2041,12 +2041,11 @@ static int og_cmd_images(char *buffer_reply)
return 0;
}
-static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
+int og_json_parse_create_image(json_t *element,
+ struct og_msg_params *params)
{
- char new_image_id[OG_DB_INT_MAXLEN + 1];
struct og_image image = {};
- json_t *value, *clients;
- struct og_dbi *dbi;
+ json_t *value;
const char *key;
int err = 0;
@@ -2088,6 +2087,21 @@ static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
return err;
}
+ return 0;
+}
+
+static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
+{
+ char new_image_id[OG_DB_INT_MAXLEN + 1];
+ struct og_image image = {};
+ struct og_dbi *dbi;
+ json_t *clients;
+ int err = 0;
+
+ err = og_json_parse_create_image(element, params);
+ if (err < 0)
+ return err;
+
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_DISK |
OG_REST_PARAM_PARTITION |
@@ -2126,10 +2140,10 @@ static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
clients);
}
-static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
+int og_json_parse_restore_image(json_t *element, struct og_msg_params *params)
{
- json_t *clients, *value;
const char *key;
+ json_t *value;
int err = 0;
if (json_typeof(element) != JSON_OBJECT)
@@ -2165,6 +2179,18 @@ static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
return err;
}
+ return 0;
+}
+
+static int og_cmd_restore_image(json_t *element, struct og_msg_params *params)
+{
+ json_t *clients;
+ int err = 0;
+
+ err = og_json_parse_restore_image(element, params);
+ if (err < 0)
+ return err;
+
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
OG_REST_PARAM_DISK |
OG_REST_PARAM_PARTITION |
@@ -2953,7 +2979,7 @@ static int og_dbi_queue_command(struct og_dbi *dbi, uint32_t task_id,
result = dbi_conn_queryf(dbi->conn,
"SELECT idaccion, idcentro, idordenador, parametros "
"FROM acciones "
- "WHERE sesion = %u", task_id);
+ "WHERE idaccion = %u", task_id);
if (!result) {
dbi_conn_error(dbi->conn, &msglog);
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
@@ -4282,6 +4308,168 @@ static int og_cmd_post_room_delete(json_t *element,
return 0;
}
+enum {
+ OG_SCHEDULE_CMD_TYPE = 0,
+ OG_SCHEDULE_CMD_PARAMS,
+};
+
+static bool og_cmd_validate(const struct og_cmd_json *cmd,
+ const uint64_t flags)
+{
+ return (cmd->flags & flags) == flags;
+}
+
+
+static int og_cmd_post_schedule_command(json_t *element,
+ struct og_msg_params *params)
+{
+ char *centerid_query = "SELECT o.idordenador, c.idcentro "
+ "FROM `ordenadores` AS o "
+ "INNER JOIN aulas AS a ON o.idaula = a.idaula "
+ "INNER JOIN centros AS c ON a.idcentro = c.idcentro "
+ "WHERE o.ip = '%s';";
+ int center_id, client_id, len;
+ struct og_cmd_json cmd = {};
+ const char *legacy_params;
+ const char *key, *msglog;
+ struct og_dbi *dbi;
+ char task_id[128];
+ uint32_t sequence;
+ bool when = false;
+ dbi_result result;
+ json_t *value;
+ int err = 0, i;
+
+ json_object_foreach(element, key, value) {
+ if (!strcmp(key, "clients")) {
+ err = og_json_parse_clients(value, params);
+ } else if (!strcmp(key, "command")) {
+ err = og_json_parse_string(value, &cmd.type);
+ cmd.flags |= OG_SCHEDULE_CMD_TYPE;
+ } else if (!strcmp(key, "params")) {
+ cmd.json = value;
+ cmd.flags |= OG_SCHEDULE_CMD_PARAMS;
+ } else if (!strcmp(key, "when")) {
+ err = og_json_parse_time_params(value, params);
+ when = true;
+ }
+
+ if (err < 0)
+ return err;
+ }
+
+ if (!og_cmd_validate(&cmd, OG_SCHEDULE_CMD_TYPE |
+ OG_SCHEDULE_CMD_PARAMS))
+ return -1;
+
+ if (!when) {
+ params->time.check_stale = false;
+ og_schedule_time_now(&params->time);
+ params->flags |= OG_REST_PARAM_TIME_YEARS |
+ OG_REST_PARAM_TIME_MONTHS |
+ OG_REST_PARAM_TIME_WEEKS |
+ OG_REST_PARAM_TIME_WEEK_DAYS |
+ OG_REST_PARAM_TIME_DAYS |
+ OG_REST_PARAM_TIME_HOURS |
+ OG_REST_PARAM_TIME_AM_PM |
+ OG_REST_PARAM_TIME_MINUTES;
+ } else {
+ params->time.check_stale = true;
+ }
+
+ if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR |
+ OG_REST_PARAM_TIME_YEARS |
+ OG_REST_PARAM_TIME_MONTHS |
+ OG_REST_PARAM_TIME_WEEKS |
+ OG_REST_PARAM_TIME_WEEK_DAYS |
+ OG_REST_PARAM_TIME_DAYS |
+ OG_REST_PARAM_TIME_HOURS |
+ OG_REST_PARAM_TIME_MINUTES |
+ OG_REST_PARAM_TIME_AM_PM))
+ return -1;
+
+ params->type = "command";
+ dbi = og_dbi_open(&ogconfig.db);
+ if (!dbi) {
+ syslog(LOG_ERR, "cannot open conection database (%s:%d)\n",
+ __func__, __LINE__);
+ goto err_dbi_open;
+ }
+
+ legacy_params = og_msg_params_to_legacy(&cmd);
+ if (!legacy_params)
+ goto err_legacy_params;
+
+ /* ips_array -> ids */
+ for (i = 0; i < params->ips_array_len; i++) {
+
+ result = dbi_conn_queryf(dbi->conn, centerid_query, params->ips_array[i]);
+ if (!result) {
+ dbi_conn_error(dbi->conn, &msglog);
+ syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
+ __func__, __LINE__, msglog);
+ goto err_dbi_result;
+ }
+ if (dbi_result_get_numrows(result) != 1) {
+ dbi_conn_error(dbi->conn, &msglog);
+ syslog(LOG_ERR, "client not found (%s:%d) %s\n",
+ __func__, __LINE__, msglog);
+ goto err_dbi;
+ }
+
+ if (!dbi_result_next_row(result)) {
+ dbi_conn_error(dbi->conn, &msglog);
+ syslog(LOG_ERR, "failed to get idcentro (%s:%d) %s\n",
+ __func__, __LINE__, msglog);
+ goto err_dbi;
+ }
+ center_id = dbi_result_get_uint(result, "idcentro");
+ if (!center_id) {
+ dbi_conn_error(dbi->conn, &msglog);
+ syslog(LOG_ERR, "failed to get idcentro (%s:%d) %s\n",
+ __func__, __LINE__, msglog);
+ goto err_dbi;
+ }
+ client_id = dbi_result_get_uint(result, "idordenador");
+ dbi_result_free(result);
+
+ result = dbi_conn_queryf(dbi->conn, "INSERT INTO acciones (idordenador, "
+ "idcentro, parametros)"
+ "VALUES (%d, %d, '%s')",
+ client_id, center_id, legacy_params);
+ if (!result) {
+ dbi_conn_error(dbi->conn, &msglog);
+ syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
+ __func__, __LINE__, msglog);
+ goto err_dbi_result;
+ }
+ dbi_result_free(result);
+
+ sequence = dbi_conn_sequence_last(dbi->conn, NULL);
+ len = snprintf(task_id, sizeof(sequence), "%d", sequence);
+ if (len >= (int)sizeof(task_id)) {
+ syslog(LOG_ERR, "truncated snprintf (%s:%d)\n",
+ __func__, __LINE__);
+ goto err_dbi;
+ }
+ params->task_id = task_id;
+ og_task_schedule_create(params);
+ }
+
+ free((char *)legacy_params);
+ og_dbi_close(dbi);
+ return 0;
+
+err_dbi:
+ dbi_result_free(result);
+err_dbi_result:
+ free((char *)legacy_params);
+err_legacy_params:
+ og_dbi_close(dbi);
+err_dbi_open:
+ return -1;
+}
+
static int og_client_method_not_found(struct og_client *cli)
{
/* To meet RFC 7231, this function MUST generate an Allow header field
@@ -4823,6 +5011,19 @@ int og_client_state_process_payload_rest(struct og_client *cli)
goto err_process_rest_payload;
}
err = og_cmd_post_procedure_add(root, &params);
+ } else if (!strncmp(cmd, "schedule/command", strlen("schedule/command"))) {
+ if (method != OG_METHOD_POST) {
+ err = og_client_method_not_found(cli);
+ goto err_process_rest_payload;
+ }
+
+ if (!root) {
+ syslog(LOG_ERR,
+ "command schedule action with no payload\n");
+ err = og_client_bad_request(cli);
+ goto err_process_rest_payload;
+ }
+ err = og_cmd_post_schedule_command(root, &params);
} else {
syslog(LOG_ERR, "unknown command: %.32s ...\n", cmd);
err = og_client_not_found(cli);