OSDN Git Service

f1b7dfb42c0be7eeec7911bbf5ebfe03fa57a017
[openpts/openpts.git] / src / target.c
1 /*
2  * This file is part of the OpenPTS project.
3  *
4  * The Initial Developer of the Original Code is International
5  * Business Machines Corporation. Portions created by IBM
6  * Corporation are Copyright (C) 2010 International Business
7  * Machines Corporation. All Rights Reserved.
8  *
9  * This program is free software; you can redistribute it and/or modify
10  * it under the terms of the Common Public License as published by
11  * IBM Corporation; either version 1 of the License, or (at your option)
12  * any later version.
13  *
14  * This program is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17  * Common Public License for more details.
18  *
19  * You should have received a copy of the Common Public License
20  * along with this program; if not, a copy can be viewed at
21  * http://www.opensource.org/licenses/cpl1.0.php.
22  */
23
24 /**
25  * \file src/target.c
26  * \brief target(collector)
27  * @author Seiji Munetoh <munetoh@users.sourceforge.jp>
28  * @date 2011-06-22
29  * cleanup 2011-07-06 SM
30  *
31  * branch from uuid.c
32  *
33  * Unit Test: NA
34  *
35  */
36
37 #include <stdio.h>
38 #include <string.h>
39 #include <time.h>
40 #include <sys/stat.h>
41
42 #include <sys/types.h>
43 #include <fcntl.h>
44
45 #include <errno.h>
46
47
48 // DIR
49 #include <unistd.h>
50 #include <dirent.h>
51
52 #include <openpts.h>
53
54 #define SEP_LINE "-----------------------------------------------------------------------------------------"
55
56 /**
57  *
58  *  @retval 0 - time1 <= time2, time1 is same or old
59  *  @retval 1 - time1 > time2   time1 is new
60  */
61 int cmpDateTime(PTS_DateTime *time1, PTS_DateTime *time2) {
62     uint64_t t1 = 0;
63     uint64_t t2 = 0;
64
65     t1 += time1->year;
66     t1 = t1 << 16;
67     t1 += time1->mon;
68     t1 = t1 << 8;
69     t1 += time1->mday;
70     t1 = t1 << 8;
71     t1 += time1->hour;
72     t1 = t1 << 8;
73     t1 += time1->min;
74     t1 = t1 << 8;
75     t1 += time1->sec;
76
77     t2 += time2->year;
78     t2 = t2 << 16;
79     t2 += time2->mon;
80     t2 = t2 << 8;
81     t2 += time2->mday;
82     t2 = t2 << 8;
83     t2 += time2->hour;
84     t2 = t2 << 8;
85     t2 += time2->min;
86     t2 = t2 << 8;
87     t2 += time2->sec;
88
89     if (t1 > t2) {
90         return 1;
91     }
92
93     return 0;
94 }
95
96
97
98 /**
99  * selectUuidDir
100  *
101  * select UUID dir, e.g. 12877946-0682-11e0-b442-001f160c9c28
102  *
103  * @retval 0
104  * @retval 1 - hit
105  */
106 static int selectUuidDir(const struct dirent *entry) {
107     int len;
108 #ifndef __linux__
109     struct stat buffer;
110 #endif
111
112     /* skip . .. dirs */
113     if (0 == strcmp(".", entry->d_name)) return 0;
114     if (0 == strcmp("..", entry->d_name)) return 0;
115
116     /* skip bad dir name - by length */
117     len = strlen(entry->d_name);
118     // TODO ("UUID dirname len = %d, %s\n",len, entry->d_name);
119     if (len != 36) return 0;
120
121     // TODO not enough?, add test cases for the bad dir name
122
123     /* Dir HIT */
124     // TODO check the format
125 #ifndef __linux__
126     if (0 != stat(entry->d_name, &buffer)) return 0;
127     if (S_ISDIR(buffer.st_mode)) return 1;
128 #else
129     if (entry->d_type == DT_DIR) return 1;
130 #endif
131
132     return 0;
133 }
134
135 /**
136  * list/get RM
137  *
138  * CONFDIR/UUID/rmX.xml
139  *   conf->rm_num
140  *   conf->rm_uuid[]
141  *   conf->rm_date[]
142  *
143  *   conf->current_rm_uuid
144  *   conf->next_rm_uuid
145  *
146  * @retval PTS_SUCCESS
147  * @retval PTS_INTERNAL_ERROR
148  */
149 int getRmList(OPENPTS_CONFIG *conf, char * config_dir) {
150     int cnt = 0;
151     int dir_num;
152     struct dirent **dir_list;
153     int i, j;
154
155     char         *tmp_str_uuid;
156     PTS_UUID     *tmp_uuid;
157     PTS_DateTime *tmp_time;
158     int           tmp_state;
159     char         *tmp_dir;
160
161     OPENPTS_RMSET *rmset;
162     OPENPTS_RMSET *rmset1;
163     OPENPTS_RMSET *rmset2;
164
165     // printf("Show RMs by UUID\n");
166     // printf("config dir                  : %s\n", config_dir);
167
168     /* move to config dir */
169     if ((chdir(conf->config_dir)) != 0) {
170         fprintf(stderr, "Accessing config directory %s\n", conf->config_dir);
171         return PTS_INTERNAL_ERROR;
172     }
173
174     /* scan dirs */
175     dir_num = scandir(".", &dir_list, &selectUuidDir, NULL);
176     if ( dir_num == -1 ) {
177         fprintf(stderr, "no target data\n");
178         return PTS_INTERNAL_ERROR;
179     }
180
181     /* malloc */
182     // TODO alloc 1 more RMSET for update
183     conf->rmsets = (OPENPTS_RMSETS *) malloc(sizeof(OPENPTS_RMSETS) + sizeof(OPENPTS_RMSET) * (dir_num + 1) );
184     if (conf->rmsets == NULL) {
185         ERROR("no memory");
186         return PTS_INTERNAL_ERROR;
187     }
188     conf->rmsets->rmset_num = dir_num;
189
190     /* Set */
191     for (cnt = 0; cnt < dir_num; cnt++) {
192         rmset = &conf->rmsets->rmset[cnt];
193         if (rmset == NULL) {
194             ERROR("no memory cnt=%d\n", cnt);
195             return PTS_INTERNAL_ERROR;
196         }
197         rmset->str_uuid = smalloc(dir_list[cnt]->d_name);
198         rmset->uuid = getUuidFromString(dir_list[cnt]->d_name);
199         rmset->time = getDateTimeOfUuid(rmset->uuid);
200         rmset->state = OPENPTS_RM_STATE_UNKNOWN;
201         rmset->dir = getFullpathName(conf->config_dir, rmset->str_uuid);
202
203         /* check state */
204         if (conf->rm_uuid->str != NULL) {
205             /* check new RM 1st */
206             if (conf->newrm_uuid != NULL) {
207                 if (conf->newrm_uuid->str != NULL) {
208                     if (strcmp(conf->newrm_uuid->str, rmset->str_uuid) == 0) {
209                         rmset->state = OPENPTS_RM_STATE_NEW;
210                     }
211                 }
212             }
213
214             /* check current RM */
215             if (strcmp(conf->rm_uuid->str, rmset->str_uuid) == 0) {
216                 /* overrite if newrm = rm */
217                 // TODO ("HIT %s\n", conf->str_rm_uuid);
218                 rmset->state = OPENPTS_RM_STATE_NOW;
219             }
220         }
221
222         free(dir_list[cnt]);
223     }
224     free(dir_list);
225
226     /* sort (bub) */
227     for (i = 0; i< dir_num - 1; i++) {
228         for (j = dir_num - 1; j > i; j--) {
229             // printf("i=%d, j=%d\n",i,j);
230             rmset1 = &conf->rmsets->rmset[j-1];
231             rmset2 = &conf->rmsets->rmset[j];
232             if (cmpDateTime(rmset1->time, rmset2->time) > 0) {
233                 // printf("%d <-> %d\n", j-1, j);
234
235                 tmp_str_uuid = rmset2->str_uuid;
236                 tmp_uuid     = rmset2->uuid;
237                 tmp_time     = rmset2->time;
238                 tmp_state    = rmset2->state;
239                 tmp_dir      = rmset2->dir;
240
241                 rmset2->str_uuid = rmset1->str_uuid;
242                 rmset2->uuid     = rmset1->uuid;
243                 rmset2->time     = rmset1->time;
244                 rmset2->state    = rmset1->state;
245                 rmset2->dir      = rmset1->dir;
246
247                 rmset1->str_uuid = tmp_str_uuid;
248                 rmset1->uuid     = tmp_uuid;
249                 rmset1->time     = tmp_time;
250                 rmset1->state    = tmp_state;
251                 rmset1->dir      = tmp_dir;
252             }
253         }
254         //  printRmList(conf);
255     }
256
257     /* set current_id */
258     conf->rmsets->current_id = 0;
259     for (i = 0; i< dir_num; i++) {
260         rmset = &conf->rmsets->rmset[i];
261         if (rmset->state == OPENPTS_RM_STATE_NOW) {
262             conf->rmsets->current_id = i;
263         }
264     }
265
266     /* set old flag  id < current_id */
267     for (i = 0; i< conf->rmsets->current_id; i++) {
268         rmset = &conf->rmsets->rmset[i];
269         rmset->state = OPENPTS_RM_STATE_OLD;
270     }
271
272     /* set update_id */
273     conf->rmsets->update_id = 9999;  // TODO
274     for (i = conf->rmsets->current_id+1; i< dir_num; i++) {
275         rmset = &conf->rmsets->rmset[i];
276         if (rmset->state == OPENPTS_RM_STATE_NEW) {
277             conf->rmsets->update_id = i;
278         }
279     }
280
281     /* set trash  flag  id < current_id */
282     for (i = conf->rmsets->current_id + 1; i< dir_num && i < conf->rmsets->update_id; i++) {
283         rmset = &conf->rmsets->rmset[i];
284         rmset->state = OPENPTS_RM_STATE_TRASH;
285     }
286
287
288     return PTS_SUCCESS;
289 }
290
291 /**
292  * rm -r RM_dir
293  */
294 int rmRmsetDir(char * dir) {
295     int rc;
296     char buf[BUF_SIZE];
297
298     // DEBUG("rm -r %s\n", dir);
299     snprintf(buf, BUF_SIZE, "rm -r %s\n", dir);
300     rc = system(buf);
301     if (rc < 0) {
302         DEBUG("rmRmsetDir() - system failed, %s\n", buf);
303         return PTS_OS_ERROR;
304     }
305
306     return PTS_SUCCESS;
307 }
308
309 /**
310  * Purge RMs 
311  *
312  * @retval PTS_SUCCESS
313  * @retval PTS_OS_ERROR
314  */
315 int purgeRenewedRm(OPENPTS_CONFIG *conf) {
316     int cnt;
317     int state;
318     int num = 0;
319     OPENPTS_RMSET *rmset;
320     int rc;
321     int rc2 = PTS_SUCCESS;
322
323     num = conf->rmsets->rmset_num;
324
325     /* scan  */
326     for (cnt = 0; cnt < num; cnt++) {
327         rmset = &conf->rmsets->rmset[cnt];
328         state = rmset->state;
329
330         if (state == OPENPTS_RM_STATE_TRASH) {
331             printf("  purge %s\n", rmset->str_uuid);
332             rc = rmRmsetDir(rmset->dir);
333             if (rc != PTS_SUCCESS) {
334                 rc2 = PTS_OS_ERROR;
335             }
336         }
337     }
338     return rc2;
339 }
340
341
342 void printRmList(OPENPTS_CONFIG *conf, char *indent) {
343     int cnt;
344     PTS_DateTime *time;
345     int state;
346     OPENPTS_RMSET *rmset;
347     char * str_uuid;
348     int num = 0;
349
350     /* check */
351     if (conf == NULL) {
352         ERROR(" conf is NULL");
353         return;
354     }
355     if (conf->rmsets == NULL) {
356         ERROR(" conf->rmsets is NULL");
357         return;
358     }
359
360
361     num = conf->rmsets->rmset_num;
362
363     printf("%s  ID              UUID                        date(UTC)                status\n", indent);
364     printf("%s%s\n", indent, SEP_LINE);
365
366     /* Print  */
367     for (cnt = 0; cnt < num; cnt++) {
368         rmset = &conf->rmsets->rmset[cnt];
369
370         str_uuid = rmset->str_uuid;
371         time = rmset->time;
372         state = rmset->state;
373
374         printf("%s %3d %s %04d-%02d-%02d-%02d:%02d:%02d",
375             indent,
376             cnt,
377             str_uuid,
378             time->year + 1900,
379             time->mon + 1,
380             time->mday,
381             time->hour,
382             time->min,
383             time->sec);
384
385         if (state == OPENPTS_RM_STATE_OLD) {
386             printf(" OLD\n");
387         } else if (state == OPENPTS_RM_STATE_NOW) {
388             printf(" NOW\n");
389         } else if (state == OPENPTS_RM_STATE_NEW) {  // TODO def name is not clear
390             printf(" NEW (for next boot)\n");
391         } else if (state == OPENPTS_RM_STATE_TRASH) {
392             printf(" RENEWED (-R to purge)\n");
393         } else {
394             printf(" state=UNKNOWN\n");
395         }
396     }
397     printf("%s%s\n", indent, SEP_LINE);
398 }
399
400
401
402 /* for verifier */
403
404 /**
405  * list/get target list at HOME/.openpts
406  *
407  * 2011-06-12 SM
408  *   Setup all entries of target_conf
409  *   Does performance issue exist, if we manage large num of targets?
410  *
411  *
412  * @retval PTS_SUCCESS
413  * @retval PTS_INTERNAL_ERROR
414  */
415 int getTargetList(OPENPTS_CONFIG *conf, char * config_dir) {
416     int cnt = 0;
417     int dir_num;
418     struct dirent **dir_list;
419     OPENPTS_TARGET *target;
420     OPENPTS_CONFIG *target_conf;
421     int rc;
422
423     DEBUG("getTargetList()            : %s\n", config_dir);
424
425     /* check */
426     if (conf->target_list != NULL) {
427         ERROR("conf->target_list exist\n");
428     }
429
430     /* move to config dir */
431     if ((chdir(conf->config_dir)) != 0) {
432         fprintf(stderr, "Accessing config directory %s\n", conf->config_dir);
433         return PTS_INTERNAL_ERROR;
434     }
435
436     /* scan dirs */
437     dir_num = scandir(".", &dir_list, &selectUuidDir, NULL);
438     if ( dir_num == -1 ) {
439         fprintf(stderr, "no target data\n");
440         return PTS_INTERNAL_ERROR;
441     }
442
443     /* malloc target_list */
444     conf->target_list = newTargetList(dir_num + 1);  // conf.c
445     if (conf->target_list == NULL) {
446         ERROR("no memory");
447         return PTS_INTERNAL_ERROR;
448     }
449
450     /* Set */
451     for (cnt = 0; cnt < dir_num; cnt++) {
452         target = &conf->target_list->target[cnt];
453         if (target == NULL) {
454             ERROR("no memory cnt=%d\n", cnt);
455             return PTS_INTERNAL_ERROR;
456         }
457         /* init */
458         target->str_uuid = smalloc(dir_list[cnt]->d_name);
459         target->uuid = getUuidFromString(dir_list[cnt]->d_name);
460         target->time = getDateTimeOfUuid(target->uuid);
461         target->dir = getFullpathName(conf->config_dir, target->str_uuid);
462         target->target_conf_filename = getFullpathName(target->dir, "target.conf");
463
464         DEBUG("target conf[%3d]           : %s\n", cnt, target->target_conf_filename);
465
466         /* read target config */
467         target_conf = (void *)newPtsConfig();
468         if (target_conf  == NULL) {
469             printf("no memory\n");
470             return PTS_INTERNAL_ERROR;  // TODO
471         }
472         readTargetConf(target_conf, target->target_conf_filename);
473
474         /* set collector UUID */
475         target_conf->uuid = newOpenptsUuid2(target->uuid);
476
477         /* set RM UUID (Mandatory) */
478         rc = readOpenptsUuidFile(target_conf->rm_uuid);
479         if (rc != PTS_SUCCESS) {
480             ERROR("getTargetList() - readOpenptsUuidFile() fail rc=%d\n", rc);
481             freeOpenptsUuid(target_conf->rm_uuid);
482             target_conf->rm_uuid = NULL;
483             return  PTS_INTERNAL_ERROR;
484         }
485
486         /* set New RM UUID (Optional) */
487         rc = readOpenptsUuidFile(target_conf->newrm_uuid);
488         if (rc != PTS_SUCCESS) {
489             DEBUG("getTargetList() - readOpenptsUuidFile() fail rc=%d\n", rc);
490             freeOpenptsUuid(target_conf->newrm_uuid);
491             target_conf->newrm_uuid = NULL;
492         }
493
494         /* set Old RM UUID (Optional)  */
495         rc = readOpenptsUuidFile(target_conf->oldrm_uuid);
496         if (rc != PTS_SUCCESS) {
497             DEBUG("getTargetList() - readOpenptsUuidFile() fail rc=%d\n", rc);
498             freeOpenptsUuid(target_conf->oldrm_uuid);
499             target_conf->oldrm_uuid = NULL;
500         }
501
502         target->target_conf = (void *)target_conf;
503
504         free(dir_list[cnt]);
505     }
506     free(dir_list);
507
508     return PTS_SUCCESS;
509 }
510
511 /**
512  *  look up the yarget by the hostname.
513  *  get the target in target_list which hostname is conf->hostname (given)
514  *
515  *  openpts, standalone verifier only?
516  *
517  * @return dir_string
518  */
519 char *getTargetConfDir(OPENPTS_CONFIG *conf) {
520     char *dir = NULL;
521     int cnt;
522     OPENPTS_TARGET *target;
523     OPENPTS_CONFIG *target_conf;
524     int num = 0;
525
526     /* check */
527     if (conf == NULL) {
528         ERROR("getTargetConfDir() - conf is NULL\n");
529         return NULL;
530     }
531     if (conf->hostname == NULL) {
532         ERROR("getTargetConfDir() - conf->hostname is NULL\n");
533         return NULL;
534     }
535     if (conf->target_list == NULL) {
536         ERROR("getTargetConfDir() - conf->target_list is NULL\n");
537         return NULL;
538     }
539
540     /* how many targets? */
541     num = conf->target_list->target_num;
542
543     /* find the name in the target list */
544     for (cnt = 0; cnt < num; cnt++) {
545         target = &conf->target_list->target[cnt];
546         target_conf = (OPENPTS_CONFIG *) target->target_conf;
547
548         if (target_conf->hostname == NULL) {
549             DEBUG("hostname is missing in %s\n", target->target_conf_filename);
550         } else {
551             if (!strcmp(conf->hostname, target_conf->hostname)) {
552                 /* HIT, return first one, if multiple host was exist conf dir was broken */
553                 dir = smalloc(target->dir);
554                 return dir;
555             }
556         }
557     }
558
559     return dir;
560 }
561
562 /**
563  *  get the target in target_list which hostname is conf->hostname (given)
564  *
565  * @return OPENPTS_TARGET
566  */
567 OPENPTS_TARGET *getTargetCollector(OPENPTS_CONFIG *conf) {
568     int cnt;
569     OPENPTS_TARGET *target;
570     OPENPTS_CONFIG *target_conf;
571     int num = 0;
572
573     num = conf->target_list->target_num;
574
575     /* loop  */
576     for (cnt = 0; cnt < num; cnt++) {
577         target = &conf->target_list->target[cnt];
578         target_conf = (OPENPTS_CONFIG *) target->target_conf;
579
580         if (target_conf != NULL) {
581             if (target_conf->hostname == NULL) {
582                 DEBUG("hostname is missing in %s\n", target->target_conf_filename);
583             } else {
584                 if (!strcmp(conf->hostname, target_conf->hostname)) {
585                     /* HIT */
586                     return target;
587                 }
588             }
589         } else {
590             /* miss -> skip */
591         }
592     }
593
594     return NULL;
595 }
596
597
598
599
600 /**
601  * print target list, target par line
602  */
603 void printTargetList(OPENPTS_CONFIG *conf, char *indent) {
604     int cnt;
605     PTS_DateTime *time;
606     OPENPTS_TARGET *target;
607     OPENPTS_CONFIG *target_conf;
608     char * str_uuid = "N/A";
609     int num = 0;
610
611     num = conf->target_list->target_num;
612
613     printf("%s  ID    UUID                                 "
614            "date(UTC)          username@hostname:port\n",
615         indent);
616     printf("%s%s\n", indent, SEP_LINE);
617
618     /* Print  */
619     for (cnt = 0; cnt < num; cnt++) {
620         target = &conf->target_list->target[cnt];
621         target_conf = (OPENPTS_CONFIG *) target->target_conf;
622
623         time = target->time;
624
625         if (target_conf != NULL) {
626             if (target_conf->uuid != NULL) {
627                 if (target_conf->uuid->str != NULL) {
628                     str_uuid = target_conf->uuid->str;
629                 }
630             }
631             printf("%s %4d %s %04d-%02d-%02d-%02d:%02d:%02d %s@%s:%s\n",
632                 indent,
633                 cnt,
634                 str_uuid,
635                 time->year + 1900,
636                 time->mon + 1,
637                 time->mday,
638                 time->hour,
639                 time->min,
640                 time->sec,
641                 target_conf->ssh_username ? target_conf->ssh_username : "default",
642                 target_conf->hostname,
643                 target_conf->ssh_port ? target_conf->ssh_port : "default");
644         } else {
645             // printf("--\n");
646         }
647     }
648     printf("%s%s\n", indent, SEP_LINE);
649 }