summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJavier Sánchez Parra <jsanchez@soleta.eu>2020-09-23 11:01:22 +0200
committerOpenGnSys Support Team <soporte-og@soleta.eu>2020-09-29 12:43:07 +0200
commit403e7c323b3069c8c70088ded30de3096a216e3f (patch)
treeaf2d46c5838054ba77cb99bcb67a928eab52ba60
parentf068a79c1a39f7f796e045628693241b0f3bc15a (diff)
#1004 Add GET /images
This commit adds GET /images to the ogServer REST API. This call returns information of all the images in ogServer. Example response: { "images": [ { "filename": "ubuntu.img", "datasize": 2150400000, "size": 613476223, "modified": "Wed Sep 23 10:37:36 2020", "permissions": "744" }, { "filename": "test.img", "datasize": 2150400000, "size": 613236475, "modified": "Tue Sep 29 08:57:47 2020", "permissions": "744" } ], "disk": { "total": 52573995008, "free": 39624544256 } }
-rw-r--r--src/cfg.c27
-rw-r--r--src/cfg.h3
-rw-r--r--src/rest.c165
-rw-r--r--src/rest.h1
4 files changed, 195 insertions, 1 deletions
diff --git a/src/cfg.c b/src/cfg.c
index fa88fc1..f4361ec 100644
--- a/src/cfg.c
+++ b/src/cfg.c
@@ -88,9 +88,28 @@ static int parse_json_wol(struct og_server_cfg *cfg, json_t *element)
return 0;
}
+static int parse_json_repo(struct og_server_cfg *cfg, json_t *element)
+{
+ const char *key;
+ json_t *value;
+
+ json_object_foreach(element, key, value) {
+ if (!strcmp(key, "directory")) {
+ if (og_json_parse_string(value, &cfg->repo.dir) < 0)
+ return -1;
+ } else {
+ syslog(LOG_ERR, "unknown key `%s' in repo\n", key);
+ return -1;
+ }
+ }
+
+ return 0;
+}
+
#define OG_SERVER_CFG_REST (1 << 0)
#define OG_SERVER_CFG_DB (1 << 1)
#define OG_SERVER_CFG_WOL (1 << 2)
+#define OG_SERVER_CFG_REPO (1 << 3)
int parse_json_config(const char *filename, struct og_server_cfg *cfg)
{
@@ -138,6 +157,11 @@ int parse_json_config(const char *filename, struct og_server_cfg *cfg)
break;
}
flags |= OG_SERVER_CFG_DB;
+ } else if (!strcmp(key, "repository")) {
+ if (parse_json_repo(cfg, value) < 0)
+ return -1;
+
+ flags |= OG_SERVER_CFG_REPO;
} else {
syslog(LOG_ERR, "unknown key `%s' in %s\n",
key, filename);
@@ -150,7 +174,8 @@ int parse_json_config(const char *filename, struct og_server_cfg *cfg)
if ((flags & OG_SERVER_CFG_REST) &&
(flags & OG_SERVER_CFG_DB) &&
- (flags & OG_SERVER_CFG_WOL)) {
+ (flags & OG_SERVER_CFG_WOL) &&
+ (flags & OG_SERVER_CFG_REPO)) {
ret = 0;
} else {
syslog(LOG_ERR, "Missing attributes in json file");
diff --git a/src/cfg.h b/src/cfg.h
index c88a406..0d45bbd 100644
--- a/src/cfg.h
+++ b/src/cfg.h
@@ -17,6 +17,9 @@ struct og_server_cfg {
struct {
const char *interface;
} wol;
+ struct {
+ const char *dir;
+ } repo;
json_t *json;
};
diff --git a/src/rest.c b/src/rest.c
index b5b5f0c..966deaf 100644
--- a/src/rest.c
+++ b/src/rest.c
@@ -26,6 +26,7 @@
#include <stdlib.h>
#include <unistd.h>
#include <sys/wait.h>
+#include <sys/statvfs.h>
struct ev_loop *og_loop;
@@ -240,6 +241,7 @@ static const char *og_cmd_to_uri[OG_CMD_MAX] = {
[OG_CMD_IMAGE_RESTORE] = "image/restore",
[OG_CMD_SETUP] = "setup",
[OG_CMD_RUN_SCHEDULE] = "run/schedule",
+ [OG_CMD_IMAGES] = "images",
};
static bool og_client_is_busy(const struct og_client *cli,
@@ -1532,6 +1534,161 @@ static int og_cmd_software(json_t *element, struct og_msg_params *params)
return og_send_request(OG_METHOD_POST, OG_CMD_SOFTWARE, params, clients);
}
+#define OG_IMAGE_TYPE_MAXLEN 4
+
+struct og_image {
+ const char *filename;
+ uint64_t datasize;
+ struct stat image_stats;
+};
+
+static int og_get_image_stats(const char *name,
+ struct stat *image_stats)
+{
+ const char *dir = cfg.repo.dir;
+ char filename[PATH_MAX + 1];
+
+ snprintf(filename, sizeof(filename), "%s/%s", dir, name);
+ if (stat(filename, image_stats) < 0) {
+ syslog(LOG_ERR, "%s image does not exists", name);
+ return -1;
+ }
+ return 0;
+}
+
+static json_t *og_json_disk_alloc()
+{
+ const char *dir = cfg.repo.dir;
+ struct statvfs buffer;
+ json_t *disk_json;
+ int ret;
+
+ ret = statvfs(dir, &buffer);
+ if (ret)
+ return NULL;
+
+ disk_json = json_object();
+ if (!disk_json)
+ return NULL;
+
+ json_object_set_new(disk_json, "total",
+ json_integer(buffer.f_blocks * buffer.f_frsize));
+ json_object_set_new(disk_json, "free",
+ json_integer(buffer.f_bfree * buffer.f_frsize));
+
+ return disk_json;
+}
+
+#define OG_PERMS_IRWX (S_IRWXU | S_IRWXG | S_IRWXO)
+#define OG_PERMS_MAXLEN 4
+
+static json_t *og_json_image_alloc(struct og_image *image)
+{
+ char perms_string[OG_PERMS_MAXLEN];
+ json_t *image_json;
+ char *modified;
+ uint16_t perms;
+
+ image_json = json_object();
+ if (!image_json)
+ return NULL;
+
+ perms = image->image_stats.st_mode & OG_PERMS_IRWX;
+ snprintf(perms_string, sizeof(perms_string), "%o", perms);
+
+ modified = ctime(&image->image_stats.st_mtime);
+ modified[strlen(modified) - 1] = '\0';
+
+ json_object_set_new(image_json, "filename",
+ json_string(image->filename));
+ json_object_set_new(image_json, "datasize",
+ json_integer(image->datasize));
+ json_object_set_new(image_json, "size",
+ json_integer(image->image_stats.st_size));
+ json_object_set_new(image_json, "modified",
+ json_string(modified));
+ json_object_set_new(image_json, "permissions",
+ json_string(perms_string));
+
+ return image_json;
+}
+
+static int og_cmd_images(char *buffer_reply)
+{
+ json_t *root, *images, *image_json, *disk_json;
+ struct og_buffer og_buffer = {
+ .data = buffer_reply
+ };
+ struct og_image image;
+ struct og_dbi *dbi;
+ dbi_result result;
+
+ root = json_object();
+ if (!root)
+ return -1;
+
+ images = json_array();
+ if (!images) {
+ json_decref(root);
+ return -1;
+ }
+
+ json_object_set_new(root, "images", images);
+
+ dbi = og_dbi_open(&dbi_config);
+ if (!dbi) {
+ syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
+ __func__, __LINE__);
+ json_decref(root);
+ return -1;
+ }
+
+ result = dbi_conn_queryf(dbi->conn,
+ "SELECT i.nombreca, o.nombreordenador, "
+ " i.clonator, i.compressor, "
+ " i.filesystem, i.datasize "
+ "FROM imagenes i "
+ "LEFT JOIN ordenadores o "
+ "ON i.idordenador = o.idordenador");
+
+ while (dbi_result_next_row(result)) {
+ image = (struct og_image){0};
+ image.filename = dbi_result_get_string(result, "nombreca");
+ image.datasize = dbi_result_get_ulonglong(result, "datasize");
+
+ if (og_get_image_stats(image.filename, &image.image_stats)) {
+ continue;
+ }
+
+ image_json = og_json_image_alloc(&image);
+ if (!image_json) {
+ dbi_result_free(result);
+ og_dbi_close(dbi);
+ json_decref(root);
+ return -1;
+ }
+
+ json_array_append(images, image_json);
+ }
+
+ dbi_result_free(result);
+ og_dbi_close(dbi);
+
+ disk_json = og_json_disk_alloc();
+ if (!disk_json) {
+ syslog(LOG_ERR, "cannot allocate disk json");
+ json_decref(root);
+ return -1;
+ }
+
+ json_object_set_new(root, "disk", disk_json);
+
+ json_dump_callback(root, og_json_dump_clients, &og_buffer, 0);
+ json_decref(root);
+
+ return 0;
+}
+
static int og_cmd_create_image(json_t *element, struct og_msg_params *params)
{
json_t *value, *clients;
@@ -3489,6 +3646,14 @@ int og_client_state_process_payload_rest(struct og_client *cli)
return og_client_bad_request(cli);
}
err = og_cmd_software(root, &params);
+ } else if (!strncmp(cmd, "images", strlen("images"))) {
+ if (method != OG_METHOD_GET)
+ return og_client_method_not_found(cli);
+
+ if (!root)
+ err = og_cmd_images(buf_reply);
+ else
+ return og_client_method_not_found(cli);
} else if (!strncmp(cmd, "image/create", strlen("image/create"))) {
if (method != OG_METHOD_POST)
return og_client_method_not_found(cli);
diff --git a/src/rest.h b/src/rest.h
index 4f2347f..58d25c7 100644
--- a/src/rest.h
+++ b/src/rest.h
@@ -33,6 +33,7 @@ enum og_cmd_type {
OG_CMD_IMAGE_RESTORE,
OG_CMD_SETUP,
OG_CMD_RUN_SCHEDULE,
+ OG_CMD_IMAGES,
OG_CMD_MAX
};