From 5eba9f4e1b44fb0d4b4962c2241fe9391e202d7b Mon Sep 17 00:00:00 2001 From: OpenGnSys Support Team Date: Wed, 21 Aug 2024 20:19:23 +0200 Subject: 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. --- Makefile.am | 1 + src/client.c | 13 ++- src/dbi.c | 74 +++++++++++-- src/dbi.h | 8 +- src/repo.c | 141 +++++++++++++++++++++++++ src/repo.h | 20 ++++ src/rest.c | 331 +++++++++++++++++++++++++++++++++++------------------------ src/schema.c | 30 ++++++ 8 files changed, 461 insertions(+), 157 deletions(-) create mode 100644 src/repo.c create mode 100644 src/repo.h diff --git a/Makefile.am b/Makefile.am index 2dc6fbb..944ebbb 100644 --- a/Makefile.am +++ b/Makefile.am @@ -10,6 +10,7 @@ ogserver_SOURCES= src/ogAdmServer.c \ src/schedule.c \ src/schema.c \ src/utils.c \ + src/repo.c \ src/rest.c \ src/client.c \ src/json.c \ diff --git a/src/client.c b/src/client.c index d5e0391..675be74 100644 --- a/src/client.c +++ b/src/client.c @@ -621,15 +621,15 @@ static bool og_dbi_update_image(struct og_dbi *dbi, const struct og_image_legacy *img_info, const char *computer_id) { + int repo_id, sw_id, repo_alias; const char *msglog; dbi_result result; - int repo_id, sw_id; uint32_t revision; /* find repository identifier by repository ip and computer ID. */ result = dbi_conn_queryf(dbi->conn, - "SELECT repositorios.idrepositorio" - " FROM repositorios" + "SELECT repositorios.idrepositorio, repositorios.alias" + " FROM repositorios" " LEFT JOIN ordenadores USING (idrepositorio)" " WHERE repositorios.ip='%s' AND ordenadores.idordenador=%s", img_info->repo, computer_id); @@ -646,7 +646,12 @@ static bool og_dbi_update_image(struct og_dbi *dbi, dbi_result_free(result); return false; } - repo_id = dbi_result_get_uint(result, "idrepositorio"); + repo_alias = dbi_result_get_uint(result, "alias"); + if (repo_alias) + repo_id = repo_alias; + else + repo_id = dbi_result_get_uint(result, "idrepositorio"); + dbi_result_free(result); /* find software id by computer ID, disk number and partition. */ diff --git a/src/dbi.c b/src/dbi.c index 9eb1a39..f4f9ffa 100644 --- a/src/dbi.c +++ b/src/dbi.c @@ -270,34 +270,88 @@ bool og_dbi_get_image(struct og_dbi *dbi, struct og_image *image) } int og_dbi_get_repository_ip(const struct og_dbi *dbi, const uint32_t repo_id, - char *repository_ip) + const char *client_ip, char *repository_ip) { - const char *msglog, *dbi_repository_ip; + const char *msglog, *netmask_ip, *repo_ip; + struct in_addr client, netmask, repo; + bool found = false; dbi_result result; + if (inet_aton(client_ip, &client) < 0) { + syslog(LOG_ERR, "failed to parse client IP (%s:%d)\n", + __func__, __LINE__); + return -1; + } + result = dbi_conn_queryf(dbi->conn, - "SELECT ip FROM repositorios WHERE idrepositorio = %u", - repo_id); + "SELECT aulas.netmask FROM aulas " + "INNER JOIN ordenadores ON ordenadores.idaula = aulas.idaula " + "WHERE ordenadores.ip = '%s'", client_ip); if (!result) { dbi_conn_error(dbi->conn, &msglog); - syslog(LOG_ERR, "failed to query database (%s:%d) %s\n", + syslog(LOG_ERR, "failed to get netmask (%s:%d) %s\n", __func__, __LINE__, msglog); return -1; } if (!dbi_result_next_row(result)) { + syslog(LOG_ERR, "netmask does not exist in database (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return -1; + } + + netmask_ip = dbi_result_get_string(result, "netmask"); + if (inet_aton(netmask_ip, &netmask) < 0) { + syslog(LOG_ERR, "failed to parse netmask (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return -1; + } + + dbi_result_free(result); + + result = dbi_conn_queryf(dbi->conn, + "SELECT ip FROM repositorios WHERE idrepositorio = %u OR alias = %u", + repo_id, repo_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; + } + + while (dbi_result_next_row(result) > 0) { + repo_ip = dbi_result_get_string(result, "ip"); + + if (inet_aton(repo_ip, &repo) < 0) { + syslog(LOG_ERR, "failed to get repository IP (%s:%d)\n", + __func__, __LINE__); + dbi_result_free(result); + return -1; + } + client.s_addr &= netmask.s_addr; + + if (client.s_addr != (repo.s_addr & netmask.s_addr)) + continue; + + found = true; + break; + } + + if (!found) { syslog(LOG_ERR, - "repository with id %u does not exist (%s:%d) %s\n", - repo_id, __func__, __LINE__, msglog); + "cannot find repository IP with repository ID %u for client %s (%s:%d)\n", + repo_id, client_ip, __func__, __LINE__); dbi_result_free(result); return -1; } - dbi_repository_ip = dbi_result_get_string(result, "ip"); - snprintf(repository_ip, OG_DB_IP_MAXLEN + 1, "%s", dbi_repository_ip); - + snprintf(repository_ip, OG_DB_IP_MAXLEN + 1, "%s", repo_ip); dbi_result_free(result); + syslog(LOG_INFO, "using repository with ID %u and IP %s for computer %s\n", + repo_id, repository_ip, client_ip); + return 0; } diff --git a/src/dbi.h b/src/dbi.h index e16e5d1..81eac3e 100644 --- a/src/dbi.h +++ b/src/dbi.h @@ -127,12 +127,6 @@ struct og_folder { char name[OG_DB_FOLDER_NAME_MAXLEN + 1]; }; -struct og_repository { - unsigned int center; - char name[OG_DB_REPO_NAME_MAXLEN]; - char ip[OG_DB_IP_MAXLEN]; -}; - struct in_addr; int og_dbi_get_computer_info(struct og_dbi *dbi, struct og_computer *computer, struct in_addr addr); @@ -145,6 +139,6 @@ int og_dbi_add_image(struct og_dbi *dbi, struct og_image *image); int og_dbi_schema_update(void); int og_dbi_get_repository_ip(const struct og_dbi *dbi, const uint32_t repo_id, - char *repository_ip); + const char *client_ip, char *repository_ip); #endif diff --git a/src/repo.c b/src/repo.c new file mode 100644 index 0000000..d2b55cb --- /dev/null +++ b/src/repo.c @@ -0,0 +1,141 @@ +/* + * Copyright (C) 2020-2021 Soleta Networks + * + * This program is free software: you can redistribute it and/or modify it under + * the terms of the GNU Affero General Public License as published by the + * Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + */ + +#include +#include +#include +#include +#include +#include +#include "cfg.h" +#include "list.h" +#include "repo.h" +#include "dbi.h" + +static struct og_repo *og_repo_alloc(uint32_t id, const char *name, + struct in_addr *addr) +{ + struct og_repo *repo; + + repo = calloc(1, sizeof(struct og_repo)); + if (!repo) + return NULL; + + repo->name = strdup(name); + repo->id = id; + repo->addr[0] = *addr; + repo->num_ips++; + + return repo; +} + +static int og_repo_add_ip(struct og_repo *repo, struct in_addr *addr) +{ + if (repo->num_ips > OG_ADDR_REPO_MAX) + return -1; + + repo->addr[repo->num_ips++] = *addr; + + return 0; +} + +static struct og_repo *og_repo_find(uint32_t id, struct list_head *repo_list) +{ + struct og_repo *repo; + + list_for_each_entry(repo, repo_list, list) { + if (repo->id == id) + return repo; + } + + return NULL; +} + +int og_repo_list(struct list_head *repo_list) +{ + const char *name, *ip; + struct og_repo *repo; + struct in_addr addr; + const char *msglog; + struct og_dbi *dbi; + uint32_t id, alias; + dbi_result result; + + dbi = og_dbi_open(&ogconfig.db); + if (!dbi) { + syslog(LOG_ERR, "cannot open connection database (%s:%d)\n", + __func__, __LINE__); + return -1; + } + + result = dbi_conn_queryf(dbi->conn, + "SELECT idrepositorio, ip, nombrerepositorio, alias " + "FROM repositorios"); + 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; + } + + while (dbi_result_next_row(result)) { + id = dbi_result_get_ulonglong(result, "idrepositorio"); + ip = dbi_result_get_string(result, "ip"); + name = dbi_result_get_string(result, "nombrerepositorio"); + alias = dbi_result_get_ulonglong(result, "alias"); + + if (inet_aton(ip, &addr) < 0) { + syslog(LOG_ERR, "malformed IP in repo %s\n", name); + goto err_repo_list; + } + + if (alias) + id = alias; + + repo = og_repo_find(id, repo_list); + if (repo) { + if (og_repo_add_ip(repo, &addr) < 0) { + syslog(LOG_ERR, "too many IPs in repo %s\n", + repo->name); + goto err_repo_list; + } + continue; + } + + repo = og_repo_alloc(id, name, &addr); + if (!repo) + goto err_repo_list; + + list_add_tail(&repo->list, repo_list); + } + + dbi_result_free(result); + og_dbi_close(dbi); + + return 0; + +err_repo_list: + og_repo_free_list(repo_list); + dbi_result_free(result); + og_dbi_close(dbi); + + return -1; +} + +void og_repo_free_list(struct list_head *repo_list) +{ + struct og_repo *repo, *next; + + list_for_each_entry_safe(repo, next, repo_list, list) { + list_del(&repo->list); + free((void *)repo->name); + free(repo); + } +} diff --git a/src/repo.h b/src/repo.h new file mode 100644 index 0000000..08b6260 --- /dev/null +++ b/src/repo.h @@ -0,0 +1,20 @@ +#ifndef _OG_REPO_H_ +#define _OG_REPO_H_ + +#include +#include "list.h" + +#define OG_ADDR_REPO_MAX 16 + +struct og_repo { + struct list_head list; + const char *name; + uint32_t id; + struct in_addr addr[OG_ADDR_REPO_MAX]; + int num_ips; +}; + +int og_repo_list(struct list_head *repo_list); +void og_repo_free_list(struct list_head *repo_list); + +#endif diff --git a/src/rest.c b/src/rest.c index ad7573b..f714e0f 100644 --- a/src/rest.c +++ b/src/rest.c @@ -15,6 +15,7 @@ #include "core.h" #include "wol.h" #include "cfg.h" +#include "repo.h" #include "schedule.h" #include "legacy.h" #include @@ -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; diff --git a/src/schema.c b/src/schema.c index 7390e27..a41f062 100644 --- a/src/schema.c +++ b/src/schema.c @@ -369,6 +369,35 @@ static int og_dbi_schema_v8(struct og_dbi *dbi) return 0; } +static int og_dbi_schema_v9(struct og_dbi *dbi) +{ + const char *msglog; + dbi_result result; + + syslog(LOG_DEBUG, "Adding alias to repositorios\n"); + result = dbi_conn_query(dbi->conn, + "ALTER TABLE `repositorios` " + "ADD `alias` int(11) NULL;"); + if (!result) { + dbi_conn_error(dbi->conn, &msglog); + syslog(LOG_INFO, "Error when adding alias (%s:%d) %s\n", + __func__, __LINE__, msglog); + return -1; + } + dbi_result_free(result); + + result = dbi_conn_query(dbi->conn, "UPDATE version SET version = 9"); + 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); @@ -381,6 +410,7 @@ static struct og_schema_version { { .version = 6, .update = og_dbi_schema_v6 }, { .version = 7, .update = og_dbi_schema_v7, }, { .version = 8, .update = og_dbi_schema_v8, }, + { .version = 9, .update = og_dbi_schema_v9, }, { 0, NULL }, }; -- cgit v1.2.3-18-g5258