summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorOpenGnSys Support Team <soporte-og@soleta.eu>2024-08-21 20:19:23 +0200
committerOpenGnSys Support Team <soporte-og@soleta.eu>2024-08-21 21:58:48 +0200
commit5eba9f4e1b44fb0d4b4962c2241fe9391e202d7b (patch)
tree1940f98fcf9d24b1046e425b77eddc5bab624ee4
parent4e0f9aac9e2883a992469f5b2b231ecb14b30183 (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.
-rw-r--r--Makefile.am1
-rw-r--r--src/client.c13
-rw-r--r--src/dbi.c74
-rw-r--r--src/dbi.h8
-rw-r--r--src/repo.c141
-rw-r--r--src/repo.h20
-rw-r--r--src/rest.c331
-rw-r--r--src/schema.c30
8 files changed, 461 insertions, 157 deletions
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 <info@soleta.eu>
+ *
+ * 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 <stdint.h>
+#include <syslog.h>
+#include <string.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#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 <stdint.h>
+#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 <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;
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 },
};