source: ogServer-Git/src/client.c @ be9816e

Last change on this file since be9816e was 24e6fbf, checked in by OpenGnSys Support Team <soporte-og@…>, 4 years ago

#1008 Restore support for 4 disks and 16 partitions

ogServer expects to receive information of 1 disk and 4 partitions
from ogClient. Previous ogServer versions support several disks and
partitions.

Add ogServer support for 4 disks and 16 partitions.

  • Property mode set to 100644
File size: 16.4 KB
Line 
1/*
2 * Copyright (C) 2020 Soleta Networks <info@soleta.eu>
3 *
4 * This program is free software: you can redistribute it and/or modify it under
5 * the terms of the GNU Affero General Public License as published by the
6 * Free Software Foundation, version 3.
7 */
8
9#include "ogAdmServer.h"
10#include "cfg.h"
11#include "dbi.h"
12#include "utils.h"
13#include "list.h"
14#include "rest.h"
15#include "json.h"
16#include "schedule.h"
17#include <syslog.h>
18#include <sys/ioctl.h>
19#include <ifaddrs.h>
20#include <sys/types.h>
21#include <sys/stat.h>
22#include <fcntl.h>
23#include <jansson.h>
24#include <time.h>
25
26static int og_resp_probe(struct og_client *cli, json_t *data)
27{
28        const char *status = NULL;
29        const char *key;
30        json_t *value;
31        int err = 0;
32
33        if (json_typeof(data) != JSON_OBJECT)
34                return -1;
35
36        json_object_foreach(data, key, value) {
37                if (!strcmp(key, "status")) {
38                        err = og_json_parse_string(value, &status);
39                        if (err < 0)
40                                return err;
41                } else {
42                        return -1;
43                }
44        }
45
46        if (!strcmp(status, "BSY"))
47                cli->status = OG_CLIENT_STATUS_BUSY;
48        else if (!strcmp(status, "OPG"))
49                cli->status = OG_CLIENT_STATUS_OGLIVE;
50        else if (!strcmp(status, "VDI"))
51                cli->status = OG_CLIENT_STATUS_VIRTUAL;
52
53        return status ? 0 : -1;
54}
55
56static int og_resp_shell_run(struct og_client *cli, json_t *data)
57{
58        const char *output = NULL;
59        char filename[4096];
60        const char *key;
61        json_t *value;
62        int err = -1;
63        FILE *file;
64
65        if (json_typeof(data) != JSON_OBJECT)
66                return -1;
67
68        json_object_foreach(data, key, value) {
69                if (!strcmp(key, "out")) {
70                        err = og_json_parse_string(value, &output);
71                        if (err < 0)
72                                return err;
73                } else {
74                        return -1;
75                }
76        }
77
78        if (!output) {
79                syslog(LOG_ERR, "%s:%d: malformed json response\n",
80                       __FILE__, __LINE__);
81                return -1;
82        }
83
84        sprintf(filename, "/tmp/_Seconsola_%s", inet_ntoa(cli->addr.sin_addr));
85        file = fopen(filename, "wt");
86        if (!file) {
87                syslog(LOG_ERR, "cannot open file %s: %s\n",
88                       filename, strerror(errno));
89                return -1;
90        }
91
92        fprintf(file, "%s", output);
93        fclose(file);
94
95        return 0;
96}
97
98struct og_computer_legacy  {
99        char center[OG_DB_INT_MAXLEN + 1];
100        char id[OG_DB_INT_MAXLEN + 1];
101        char hardware[8192];
102};
103
104static int og_resp_hardware(json_t *data, struct og_client *cli)
105{
106        struct og_computer_legacy legacy = {};
107        struct og_computer computer = {};
108        const char *hardware = NULL;
109        struct og_dbi *dbi;
110        const char *key;
111        json_t *value;
112        int err = 0;
113        bool res;
114
115        if (json_typeof(data) != JSON_OBJECT)
116                return -1;
117
118        json_object_foreach(data, key, value) {
119                if (!strcmp(key, "hardware")) {
120                        err = og_json_parse_string(value, &hardware);
121                        if (err < 0)
122                                return -1;
123                } else {
124                        return -1;
125                }
126        }
127
128        if (!hardware) {
129                syslog(LOG_ERR, "malformed response json\n");
130                return -1;
131        }
132
133        dbi = og_dbi_open(&ogconfig.db);
134        if (!dbi) {
135                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
136                       __func__, __LINE__);
137                return -1;
138        }
139
140        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
141        if (err < 0) {
142                og_dbi_close(dbi);
143                return -1;
144        }
145
146        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
147        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
148        snprintf(legacy.hardware, sizeof(legacy.hardware), "%s", hardware);
149
150        res = actualizaHardware(dbi, legacy.hardware, legacy.id, computer.name,
151                                legacy.center);
152        og_dbi_close(dbi);
153
154        if (!res) {
155                syslog(LOG_ERR, "Problem updating client configuration\n");
156                return -1;
157        }
158
159        return 0;
160}
161
162struct og_software_legacy {
163        char software[8192];
164        char center[OG_DB_INT_MAXLEN + 1];
165        char part[OG_DB_SMALLINT_MAXLEN + 1];
166        char id[OG_DB_INT_MAXLEN + 1];
167};
168
169static int og_resp_software(json_t *data, struct og_client *cli)
170{
171        struct og_software_legacy legacy = {};
172        struct og_computer computer = {};
173        const char *partition = NULL;
174        const char *software = NULL;
175        struct og_dbi *dbi;
176        const char *key;
177        json_t *value;
178        int err = 0;
179        bool res;
180
181        if (json_typeof(data) != JSON_OBJECT)
182                return -1;
183
184        json_object_foreach(data, key, value) {
185                if (!strcmp(key, "software"))
186                        err = og_json_parse_string(value, &software);
187                else if (!strcmp(key, "partition"))
188                        err = og_json_parse_string(value, &partition);
189                else
190                        return -1;
191
192                if (err < 0)
193                        return -1;
194        }
195
196        if (!software || !partition) {
197                syslog(LOG_ERR, "malformed response json\n");
198                return -1;
199        }
200
201        dbi = og_dbi_open(&ogconfig.db);
202        if (!dbi) {
203                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
204                       __func__, __LINE__);
205                return -1;
206        }
207
208        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
209        if (err < 0) {
210                og_dbi_close(dbi);
211                return -1;
212        }
213
214        snprintf(legacy.software, sizeof(legacy.software), "%s", software);
215        snprintf(legacy.part, sizeof(legacy.part), "%s", partition);
216        snprintf(legacy.id, sizeof(legacy.id), "%d", computer.id);
217        snprintf(legacy.center, sizeof(legacy.center), "%d", computer.center);
218
219        res = actualizaSoftware(dbi, legacy.software, legacy.part, legacy.id,
220                                computer.name, legacy.center);
221        og_dbi_close(dbi);
222
223        if (!res) {
224                syslog(LOG_ERR, "Problem updating client configuration\n");
225                return -1;
226        }
227
228        return 0;
229}
230
231#define OG_PARAMS_RESP_REFRESH  (OG_PARAM_PART_DISK |           \
232                                 OG_PARAM_PART_NUMBER |         \
233                                 OG_PARAM_PART_CODE |           \
234                                 OG_PARAM_PART_FILESYSTEM |     \
235                                 OG_PARAM_PART_OS |             \
236                                 OG_PARAM_PART_SIZE |           \
237                                 OG_PARAM_PART_USED_SIZE)
238
239static int og_json_parse_partition_array(json_t *value,
240                                         struct og_partition *partitions)
241{
242        json_t *element;
243        int i, err;
244
245        if (json_typeof(value) != JSON_ARRAY)
246                return -1;
247
248        for (i = 0; i < json_array_size(value) && i < OG_PARTITION_MAX; i++) {
249                element = json_array_get(value, i);
250
251                err = og_json_parse_partition(element, &partitions[i],
252                                              OG_PARAMS_RESP_REFRESH);
253                if (err < 0)
254                        return err;
255        }
256
257        return 0;
258}
259
260static int og_dbi_queue_autorun(uint32_t computer_id, uint32_t proc_id)
261{
262        struct og_task dummy_task = {
263                .scope          = computer_id,
264                .type_scope     = AMBITO_ORDENADORES,
265                .procedure_id   = proc_id,
266        };
267        struct og_dbi *dbi;
268
269        dbi = og_dbi_open(&ogconfig.db);
270        if (!dbi) {
271                syslog(LOG_ERR, "cannot open connection database "
272                                "(%s:%d)\n", __func__, __LINE__);
273                return -1;
274        }
275        if (og_dbi_queue_procedure(dbi, &dummy_task)) {
276                og_dbi_close(dbi);
277                return -1;
278        }
279        og_dbi_close(dbi);
280
281        return 0;
282}
283
284static int og_resp_refresh(json_t *data, struct og_client *cli)
285{
286        struct og_partition partitions[OG_PARTITION_MAX] = {};
287        struct og_partition disks[OG_DISK_MAX] = {};
288        const char *serial_number = NULL;
289        struct og_computer computer = {};
290        char cfg[4096] = {};
291        struct og_dbi *dbi;
292        const char *key;
293        unsigned int i;
294        json_t *value;
295        int err = 0;
296        bool res;
297
298        if (json_typeof(data) != JSON_OBJECT)
299                return -1;
300
301        json_object_foreach(data, key, value) {
302                if (!strcmp(key, "disk_setup")) {
303                        err = og_json_parse_partition_array(value, disks);
304                } else if (!strcmp(key, "partition_setup")) {
305                        err = og_json_parse_partition_array(value, partitions);
306                } else if (!strcmp(key, "serial_number")) {
307                        err = og_json_parse_string(value, &serial_number);
308                } else {
309                        return -1;
310                }
311
312                if (err < 0)
313                        return err;
314        }
315
316        if (strlen(serial_number) > 0)
317                snprintf(cfg, sizeof(cfg), "ser=%s\n", serial_number);
318
319        for (i = 0; i < OG_DISK_MAX; i++) {
320                if (!disks[i].disk || !disks[i].number ||
321                    !disks[i].code || !disks[i].filesystem ||
322                    !disks[i].os || !disks[i].size ||
323                    !disks[i].used_size)
324                        continue;
325
326                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
327                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
328                         disks[i].disk, disks[i].number,
329                         disks[i].code, disks[i].filesystem,
330                         disks[i].os, disks[i].size,
331                         disks[i].used_size);
332        }
333
334        for (i = 0; i < OG_PARTITION_MAX; i++) {
335                if (!partitions[i].disk || !partitions[i].number ||
336                    !partitions[i].code || !partitions[i].filesystem ||
337                    !partitions[i].os || !partitions[i].size ||
338                    !partitions[i].used_size)
339                        continue;
340
341                snprintf(cfg + strlen(cfg), sizeof(cfg) - strlen(cfg),
342                         "disk=%s\tpar=%s\tcpt=%s\tfsi=%s\tsoi=%s\ttam=%s\tuso=%s\n",
343                         partitions[i].disk, partitions[i].number,
344                         partitions[i].code, partitions[i].filesystem,
345                         partitions[i].os, partitions[i].size,
346                         partitions[i].used_size);
347        }
348
349        dbi = og_dbi_open(&ogconfig.db);
350        if (!dbi) {
351                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
352                                  __func__, __LINE__);
353                return -1;
354        }
355
356        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
357        if (err < 0) {
358                og_dbi_close(dbi);
359                return -1;
360        }
361
362        res = actualizaConfiguracion(dbi, cfg, computer.id);
363        og_dbi_close(dbi);
364
365        if (!res) {
366                syslog(LOG_ERR, "Problem updating client configuration\n");
367                return -1;
368        }
369
370        if (!cli->autorun && computer.procedure_id) {
371                cli->autorun = true;
372
373                if (og_dbi_queue_autorun(computer.id, computer.procedure_id))
374                        return -1;
375        }
376
377        return 0;
378}
379
380static int update_image_info(struct og_dbi *dbi, const char *image_id,
381                             const char *clonator, const char *compressor,
382                             const char *filesystem, const uint64_t datasize)
383{
384        const char *msglog;
385        dbi_result result;
386
387        result = dbi_conn_queryf(dbi->conn,
388                "UPDATE imagenes"
389                "   SET clonator='%s', compressor='%s',"
390                "       filesystem='%s', datasize=%lld"
391                " WHERE idimagen=%s", clonator, compressor, filesystem,
392                datasize, image_id);
393
394        if (!result) {
395                dbi_conn_error(dbi->conn, &msglog);
396                syslog(LOG_ERR, "failed to query database (%s:%d) %s\n",
397                       __func__, __LINE__, msglog);
398                return -1;
399        }
400        dbi_result_free(result);
401
402        return 0;
403}
404
405static int og_resp_image_create(json_t *data, struct og_client *cli)
406{
407        struct og_software_legacy soft_legacy;
408        struct og_image_legacy img_legacy;
409        struct og_computer computer = {};
410        const char *compressor = NULL;
411        const char *filesystem = NULL;
412        const char *partition = NULL;
413        const char *software = NULL;
414        const char *image_id = NULL;
415        const char *clonator = NULL;
416        const char *disk = NULL;
417        const char *code = NULL;
418        const char *name = NULL;
419        const char *repo = NULL;
420        uint64_t datasize = 0;
421        struct og_dbi *dbi;
422        const char *key;
423        json_t *value;
424        int err = 0;
425        bool res;
426
427        if (json_typeof(data) != JSON_OBJECT)
428                return -1;
429
430        json_object_foreach(data, key, value) {
431                if (!strcmp(key, "software"))
432                        err = og_json_parse_string(value, &software);
433                else if (!strcmp(key, "partition"))
434                        err = og_json_parse_string(value, &partition);
435                else if (!strcmp(key, "disk"))
436                        err = og_json_parse_string(value, &disk);
437                else if (!strcmp(key, "code"))
438                        err = og_json_parse_string(value, &code);
439                else if (!strcmp(key, "id"))
440                        err = og_json_parse_string(value, &image_id);
441                else if (!strcmp(key, "name"))
442                        err = og_json_parse_string(value, &name);
443                else if (!strcmp(key, "repository"))
444                        err = og_json_parse_string(value, &repo);
445                else if (!strcmp(key, "clonator"))
446                        err = og_json_parse_string(value, &clonator);
447                else if (!strcmp(key, "compressor"))
448                        err = og_json_parse_string(value, &compressor);
449                else if (!strcmp(key, "filesystem"))
450                        err = og_json_parse_string(value, &filesystem);
451                else if (!strcmp(key, "datasize"))
452                        err = og_json_parse_uint64(value, &datasize);
453                else
454                        return -1;
455
456                if (err < 0)
457                        return err;
458        }
459
460        if (!software || !partition || !disk || !code || !image_id || !name ||
461            !repo || !clonator || !compressor || !filesystem || !datasize) {
462                syslog(LOG_ERR, "malformed response json\n");
463                return -1;
464        }
465
466        dbi = og_dbi_open(&ogconfig.db);
467        if (!dbi) {
468                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
469                       __func__, __LINE__);
470                return -1;
471        }
472
473        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
474        if (err < 0) {
475                og_dbi_close(dbi);
476                return -1;
477        }
478
479        snprintf(soft_legacy.center, sizeof(soft_legacy.center), "%d",
480                 computer.center);
481        snprintf(soft_legacy.software, sizeof(soft_legacy.software), "%s",
482                 software);
483        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
484                 image_id);
485        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
486        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
487        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
488        snprintf(img_legacy.code, sizeof(img_legacy.code), "%s", code);
489        snprintf(img_legacy.name, sizeof(img_legacy.name), "%s", name);
490        snprintf(img_legacy.repo, sizeof(img_legacy.repo), "%s", repo);
491
492        res = actualizaSoftware(dbi,
493                                soft_legacy.software,
494                                img_legacy.part,
495                                soft_legacy.id,
496                                computer.name,
497                                soft_legacy.center);
498        if (!res) {
499                og_dbi_close(dbi);
500                syslog(LOG_ERR, "Problem updating client configuration\n");
501                return -1;
502        }
503
504        res = actualizaCreacionImagen(dbi,
505                                      img_legacy.image_id,
506                                      img_legacy.disk,
507                                      img_legacy.part,
508                                      img_legacy.code,
509                                      img_legacy.repo,
510                                      soft_legacy.id);
511        if (!res) {
512                og_dbi_close(dbi);
513                syslog(LOG_ERR, "Problem updating client configuration\n");
514                return -1;
515        }
516
517        res = update_image_info(dbi, image_id, clonator, compressor,
518                                filesystem, datasize);
519        og_dbi_close(dbi);
520
521        if (res) {
522                syslog(LOG_ERR, "Problem updating image info\n");
523                return -1;
524        }
525
526        return 0;
527}
528
529static int og_resp_image_restore(json_t *data, struct og_client *cli)
530{
531        struct og_software_legacy soft_legacy;
532        struct og_image_legacy img_legacy;
533        struct og_computer computer = {};
534        const char *partition = NULL;
535        const char *image_id = NULL;
536        const char *disk = NULL;
537        dbi_result query_result;
538        struct og_dbi *dbi;
539        const char *key;
540        json_t *value;
541        int err = 0;
542        bool res;
543
544        if (json_typeof(data) != JSON_OBJECT)
545                return -1;
546
547        json_object_foreach(data, key, value) {
548                if (!strcmp(key, "partition"))
549                        err = og_json_parse_string(value, &partition);
550                else if (!strcmp(key, "disk"))
551                        err = og_json_parse_string(value, &disk);
552                else if (!strcmp(key, "image_id"))
553                        err = og_json_parse_string(value, &image_id);
554                else
555                        return -1;
556
557                if (err < 0)
558                        return err;
559        }
560
561        if (!partition || !disk || !image_id) {
562                syslog(LOG_ERR, "malformed response json\n");
563                return -1;
564        }
565
566        dbi = og_dbi_open(&ogconfig.db);
567        if (!dbi) {
568                syslog(LOG_ERR, "cannot open connection database (%s:%d)\n",
569                       __func__, __LINE__);
570                return -1;
571        }
572
573        query_result = dbi_conn_queryf(dbi->conn,
574                                       "SELECT idperfilsoft FROM imagenes "
575                                       " WHERE idimagen='%s'",
576                                       image_id);
577        if (!query_result) {
578                og_dbi_close(dbi);
579                syslog(LOG_ERR, "failed to query database\n");
580                return -1;
581        }
582        if (!dbi_result_next_row(query_result)) {
583                dbi_result_free(query_result);
584                og_dbi_close(dbi);
585                syslog(LOG_ERR, "software profile does not exist in database\n");
586                return -1;
587        }
588        snprintf(img_legacy.software_id, sizeof(img_legacy.software_id),
589                 "%d", dbi_result_get_uint(query_result, "idperfilsoft"));
590        dbi_result_free(query_result);
591
592        err = og_dbi_get_computer_info(dbi, &computer, cli->addr.sin_addr);
593        if (err < 0) {
594                og_dbi_close(dbi);
595                return -1;
596        }
597
598        snprintf(img_legacy.image_id, sizeof(img_legacy.image_id), "%s",
599                 image_id);
600        snprintf(img_legacy.part, sizeof(img_legacy.part), "%s", partition);
601        snprintf(img_legacy.disk, sizeof(img_legacy.disk), "%s", disk);
602        snprintf(soft_legacy.id, sizeof(soft_legacy.id), "%d", computer.id);
603
604        res = actualizaRestauracionImagen(dbi,
605                                          img_legacy.image_id,
606                                          img_legacy.disk,
607                                          img_legacy.part,
608                                          soft_legacy.id,
609                                          img_legacy.software_id);
610        og_dbi_close(dbi);
611
612        if (!res) {
613                syslog(LOG_ERR, "Problem updating client configuration\n");
614                return -1;
615        }
616
617        return 0;
618}
619
620int og_agent_state_process_response(struct og_client *cli)
621{
622        json_error_t json_err;
623        json_t *root;
624        int err = -1;
625        char *body;
626
627        if (!strncmp(cli->buf, "HTTP/1.0 202 Accepted",
628                     strlen("HTTP/1.0 202 Accepted"))) {
629                og_dbi_update_action(cli->last_cmd_id, true);
630                cli->last_cmd_id = 0;
631                return 1;
632        }
633
634        if (strncmp(cli->buf, "HTTP/1.0 200 OK", strlen("HTTP/1.0 200 OK"))) {
635                og_dbi_update_action(cli->last_cmd_id, false);
636                cli->last_cmd_id = 0;
637                return -1;
638        }
639        og_dbi_update_action(cli->last_cmd_id, true);
640        cli->last_cmd_id = 0;
641
642        if (!cli->content_length) {
643                cli->last_cmd = OG_CMD_UNSPEC;
644                return 0;
645        }
646
647        body = strstr(cli->buf, "\r\n\r\n") + 4;
648
649        root = json_loads(body, 0, &json_err);
650        if (!root) {
651                syslog(LOG_ERR, "%s:%d: malformed json line %d: %s\n",
652                       __FILE__, __LINE__, json_err.line, json_err.text);
653                return -1;
654        }
655
656        switch (cli->last_cmd) {
657        case OG_CMD_PROBE:
658                err = og_resp_probe(cli, root);
659                break;
660        case OG_CMD_SHELL_RUN:
661                err = og_resp_shell_run(cli, root);
662                break;
663        case OG_CMD_HARDWARE:
664                err = og_resp_hardware(root, cli);
665                break;
666        case OG_CMD_SOFTWARE:
667                err = og_resp_software(root, cli);
668                break;
669        case OG_CMD_REFRESH:
670                err = og_resp_refresh(root, cli);
671                break;
672        case OG_CMD_SETUP:
673                err = og_resp_refresh(root, cli);
674                break;
675        case OG_CMD_IMAGE_CREATE:
676                err = og_resp_image_create(root, cli);
677                break;
678        case OG_CMD_IMAGE_RESTORE:
679                err = og_resp_image_restore(root, cli);
680                break;
681        default:
682                err = -1;
683                break;
684        }
685
686        cli->last_cmd = OG_CMD_UNSPEC;
687
688        return err;
689}
Note: See TracBrowser for help on using the repository browser.