mirror of https://git.48k.eu/ogserver
rest: add GET /efi
Add GET /efi request to obtain information about the client's boot entries. Field inside the /refresh payload 'efi': { 'entries': [ { "order": 0, "name": "Boot0000", "active": false, "description": "grub" }, { "order": 1, "name": "Boot0001", "active": true, "description": "UEFI: PXE IP4 Realtek PCIe GBE Family Controller" } ] } If the client is not a EFI system it won't add the 'efi' field. If an entry is not in the boot order it won't have the 'order' field. GET /efi resquest payload structure: { 'clients': ['10.141.10.21', '10.141.10.22'] } GET /efi response's structure: { 'clients': [ { 'ip': '10.141.10.21', 'entries': [ { "order": 0, "name": "Boot0000", "active": false, "description": "grub" }, { "order": 1, "name": "Boot0001", "active": true, "description": "UEFI: PXE IP4 Realtek PCIe GBE Family Controller" } ] }, { 'ip': '10.141.10.22', 'entries': [] } ] } The client with ip 10.141.10.22 is a BIOS system. If an entry does not appear in the boot order it won't have the 'order' field.master
parent
1fa3813b92
commit
e3a73a504f
50
src/client.c
50
src/client.c
|
@ -435,6 +435,45 @@ static int og_update_cache_info(struct og_dbi *dbi, struct list_head *cache_list
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int og_update_boot_entries(struct og_dbi *dbi, struct list_head *boot_entry_list, int client_id)
|
||||
{
|
||||
struct og_boot_entry *boot_entry;
|
||||
const char *msglog;
|
||||
dbi_result result;
|
||||
|
||||
/* Remove old boot entries */
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
"DELETE FROM boot_entries WHERE client_id=%d;", client_id);
|
||||
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
/* Add new boot entries */
|
||||
list_for_each_entry(boot_entry, boot_entry_list, list) {
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
"INSERT INTO boot_entries (client_id, name, active, description, entry_order)"
|
||||
"VALUES (%d, '%s', %d, '%s', %d)",
|
||||
client_id,
|
||||
boot_entry->name,
|
||||
boot_entry->active ? 1 : 0,
|
||||
boot_entry->description,
|
||||
boot_entry->order == UINT64_MAX ? -1 : boot_entry->order);
|
||||
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int og_resp_update_cache(json_t *data, struct og_client *cli)
|
||||
{
|
||||
struct og_computer computer = {};
|
||||
|
@ -496,6 +535,7 @@ static int og_resp_refresh(json_t *data, struct og_client *cli)
|
|||
struct og_computer computer = {};
|
||||
json_t *value, *cache = NULL;
|
||||
const char *status = NULL;
|
||||
LIST_HEAD(boot_entry_list);
|
||||
LIST_HEAD(cache_list);
|
||||
char cfg[4096] = {};
|
||||
struct og_dbi *dbi;
|
||||
|
@ -519,6 +559,8 @@ static int og_resp_refresh(json_t *data, struct og_client *cli)
|
|||
err = og_json_parse_string(value, &status);
|
||||
} else if (!strcmp(key, "link")) {
|
||||
err = og_json_parse_uint(value, &link);
|
||||
} else if (!strcmp(key, "efi")) {
|
||||
err = og_json_parse_efi(value, &boot_entry_list);
|
||||
} else if (!strcmp(key, "cache")) {
|
||||
err = og_json_parse_cache(value, &cache_list);
|
||||
cache = value;
|
||||
|
@ -595,6 +637,12 @@ static int og_resp_refresh(json_t *data, struct og_client *cli)
|
|||
goto err_out;
|
||||
}
|
||||
|
||||
res = og_update_boot_entries(dbi, &boot_entry_list, computer.id);
|
||||
if (err < 0) {
|
||||
og_dbi_close(dbi);
|
||||
goto err_out;
|
||||
}
|
||||
|
||||
res = actualizaConfiguracion(dbi, cfg, computer.id);
|
||||
og_dbi_close(dbi);
|
||||
|
||||
|
@ -611,9 +659,11 @@ static int og_resp_refresh(json_t *data, struct og_client *cli)
|
|||
}
|
||||
|
||||
og_cache_image_free(&cache_list);
|
||||
og_boot_entry_free(&boot_entry_list);
|
||||
return 0;
|
||||
err_out:
|
||||
og_cache_image_free(&cache_list);
|
||||
og_boot_entry_free(&boot_entry_list);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
|
97
src/json.c
97
src/json.c
|
@ -303,3 +303,100 @@ int og_json_parse_cache(json_t *element, struct list_head *cache_list)
|
|||
|
||||
return err;
|
||||
}
|
||||
|
||||
void og_boot_entry_free(struct list_head *boot_entry_list)
|
||||
{
|
||||
struct og_boot_entry *boot_entry, *tmp;
|
||||
|
||||
list_for_each_entry_safe(boot_entry, tmp, boot_entry_list, list) {
|
||||
list_del(&boot_entry->list);
|
||||
free(boot_entry);
|
||||
}
|
||||
}
|
||||
|
||||
int og_json_parse_boot_entries(json_t *json_entries, struct list_head *boot_entry_list)
|
||||
{
|
||||
uint64_t required_flags = OG_PARAM_EFI_NAME | OG_PARAM_EFI_DESCRIPTION | OG_PARAM_EFI_ACTIVE;
|
||||
struct og_boot_entry *boot_entry;
|
||||
json_t *json_elem, *value;
|
||||
uint64_t flags = 0UL;
|
||||
unsigned long i;
|
||||
const char *key;
|
||||
int err = 0;
|
||||
|
||||
if (json_typeof(json_entries) != JSON_ARRAY)
|
||||
return -1;
|
||||
|
||||
for (i = 0; i < json_array_size(json_entries); i++) {
|
||||
boot_entry = calloc(1, sizeof(struct og_boot_entry));
|
||||
boot_entry->order = UINT64_MAX;
|
||||
flags = 0UL;
|
||||
|
||||
if (!boot_entry)
|
||||
return -1;
|
||||
|
||||
json_elem = json_array_get(json_entries, i);
|
||||
|
||||
if (json_typeof(json_elem) != JSON_OBJECT) {
|
||||
free(boot_entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_object_foreach(json_elem, key, value) {
|
||||
if (!strcmp(key, "name")) {
|
||||
err = og_json_parse_string(value, &boot_entry->name);
|
||||
flags |= OG_PARAM_EFI_NAME;
|
||||
} else if (!strcmp(key, "active")) {
|
||||
err = og_json_parse_bool(value, &boot_entry->active);
|
||||
flags |= OG_PARAM_EFI_ACTIVE;
|
||||
} else if (!strcmp(key, "description")) {
|
||||
err = og_json_parse_string(value, &boot_entry->description);
|
||||
flags |= OG_PARAM_EFI_DESCRIPTION;
|
||||
} else if (!strcmp(key, "order")) {
|
||||
err = og_json_parse_uint64(value, &boot_entry->order);
|
||||
} else
|
||||
err = -1;
|
||||
|
||||
if (err < 0) {
|
||||
free(boot_entry);
|
||||
return err;
|
||||
}
|
||||
}
|
||||
|
||||
if ((flags & required_flags) != required_flags) {
|
||||
free(boot_entry);
|
||||
return -1;
|
||||
}
|
||||
|
||||
list_add_tail(&boot_entry->list, boot_entry_list);
|
||||
}
|
||||
return err;
|
||||
}
|
||||
|
||||
int og_json_parse_efi(json_t *element, struct list_head *boot_entry_list)
|
||||
{
|
||||
uint64_t required_flags = OG_PARAM_EFI_ENTRIES;
|
||||
uint64_t flags = 0UL;
|
||||
const char *key;
|
||||
json_t *value;
|
||||
int err = 0;
|
||||
|
||||
if (json_typeof(element) != JSON_OBJECT)
|
||||
return -1;
|
||||
|
||||
json_object_foreach(element, key, value) {
|
||||
if (!strcmp(key, "entries")) {
|
||||
err = og_json_parse_boot_entries(value, boot_entry_list);
|
||||
flags |= OG_PARAM_EFI_ENTRIES;
|
||||
} else
|
||||
err = -1;
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if ((flags & required_flags) != required_flags)
|
||||
return -1;
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
19
src/json.h
19
src/json.h
|
@ -2,6 +2,7 @@
|
|||
#define _OG_JSON_H
|
||||
|
||||
#include <jansson.h>
|
||||
#include <stdint.h>
|
||||
#include "schedule.h"
|
||||
|
||||
int og_json_parse_string(const json_t *element, const char **str);
|
||||
|
@ -146,4 +147,22 @@ struct og_cache_image {
|
|||
void og_cache_image_free(struct list_head *cache_list);
|
||||
int og_json_parse_cache(json_t *element, struct list_head *cache_list);
|
||||
|
||||
|
||||
#define OG_PARAM_EFI_ENTRIES (1UL << 0)
|
||||
#define OG_PARAM_EFI_ORDER (1UL << 1)
|
||||
#define OG_PARAM_EFI_NAME (1UL << 2)
|
||||
#define OG_PARAM_EFI_DESCRIPTION (1UL << 3)
|
||||
#define OG_PARAM_EFI_ACTIVE (1UL << 4)
|
||||
|
||||
struct og_boot_entry {
|
||||
const char *description;
|
||||
const char *name;
|
||||
bool active;
|
||||
uint64_t order;
|
||||
struct list_head list;
|
||||
};
|
||||
|
||||
void og_boot_entry_free(struct list_head *boot_entry_list);
|
||||
int og_json_parse_efi(json_t *element, struct list_head *boot_entry_list);
|
||||
|
||||
#endif
|
||||
|
|
151
src/rest.c
151
src/rest.c
|
@ -4337,6 +4337,143 @@ static int og_cmd_cache_list(json_t *element, struct og_msg_params *params,
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int og_dbi_client_efi_get(struct og_dbi *dbi, json_t *clients, const char *ip)
|
||||
{
|
||||
json_t *client_data, *boot_entry, *boot_entry_arr;
|
||||
const char *msglog, *entry_name, *entry_description;
|
||||
bool entry_active;
|
||||
int entry_order;
|
||||
dbi_result result;
|
||||
|
||||
client_data = json_object();
|
||||
if (!client_data)
|
||||
return -1;
|
||||
|
||||
json_object_set_new(client_data, "ip", json_string(ip));
|
||||
|
||||
result = dbi_conn_queryf(dbi->conn,
|
||||
"SELECT boot_entries.name, boot_entries.active, "
|
||||
"boot_entries.description, boot_entries.entry_order "
|
||||
"FROM boot_entries JOIN ordenadores "
|
||||
"ON ordenadores.idordenador = boot_entries.client_id "
|
||||
"WHERE ordenadores.ip = '%s' "
|
||||
"ORDER BY "
|
||||
" CASE "
|
||||
" WHEN boot_entries.entry_order >= 0 THEN 0 ELSE 1 "
|
||||
" END ASC, "
|
||||
" boot_entries.entry_order ASC", ip);
|
||||
|
||||
if (!result) {
|
||||
json_decref(client_data);
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
|
||||
boot_entry_arr = json_array();
|
||||
if (!boot_entry_arr) {
|
||||
json_decref(client_data);
|
||||
dbi_result_free(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
while (dbi_result_next_row(result)) {
|
||||
entry_name = dbi_result_get_string(result, "name");
|
||||
entry_active = dbi_result_get_int(result, "active") != 0;
|
||||
entry_description = dbi_result_get_string(result, "description");
|
||||
entry_order = dbi_result_get_int(result, "entry_order");
|
||||
|
||||
boot_entry = json_object();
|
||||
if (!boot_entry) {
|
||||
json_decref(client_data);
|
||||
json_decref(boot_entry_arr);
|
||||
dbi_result_free(result);
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_object_set_new(boot_entry, "name", json_string(entry_name));
|
||||
json_object_set_new(boot_entry, "active", json_boolean(entry_active));
|
||||
json_object_set_new(boot_entry, "description", json_string(entry_description));
|
||||
if (entry_order >= 0)
|
||||
json_object_set_new(boot_entry, "order", json_integer(entry_order));
|
||||
json_array_append_new(boot_entry_arr, boot_entry);
|
||||
}
|
||||
json_object_set_new(client_data, "entries", boot_entry_arr);
|
||||
json_array_append_new(clients, client_data);
|
||||
dbi_result_free(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int og_cmd_efi_list(json_t *element, struct og_msg_params *params,
|
||||
char *buffer_reply)
|
||||
{
|
||||
json_t *value, *root, *clients;
|
||||
struct og_dbi *dbi;
|
||||
const char *key;
|
||||
int err = 0, i;
|
||||
|
||||
struct og_buffer og_buffer = {
|
||||
.data = buffer_reply
|
||||
};
|
||||
|
||||
if (json_typeof(element) != JSON_OBJECT)
|
||||
return -1;
|
||||
|
||||
json_object_foreach(element, key, value) {
|
||||
if (!strcmp(key, "clients"))
|
||||
err = og_json_parse_clients(value, params);
|
||||
else
|
||||
err = -1;
|
||||
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
|
||||
if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR))
|
||||
return -1;
|
||||
|
||||
clients = json_array();
|
||||
if (!clients)
|
||||
return -1;
|
||||
|
||||
dbi = og_dbi_open(&ogconfig.db);
|
||||
if (!dbi) {
|
||||
syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
|
||||
__func__, __LINE__);
|
||||
json_decref(clients);
|
||||
return -1;
|
||||
}
|
||||
|
||||
for (i = 0; i < params->ips_array_len; i++) {
|
||||
if (og_dbi_client_efi_get(dbi, clients, params->ips_array[i]) < 0) {
|
||||
json_decref(clients);
|
||||
og_dbi_close(dbi);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
og_dbi_close(dbi);
|
||||
|
||||
root = json_object();
|
||||
if (!root) {
|
||||
json_decref(clients);
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_object_set_new(root, "clients", clients);
|
||||
|
||||
if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) {
|
||||
json_decref(root);
|
||||
return -1;
|
||||
}
|
||||
|
||||
json_decref(root);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int og_cmd_cache_delete(json_t *element, struct og_msg_params *params,
|
||||
char *buffer_reply)
|
||||
{
|
||||
|
@ -8317,6 +8454,7 @@ struct {
|
|||
[OG_URI_CACHE_LIST] = { "cache/list", },
|
||||
[OG_URI_CACHE_DELETE] = { "cache/delete", },
|
||||
[OG_URI_CACHE_FETCH] = { "cache/fetch", },
|
||||
[OG_URI_EFI] = { "efi", },
|
||||
[OG_URI_PART_SETUP] = { "setup", },
|
||||
[OG_URI_RUN_SCHEDULE] = { "run/schedule", },
|
||||
[OG_URI_TASK_RUN] = { "task/run", },
|
||||
|
@ -8928,6 +9066,19 @@ int og_client_state_process_payload_rest(struct og_client *cli)
|
|||
goto err_process_rest_payload;
|
||||
}
|
||||
err = og_cmd_cache_list(root, ¶ms, buf_reply);
|
||||
} else if (!strncmp(cmd, "efi", strlen("efi"))) {
|
||||
if (method != OG_METHOD_GET) {
|
||||
err = og_client_method_not_found(cli);
|
||||
goto err_process_rest_payload;
|
||||
}
|
||||
|
||||
if (!root) {
|
||||
syslog(LOG_ERR,
|
||||
"command efi with no payload\n");
|
||||
err = og_client_bad_request(cli);
|
||||
goto err_process_rest_payload;
|
||||
}
|
||||
err = og_cmd_efi_list(root, ¶ms, buf_reply);
|
||||
} else if (!strncmp(cmd, "cache/delete", strlen("cache/delete"))) {
|
||||
if (method != OG_METHOD_POST) {
|
||||
err = og_client_method_not_found(cli);
|
||||
|
|
|
@ -128,6 +128,7 @@ enum og_rest_uri {
|
|||
OG_URI_IMAGE_DELETE,
|
||||
OG_URI_IMAGE_RESTRICT,
|
||||
OG_URI_CACHE_LIST,
|
||||
OG_URI_EFI,
|
||||
OG_URI_CACHE_DELETE,
|
||||
OG_URI_CACHE_FETCH,
|
||||
OG_URI_PART_SETUP,
|
||||
|
|
37
src/schema.c
37
src/schema.c
|
@ -398,6 +398,42 @@ static int og_dbi_schema_v9(struct og_dbi *dbi)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int og_dbi_schema_v10(struct og_dbi *dbi)
|
||||
{
|
||||
const char *msglog;
|
||||
dbi_result result;
|
||||
|
||||
syslog(LOG_DEBUG, "Creating table boot_entries\n");
|
||||
result = dbi_conn_query(dbi->conn, "CREATE TABLE `boot_entries` ("
|
||||
"`id` BIGINT NOT NULL AUTO_INCREMENT,"
|
||||
"`client_id` INT NOT NULL,"
|
||||
"`name` VARCHAR(255),"
|
||||
"`active` BOOLEAN,"
|
||||
"`description` TEXT,"
|
||||
"`entry_order` INT,"
|
||||
"PRIMARY KEY (`id`),"
|
||||
"FOREIGN KEY (`client_id`) REFERENCES `ordenadores` (`idordenador`) ON DELETE CASCADE"
|
||||
")");
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_INFO, "Error when creating boot_entries (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
|
||||
result = dbi_conn_query(dbi->conn, "UPDATE version SET version = 10");
|
||||
if (!result) {
|
||||
dbi_conn_error(dbi->conn, &msglog);
|
||||
syslog(LOG_INFO, "Could not update version row (%s:%d) %s\n",
|
||||
__func__, __LINE__, msglog);
|
||||
return -1;
|
||||
}
|
||||
dbi_result_free(result);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static struct og_schema_version {
|
||||
int version;
|
||||
int (*update)(struct og_dbi *dbi);
|
||||
|
@ -411,6 +447,7 @@ static struct og_schema_version {
|
|||
{ .version = 7, .update = og_dbi_schema_v7, },
|
||||
{ .version = 8, .update = og_dbi_schema_v8, },
|
||||
{ .version = 9, .update = og_dbi_schema_v9, },
|
||||
{ .version = 10, .update = og_dbi_schema_v10,},
|
||||
{ 0, NULL },
|
||||
};
|
||||
|
||||
|
|
Loading…
Reference in New Issue