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

Last change on this file since a00eccc was 12d8fff, checked in by OpenGnSys Support Team <soporte-og@…>, 3 years ago

#1037 Add disk type

Add ogServer support for parsing and storing in the DB disk type data
from ogClient refresh response.

See also commits with #1037 in ogClient and WebConsole? repo.

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