#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
  }
}
master
Javier Sánchez Parra 2020-09-23 11:01:22 +02:00 committed by OpenGnSys Support Team
parent f068a79c1a
commit 403e7c323b
4 changed files with 195 additions and 1 deletions

View File

@ -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");

View File

@ -17,6 +17,9 @@ struct og_server_cfg {
struct {
const char *interface;
} wol;
struct {
const char *dir;
} repo;
json_t *json;
};

View File

@ -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);

View File

@ -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
};