diff options
author | OpenGnSys Support Team <soporte-og@soleta.eu> | 2024-08-21 20:19:23 +0200 |
---|---|---|
committer | OpenGnSys Support Team <soporte-og@soleta.eu> | 2024-08-21 21:58:48 +0200 |
commit | 5eba9f4e1b44fb0d4b4962c2241fe9391e202d7b (patch) | |
tree | 1940f98fcf9d24b1046e425b77eddc5bab624ee4 /src/rest.c | |
parent | 4e0f9aac9e2883a992469f5b2b231ecb14b30183 (diff) |
rest: allow repository to have more than one IP address
Repository can have more than one single IP address.
* Add alias field to database to represent the extra IPs that are attached to
the repository, update schema and add version 9.
* Use og_dbi_get_repository_ip() to infer the repository IP address.
* Add helper functions (src/repo.c) to build a list of repositories and update
rest API to use it.
Diffstat (limited to 'src/rest.c')
-rw-r--r-- | src/rest.c | 331 |
1 files changed, 195 insertions, 136 deletions
@@ -15,6 +15,7 @@ #include "core.h" #include "wol.h" #include "cfg.h" +#include "repo.h" #include "schedule.h" #include "legacy.h" #include <ev.h> @@ -1509,7 +1510,6 @@ struct og_boot_mode_params { const char *ip; const char *ipserveradm; const char *nombreaula; - const char *repoip; const char *oglivedir; const char *hardprofile; const char *router; @@ -1518,18 +1518,21 @@ struct og_boot_mode_params { const char *netiface; const char *directorio; const char *resolucion; + uint32_t repoid; int is_prof; int has_unit; }; static int og_get_client_mode_params(struct og_dbi *dbi, const char *mac, char *params, size_t params_size) { + char repository_ip[OG_DB_IP_MAXLEN + 1] = {}; struct og_boot_mode_params boot_params = {}; const char *res_prefix = " vga="; const char *res_value = "788"; char *lang = getenv("LANG"); const char *msglog; dbi_result result; + int err = 0; result = dbi_conn_queryf(dbi->conn, "SELECT " @@ -1540,7 +1543,7 @@ static int og_get_client_mode_params(struct og_dbi *dbi, const char *mac, char * "ordenadores.nombreordenador AS nombreordenador, " "ordenadores.netiface AS netiface, " "REPLACE(TRIM(aulas.nombreaula), ' ', '_') AS nombreaula, " - "IFNULL(repositorios.ip, '') AS repoip, " + "repositorios.idrepositorio AS repoid, " "ordenadores.oglivedir AS oglivedir, " "IF(ordenadores.idordenador = aulas.idordprofesor, 1, 0) AS is_prof, " "REPLACE(TRIM(IFNULL(perfileshard.descripcion, '')), ' ', '_') AS hardprofile, " @@ -1584,7 +1587,6 @@ static int og_get_client_mode_params(struct og_dbi *dbi, const char *mac, char * boot_params.nombreordenador = dbi_result_get_string_copy(result, "nombreordenador"); boot_params.netiface = dbi_result_get_string_copy(result, "netiface"); boot_params.nombreaula = dbi_result_get_string_copy(result, "nombreaula"); - boot_params.repoip = dbi_result_get_string_copy(result, "repoip"); boot_params.oglivedir = dbi_result_get_string_copy(result, "oglivedir"); boot_params.hardprofile = dbi_result_get_string_copy(result, "hardprofile"); boot_params.ntp = dbi_result_get_string_copy(result, "ntp"); @@ -1592,6 +1594,7 @@ static int og_get_client_mode_params(struct og_dbi *dbi, const char *mac, char * boot_params.proxy = dbi_result_get_string_copy(result, "proxy"); boot_params.directorio = dbi_result_get_string_copy(result, "directorio"); boot_params.resolucion = dbi_result_get_string_copy(result, "resolucion"); + boot_params.repoid = dbi_result_get_uint(result, "repoid"); boot_params.has_unit = dbi_result_get_uint(result, "has_unit"); boot_params.is_prof = dbi_result_get_uint(result, "is_prof"); @@ -1601,13 +1604,21 @@ static int og_get_client_mode_params(struct og_dbi *dbi, const char *mac, char * res_prefix = " video="; } + dbi_result_free(result); + + if (og_dbi_get_repository_ip(dbi, boot_params.repoid, boot_params.ip, + repository_ip) < 0) { + err = -1; + goto err_out; + } + snprintf(params, params_size, " LANG=%s ip=%s:%s:%s:%s:%s:%s:none group=%s ogrepo=%s oglive=%s oglog=%s ogshare=%s oglivedir=%s ogprof=%s server=%s" "%s%s%s%s%s%s%s%s%s%s%s%s", lang, boot_params.ip, boot_params.ipserveradm, boot_params.router, boot_params.netmask, boot_params.nombreordenador, boot_params.netiface, boot_params.nombreaula, - boot_params.repoip, + repository_ip, boot_params.ipserveradm, boot_params.ipserveradm, boot_params.ipserveradm, boot_params.oglivedir, boot_params.is_prof ? "true" : "false", @@ -1618,9 +1629,7 @@ static int og_get_client_mode_params(struct og_dbi *dbi, const char *mac, char * boot_params.proxy[0] ? " ogproxy=" : "", boot_params.proxy[0] ? boot_params.proxy : "", boot_params.has_unit ? " ogunit=" : "", boot_params.has_unit ? boot_params.directorio : "", res_prefix, res_value); - - dbi_result_free(result); - +err_out: free((void *)boot_params.ip); free((void *)boot_params.ipserveradm); free((void *)boot_params.router); @@ -1628,7 +1637,6 @@ static int og_get_client_mode_params(struct og_dbi *dbi, const char *mac, char * free((void *)boot_params.nombreordenador); free((void *)boot_params.netiface); free((void *)boot_params.nombreaula); - free((void *)boot_params.repoip); free((void *)boot_params.oglivedir); free((void *)boot_params.hardprofile); free((void *)boot_params.ntp); @@ -1637,11 +1645,11 @@ static int og_get_client_mode_params(struct og_dbi *dbi, const char *mac, char * free((void *)boot_params.directorio); free((void *)boot_params.resolucion); - return 0; + return err; } -static int og_set_client_mode(struct og_dbi *dbi, const char *mac, - const char *mode) +static int og_set_client_mode(struct og_dbi *dbi, const char *client_ip, + const char *mac, const char *mode) { char params[4096]; @@ -1651,7 +1659,10 @@ static int og_set_client_mode(struct og_dbi *dbi, const char *mac, return -1; } - og_get_client_mode_params(dbi, mac, params, sizeof(params)); + if (og_get_client_mode_params(dbi, mac, params, sizeof(params)) < 0) { + syslog(LOG_ERR, "failed to get boot parameters (%s:%d)\n", __FILE__, __LINE__); + return -1; + } if (og_create_boot_file(OG_TFTP_BOOT_BIOS, mac, mode, params) < 0) { syslog(LOG_ERR, "failed to create BIOS boot file (%s:%d)\n", __FILE__, __LINE__); @@ -1675,9 +1686,8 @@ static int og_set_client_mode(struct og_dbi *dbi, const char *mac, static int og_cmd_post_modes(json_t *element, struct og_msg_params *params) { - char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {}; const char *mode_str, *mac; - int ips_str_len = 0; + const char *msglog; struct og_dbi *dbi; uint64_t flags = 0; dbi_result result; @@ -1704,12 +1714,6 @@ static int og_cmd_post_modes(json_t *element, struct og_msg_params *params) !og_msg_params_validate(params, OG_REST_PARAM_ADDR)) return -1; - for (i = 0; i < params->ips_array_len; ++i) { - ips_str_len += snprintf(ips_str + ips_str_len, - sizeof(ips_str) - ips_str_len, - "'%s',", params->ips_array[i]); - } - ips_str[ips_str_len - 1] = '\0'; dbi = og_dbi_open(&ogconfig.db); if (!dbi) { @@ -1718,21 +1722,38 @@ static int og_cmd_post_modes(json_t *element, struct og_msg_params *params) return -1; } - result = dbi_conn_queryf(dbi->conn, - "SELECT mac FROM ordenadores " - "WHERE ip IN (%s)", ips_str); - - while (dbi_result_next_row(result)) { + for (i = 0; i < params->ips_array_len; i++) { + result = dbi_conn_queryf(dbi->conn, + "SELECT mac FROM ordenadores " + "WHERE ip = '%s'", 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); + og_dbi_close(dbi); + return -1; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, "could not find client IP: %s (%s:%d)\n", + params->ips_array[i], __func__, __LINE__); + dbi_result_free(result); + og_dbi_close(dbi); + return -1; + } mac = dbi_result_get_string(result, "mac"); - err = og_set_client_mode(dbi, mac, mode_str); - if (err != 0) { + + err = og_set_client_mode(dbi, params->ips_array[i], mac, mode_str); + if (err < 0) { + syslog(LOG_ERR, "cannot set boot mode for client IP: %s (%s:%d)\n", + params->ips_array[i], __func__, __LINE__); dbi_result_free(result); og_dbi_close(dbi); return -1; } + + dbi_result_free(result); } - dbi_result_free(result); og_dbi_close(dbi); return 0; @@ -2435,7 +2456,7 @@ static int og_cmd_post_client_update(json_t *element, dbi_result_free(result); - if (og_set_client_mode(dbi, computer.mac, computer.boot)) { + if (og_set_client_mode(dbi, computer.ip, computer.mac, computer.boot)) { syslog(LOG_ERR, "failed to set client boot mode (%s:%d)\n", __func__, __LINE__); og_dbi_close(dbi); @@ -3029,7 +3050,7 @@ static int og_cmd_post_client_add(json_t *element, dbi_result_free(result); - if (og_set_client_mode(dbi, computer.mac, computer.boot)) { + if (og_set_client_mode(dbi, computer.ip, computer.mac, computer.boot)) { syslog(LOG_ERR, "failed to set client boot mode (%s:%d)\n", __func__, __LINE__); og_dbi_close(dbi); @@ -3497,53 +3518,62 @@ static int og_cmd_get_software(json_t *element, struct og_msg_params *params, static const int og_cmd_get_repositories(char *buffer_reply) { - json_t *root, *repositories, *repository, *id, *ip, *name; + json_t *root, *repository, *repositories, *ips; struct og_buffer og_buffer = { .data = buffer_reply, }; - struct og_dbi *dbi; - dbi_result result; + LIST_HEAD(repo_list); + struct og_repo *repo; + uint32_t i; - dbi = og_dbi_open(&ogconfig.db); - if (!dbi) { - syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", - __func__, __LINE__); + if (og_repo_list(&repo_list) < 0) return -1; - } - result = dbi_conn_queryf(dbi->conn, - "SELECT idrepositorio, ip, nombrerepositorio " - "FROM repositorios"); + root = json_object(); + if (!root) + return -1; repositories = json_array(); + if (!repositories) { + json_decref(root); + return -1; + } - while (dbi_result_next_row(result)) { + json_object_set_new(root, "repositories", repositories); + + list_for_each_entry(repo, &repo_list, list) { repository = json_object(); - id = json_integer(dbi_result_get_ulonglong(result, - "idrepositorio")); - ip = json_string(dbi_result_get_string(result, "ip")); - name = json_string(dbi_result_get_string(result, - "nombrerepositorio")); - json_object_set_new(repository, "id", id); - json_object_set_new(repository, "ip", ip); - json_object_set_new(repository, "name", name); - json_array_append_new(repositories, repository); - } + if (!repository) + goto err_out; - dbi_result_free(result); - og_dbi_close(dbi); + ips = json_array(); + if (!ips) { + json_decref(repository); + goto err_out; + } - root = json_object(); - json_object_set_new(root, "repositories", repositories); + for (i = 0; i < repo->num_ips; i++) + json_array_append_new(ips, json_string(inet_ntoa(repo->addr[i]))); - if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) { - json_decref(root); - return -1; + json_object_set_new(repository, "id", json_integer(repo->id)); + json_object_set_new(repository, "addr", ips); + json_object_set_new(repository, "name", json_string(repo->name)); + json_array_append_new(repositories, repository); } + if (json_dump_callback(root, og_json_dump_clients, &og_buffer, JSON_ENSURE_ASCII)) + goto err_out; + + og_repo_free_list(&repo_list); json_decref(root); return 0; + +err_out: + og_repo_free_list(&repo_list); + json_decref(root); + + return -1; } #define OG_IMAGE_TYPE_MAXLEN 4 @@ -3830,7 +3860,8 @@ static int og_cmd_add_image(json_t *element, struct og_msg_params *params, clients = json_copy(element); json_object_del(clients, "clients"); - err = og_dbi_get_repository_ip(dbi, params->image.repo_id, repository_ip); + err = og_dbi_get_repository_ip(dbi, params->image.repo_id, + params->ips_array[0], repository_ip); og_dbi_close(dbi); if (err < 0) return err; @@ -7104,34 +7135,30 @@ static int og_cmd_post_repository_update(json_t *element, struct og_msg_params *params, char *buffer_reply) { - struct og_repository repo = {}; + char name[OG_DB_REPO_NAME_MAXLEN]; const char *key, *msglog; unsigned int repo_id; struct og_dbi *dbi; dbi_result result; + int err = 0, i; json_t *value; - int err = 0; json_object_foreach(element, key, value) { if (!strcmp(key, "id")) { err = og_json_parse_uint(value, &repo_id); params->flags |= OG_REST_PARAM_ID; + } else if (!strcmp(key, "name")) { + err = og_json_parse_string_copy(value, name, + sizeof(name)); + } else if (!strcmp(key, "addr")) { + err = og_json_parse_clients(value, params); } - if (!strcmp(key, "name")) { - err = og_json_parse_string_copy(value, - repo.name, - sizeof(repo.name)); - } else if (!strcmp(key, "ip")) { - err = og_json_parse_string_copy(value, - repo.ip, - sizeof(repo.ip)); - } else if (!strcmp(key, "center")) { - err = og_json_parse_uint(value, &repo.center); - } + if (err < 0) return err; } - if (!og_msg_params_validate(params, OG_REST_PARAM_ID)) + if (!og_msg_params_validate(params, OG_REST_PARAM_ID | + OG_REST_PARAM_ADDR)) return -1; dbi = og_dbi_open(&ogconfig.db); @@ -7142,12 +7169,8 @@ static int og_cmd_post_repository_update(json_t *element, } result = dbi_conn_queryf(dbi->conn, - "UPDATE repositorios" - " SET nombrerepositorio='%s'," - " ip='%s'," - " idcentro=%u" - " WHERE idrepositorio=%u;", - repo.name, repo.ip, repo.center, repo_id); + "DELETE FROM repositorios WHERE alias=%u;", + repo_id); if (!result) { dbi_conn_error(dbi->conn, &msglog); syslog(LOG_ERR, "failed to update repository in database (%s:%d) %s\n", @@ -7155,75 +7178,83 @@ static int og_cmd_post_repository_update(json_t *element, og_dbi_close(dbi); return -1; } - if (!dbi_result_get_numrows_affected(result)) { - syslog(LOG_ERR, "repository with id %u does not exist (%s:%d)\n", - repo_id, __func__, __LINE__); - dbi_result_free(result); + dbi_result_free(result); + + result = dbi_conn_queryf(dbi->conn, + "UPDATE repositorios " + "SET ip='%s' WHERE idrepositorio=%u;", + params->ips_array[0], repo_id); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, + "failed to add repository to database (%s:%d) %s\n", + __func__, __LINE__, msglog); og_dbi_close(dbi); return -1; } - dbi_result_free(result); + + for (i = 1; i < params->ips_array_len; i++) { + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO repositorios(" + "nombrerepositorio, ip, idcentro, grupoid, alias) VALUES " + "('%s', '%s', 1, 0, %u);", + name, params->ips_array[i], repo_id); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, + "failed to add repository to database (%s:%d) %s\n", + __func__, __LINE__, msglog); + og_dbi_close(dbi); + return -1; + } + dbi_result_free(result); + } + og_dbi_close(dbi); - return err; + + return 0; } static int og_cmd_post_repository_add(json_t *element, struct og_msg_params *params, char *buffer_reply) { - struct og_repository repo = { - .center = 1, /* never used, set it to 1. */ - }; + char name[OG_DB_REPO_NAME_MAXLEN]; const char *key, *msglog; - struct in_addr addr; struct og_dbi *dbi; dbi_result result; + int err = 0, i; json_t *value; - int err = 0; + uint32_t id; json_object_foreach(element, key, value) { if (!strcmp(key, "name")) { - err = og_json_parse_string_copy(value, - repo.name, - sizeof(repo.name)); - params->flags |= OG_REST_PARAM_NAME; - } else if (!strcmp(key, "ip")) { - err = og_json_parse_string_copy(value, - repo.ip, - sizeof(repo.ip)); - params->flags |= OG_REST_PARAM_ADDR; - } else if (!strcmp(key, "center")) { - err = og_json_parse_uint(value, &repo.center); + err = og_json_parse_string_copy(value, name, + sizeof(name)); + } else if (!strcmp(key, "addr")) { + err = og_json_parse_clients(value, params); } if (err < 0) return err; } - if (!og_msg_params_validate(params, OG_REST_PARAM_NAME | - OG_REST_PARAM_ADDR)) - return -1; - - if (inet_pton(AF_INET, repo.ip, &addr) <= 0) { - syslog(LOG_ERR, "invalid server ip address (%s:%d)\n", - __func__, __LINE__); + if (!og_msg_params_validate(params, OG_REST_PARAM_ADDR)) return -1; - } dbi = og_dbi_open(&ogconfig.db); if (!dbi) { - syslog(LOG_ERR, "cannot open conection database (%s:%d)\n", + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", __func__, __LINE__); return -1; } result = dbi_conn_queryf(dbi->conn, "INSERT INTO repositorios(" - "nombrerepositorio, ip, idcentro, grupoid) VALUES " - "('%s', '%s', %u, 0)", - repo.name, repo.ip, repo.center); - + "nombrerepositorio, ip, idcentro, grupoid, alias) VALUES " + "('%s', '%s', 1, 0, NULL);", + name, params->ips_array[0]); if (!result) { dbi_conn_error(dbi->conn, &msglog); syslog(LOG_ERR, @@ -7234,9 +7265,29 @@ static int og_cmd_post_repository_add(json_t *element, } dbi_result_free(result); + + id = dbi_conn_sequence_last(dbi->conn, NULL); + + for (i = 1; i < params->ips_array_len; i++) { + result = dbi_conn_queryf(dbi->conn, + "INSERT INTO repositorios(" + "nombrerepositorio, ip, idcentro, grupoid, alias) VALUES " + "('%s', '%s', 1, 0, %u);", + name, params->ips_array[i], id); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_ERR, + "failed to add repository to database (%s:%d) %s\n", + __func__, __LINE__, msglog); + og_dbi_close(dbi); + return -1; + } + dbi_result_free(result); + } + og_dbi_close(dbi); - return err; + return 0; } static int og_cmd_post_repository_delete(json_t *element, @@ -7270,7 +7321,7 @@ static int og_cmd_post_repository_delete(json_t *element, result = dbi_conn_queryf(dbi->conn, "DELETE FROM repositorios " - "WHERE idrepositorio=%u", + "WHERE idrepositorio=%u OR alias=%u", repo_id, repo_id); if (!result) { @@ -8060,10 +8111,9 @@ static int og_dbi_update_oglive(struct og_dbi *dbi, const char *mac, static int og_cmd_oglive_set(json_t *element, struct og_msg_params *params) { - char ips_str[(OG_DB_IP_MAXLEN + 1) * OG_CLIENTS_MAX + 1] = {}; const char legacy_default_oglive_str[] = "ogLive"; const char *oglive_str, *mac, *mode_str; - int ips_str_len = 0; + const char *msglog; struct og_dbi *dbi; uint64_t flags = 0; dbi_result result; @@ -8093,13 +8143,6 @@ static int og_cmd_oglive_set(json_t *element, struct og_msg_params *params) if (!strcmp(oglive_str, "default")) oglive_str = legacy_default_oglive_str; - for (i = 0; i < params->ips_array_len; ++i) { - ips_str_len += snprintf(ips_str + ips_str_len, - sizeof(ips_str) - ips_str_len, - "'%s',", params->ips_array[i]); - } - ips_str[ips_str_len - 1] = '\0'; - dbi = og_dbi_open(&ogconfig.db); if (!dbi) { syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", @@ -8107,30 +8150,46 @@ static int og_cmd_oglive_set(json_t *element, struct og_msg_params *params) return -1; } - result = dbi_conn_queryf(dbi->conn, - "SELECT mac, arranque FROM ordenadores " - "WHERE ip IN (%s)", ips_str); - - while (dbi_result_next_row(result)) { - mac = dbi_result_get_string(result, "mac"); + for (i = 0; i < params->ips_array_len; i++) { + result = dbi_conn_queryf(dbi->conn, + "SELECT mac, arranque FROM ordenadores " + "WHERE ip = '%s'", 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); + og_dbi_close(dbi); + return -1; + } + if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, "could not find client IP: %s (%s:%d)\n", + params->ips_array[i], __func__, __LINE__); + dbi_result_free(result); + og_dbi_close(dbi); + return -1; + } mode_str = dbi_result_get_string(result, "arranque"); + mac = dbi_result_get_string(result, "mac"); + err = og_dbi_update_oglive(dbi, mac, oglive_str); - if (err != 0) { + if (err < 0) { syslog(LOG_ERR, "failed to change db oglive (%s:%d)\n", __func__, __LINE__); dbi_result_free(result); og_dbi_close(dbi); return -1; } - err = og_set_client_mode(dbi, mac, mode_str); - if (err != 0) { + + err = og_set_client_mode(dbi, params->ips_array[i], mac, mode_str); + if (err < 0) { dbi_result_free(result); og_dbi_close(dbi); return -1; } + + dbi_result_free(result); } - dbi_result_free(result); og_dbi_close(dbi); return 0; |