]> andersk Git - moira.git/blob - clients/stella/stella.c
when adding or removing a hostname, use partial_canonicalize_hostname()
[moira.git] / clients / stella / stella.c
1 /*
2  * Command line oriented Moira host tool.
3  *
4  * kolya@MIT.EDU, January 2000
5  *
6  * Somewhat based on blanche
7  *
8  * Copyright (C) 2000 by the Massachusetts Institute of Technology.
9  * For copying and distribution information, please see the file
10  * <mit-copyright.h>.
11  */
12
13 #include <mit-copyright.h>
14 #include <moira.h>
15 #include <moira_site.h>
16 #include <mrclient.h>
17
18 #include <ctype.h>
19 #include <errno.h>
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23
24 RCSID("$Header$");
25
26 struct owner_type {
27   int type;
28   char *name;
29 };
30
31 struct mqelem {
32   struct mqelem *q_forw;
33   struct mqelem *q_back;
34   void *q_data;
35 };
36
37 struct string_list {
38   char *string;
39   struct string_list *next;
40 };
41
42 /* It is important to membercmp that M_USER < M_LIST < M_STRING */
43 #define M_ANY           0
44 #define M_USER          1
45 #define M_LIST          2
46 #define M_STRING        3
47 #define M_KERBEROS      4
48 #define M_NONE          5
49
50 /* argument parsing macro */
51 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
52
53 /* flags from command line */
54 int info_flag, update_flag, create_flag, delete_flag, list_map_flag;
55 int update_map_flag, verbose, noauth;
56
57 struct string_list *alias_add_queue, *alias_remove_queue;
58 struct string_list *map_add_queue, *map_remove_queue;
59
60 char *hostname, *whoami;
61
62 char *newname, *address, *network, *h_status, *vendor, *model;
63 char *os, *location, *contact, *adm_cmt, *op_cmt;
64
65 struct owner_type *owner;
66
67 void usage(char **argv);
68 int store_host_info(int argc, char **argv, void *hint);
69 void show_host_info(char **argv);
70 int show_machine_in_cluster(int argc, char **argv, void *hint);
71 struct owner_type *parse_member(char *s);
72 struct string_list *add_to_string_list(struct string_list *old_list, char *s);
73 int wrap_mr_query(char *handle, int argc, char **argv,
74                   int (*callback)(int, char **, void *), void *callarg);
75 void print_query(char *query_name, int argc, char **argv);
76
77 int main(int argc, char **argv)
78 {
79   int status, success;
80   char **arg = argv;
81   char *server = NULL;
82
83   /* clear all flags & lists */
84   info_flag = update_flag = create_flag = list_map_flag = update_map_flag = 0;
85   verbose = noauth = 0;
86   newname = address = network = h_status = vendor = model = NULL;
87   os = location = contact = adm_cmt = op_cmt = NULL;
88   owner = NULL;
89   alias_add_queue = alias_remove_queue = NULL;
90   map_add_queue = map_remove_queue = NULL;
91   whoami = argv[0];
92
93   success = 1;
94
95   /* parse args, building addlist, dellist, & synclist */
96   while (++arg - argv < argc)
97     {
98       if (**arg == '-')
99         {
100           if (argis("i", "info"))
101             info_flag++;
102           else if (argis("C", "create"))
103             create_flag++;
104           else if (argis("D", "delete"))
105             delete_flag++;
106           else if (argis("R", "rename")) {
107             if (arg - argv < argc - 1) {
108               arg++;
109               update_flag++;
110               newname = *arg;
111             } else
112               usage(argv);
113           }
114           else if (argis("A", "address")) {
115             if (arg - argv < argc - 1) {
116               arg++;
117               update_flag++;
118               address = *arg;
119             } else
120               usage(argv);
121           }
122           else if (argis("O", "owner")) {
123             if (arg - argv < argc - 1) {
124               arg++;
125               update_flag++;
126               owner = parse_member(*arg);
127             } else
128               usage(argv);
129           }
130           else if (argis("N", "network")) {
131             if (arg - argv < argc - 1) {
132               arg++;
133               update_flag++;
134               network = *arg;
135             } else
136               usage(argv);
137           }
138           else if (argis("S", "status")) {
139             if (arg - argv < argc - 1) {
140               int i;
141               int len;
142
143               arg++;
144               update_flag++;
145               h_status = *arg;
146
147               len = strlen(h_status);
148               for(i = 0; i < len; i++) {
149                 if(!isdigit(h_status[i])) {
150                   printf("Error: status code %s is not numeric.\n", h_status);
151                   exit(1);
152                 }
153               }
154             } else
155               usage(argv);
156           }
157           else if (argis("V", "vendor")) {
158             if (arg - argv < argc - 1) {
159               arg++;
160               update_flag++;
161               vendor = *arg;
162             } else
163               usage(argv);
164           }
165           else if (argis("M", "model")) {
166             if (arg - argv < argc - 1) {
167               arg++;
168               update_flag++;
169               model = *arg;
170             } else
171               usage(argv);
172           }
173           else if (argis("o", "os")) {
174             if (arg - argv < argc - 1) {
175               arg++;
176               update_flag++;
177               os = *arg;
178             } else
179               usage(argv);
180           }
181           else if (argis("L", "location")) {
182             if (arg - argv < argc - 1) {
183               arg++;
184               update_flag++;
185               location = *arg;
186             } else
187               usage(argv);
188           }
189           else if (argis("c", "contact")) {
190             if (arg - argv < argc - 1) {
191               arg++;
192               update_flag++;
193               contact = *arg;
194             } else
195               usage(argv);
196           }
197           else if (argis("ac", "admcmt")) {
198             if (arg - argv < argc - 1) {
199               arg++;
200               update_flag++;
201               adm_cmt = *arg;
202             } else
203               usage(argv);
204           }
205           else if (argis("oc", "opcmt")) {
206             if (arg - argv < argc - 1) {
207               arg++;
208               update_flag++;
209               op_cmt = *arg;
210             } else
211               usage(argv);
212           }
213           else if (argis("a", "aliasadd")) {
214             if (arg - argv < argc - 1) {
215               arg++;
216               alias_add_queue=add_to_string_list(alias_add_queue, *arg);
217             } else
218               usage(argv);
219           }
220           else if (argis("d", "aliasdelete")) {
221             if (arg - argv < argc - 1) {
222               arg++;
223               alias_remove_queue=add_to_string_list(alias_remove_queue, *arg);
224             } else
225               usage(argv);
226           }
227           else if (argis("am", "addmap")) {
228             if (arg - argv < argc - 1) {
229               arg++;
230               map_add_queue=add_to_string_list(map_add_queue, *arg);
231             } else
232               usage(argv);
233             update_map_flag++;
234           }
235           else if (argis("dm", "deletemap")) {
236             if (arg - argv < argc - 1) {
237               arg++;
238               map_remove_queue=add_to_string_list(map_remove_queue, *arg);
239             } else
240               usage(argv);
241             update_map_flag++;
242           }
243           else if (argis("lm", "listmap"))
244             list_map_flag++;
245           else if (argis("n", "noauth"))
246             noauth++;
247           else if (argis("v", "verbose"))
248             verbose++;
249           else if (argis("db", "database"))
250             {
251               if (arg - argv < argc - 1)
252                 {
253                   ++arg;
254                   server = *arg;
255                 }
256               else
257                 usage(argv);
258             }
259           else
260             usage(argv);
261         }
262       else if (hostname == NULL)
263         hostname = *arg;
264       else
265         usage(argv);
266     }
267   if (hostname == NULL)
268     usage(argv);
269
270   /* default to info_flag if nothing else was specified */
271   if(!(info_flag   || update_flag   || create_flag     || \
272        delete_flag || list_map_flag || update_map_flag )) {
273     info_flag++;
274   }
275
276   /* fire up Moira */
277   status = mrcl_connect(server, "stella", 2, !noauth);
278   if (status == MRCL_AUTH_ERROR)
279     {
280       com_err(whoami, 0, "Try the -noauth flag if you don't "
281               "need authentication.");
282     }
283   if (status)
284     exit(2);
285
286   /* create if needed */
287   if (create_flag)
288     {
289       char *argv[30];
290       int cnt;
291
292       for (cnt = 0; cnt < 15; cnt++) {
293         argv[cnt] = "";
294       }
295
296       argv[0] = canonicalize_hostname(strdup(hostname));
297
298       if (vendor)
299         argv[1] = vendor;
300       if (model)
301         argv[2] = model;
302       if (os)
303         argv[3] = os;
304       if (location)
305         argv[4] = location;
306       if (contact)
307         argv[5] = contact;
308       /* The use field always gets set to "0" */
309       argv[6] = "0";
310       if (h_status)
311         argv[7] = h_status;
312       else
313         argv[7] = "1";
314       if (network)
315         argv[8] = network;
316       if (address)
317         argv[9] = address;
318       if (adm_cmt)
319         argv[12] = adm_cmt;
320       if (op_cmt)
321         argv[13] = op_cmt;
322
323       if (owner)
324         {
325           argv[11] = owner->name;
326           switch (owner->type)
327             {
328             case M_ANY:
329             case M_USER:
330               argv[10] = "USER";
331               status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
332               if (owner->type != M_ANY || status != MR_USER)
333                 break;
334
335             case M_LIST:
336               argv[10] = "LIST";
337               status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
338               break;
339
340             case M_KERBEROS:
341               argv[10] = "KERBEROS";
342               status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
343               break;
344
345             case M_NONE:
346               argv[10] = "NONE";
347               status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
348               break;
349             }
350         }
351       else
352         {
353           argv[10] = "NONE";
354           argv[11] = "NONE";
355
356           status = wrap_mr_query("add_host", 14, argv, NULL, NULL);
357         }
358
359       if (status)
360         {
361           com_err(whoami, status, "while creating host.");
362           exit(1);
363         }
364
365     }
366   else if (update_flag)
367     {
368       char *old_argv[30];
369       char *argv[16];
370       char *args[5];
371
372       args[0] = canonicalize_hostname(strdup(hostname));
373       args[1] = args[2] = args[3] = "*";
374
375       status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv);
376       if (status)
377         {
378           com_err(whoami, status, "while getting list information");
379           exit(1);
380         }
381
382       argv[1] = old_argv[0];
383       argv[2] = old_argv[1];
384       argv[3] = old_argv[2];
385       argv[4] = old_argv[3];
386       argv[5] = old_argv[4];
387       argv[6] = old_argv[5];
388       argv[7] = old_argv[6];
389       argv[8] = old_argv[7];
390       argv[9] = old_argv[9];
391       argv[10] = old_argv[10];
392       argv[11] = old_argv[11];
393       argv[12] = old_argv[12];
394       argv[13] = old_argv[13];
395       argv[14] = old_argv[14];
396
397       argv[0] = canonicalize_hostname(strdup(hostname));
398       if (newname)
399         argv[1] = canonicalize_hostname(strdup(newname));
400       if (vendor)
401         argv[2] = vendor;
402       if (model)
403         argv[3] = model;
404       if (os)
405         argv[4] = os;
406       if (location)
407         argv[5] = location;
408       if (contact)
409         argv[6] = contact;
410       if (h_status)
411         argv[8] = h_status;
412       if (network)
413         argv[9] = network;
414       if (address)
415         argv[10] = address;
416       if (adm_cmt)
417         argv[13] = adm_cmt;
418       if (op_cmt)
419         argv[14] = op_cmt;
420
421       if (owner)
422         {
423           argv[12] = owner->name;
424           switch (owner->type)
425             {
426             case M_ANY:
427             case M_USER:
428               argv[11] = "USER";
429               status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
430               if (owner->type != M_ANY || status != MR_USER)
431                 break;
432
433             case M_LIST:
434               argv[11] = "LIST";
435               status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
436               break;
437
438             case M_KERBEROS:
439               argv[11] = "KERBEROS";
440               status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
441               break;
442
443             case M_NONE:
444               argv[11] = "NONE";
445               status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
446               break;
447             }
448         }
449       else
450         status = wrap_mr_query("update_host", 15, argv, NULL, NULL);
451
452       if (status)
453         com_err(whoami, status, "while updating host.");
454       else if (newname)
455         hostname = newname;
456     }
457
458   /* create aliases if necessary */
459   if (alias_add_queue) {
460     struct string_list *q = alias_add_queue;
461
462     while(q) {
463       char *alias = q->string;
464       char *args[2];
465
466       args[0] = partial_canonicalize_hostname(strdup(alias));
467       args[1] = canonicalize_hostname(strdup(hostname));
468       status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL);
469       if (status) {
470         com_err(whoami, status, "while adding host alias");
471         exit(1);
472       }
473
474       q = q->next;
475     }
476   }
477
478   /* delete aliases if necessary */
479   if (alias_remove_queue) {
480     struct string_list *q = alias_remove_queue;
481
482     while(q) {
483       char *alias = q->string;
484       char *args[2];
485
486       args[0] = partial_canonicalize_hostname(strdup(alias));
487       args[1] = canonicalize_hostname(strdup(hostname));
488       status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL);
489       if (status) {
490         com_err(whoami, status, "while deleting host alias");
491         exit(1);
492       }
493
494       q = q->next;
495     }
496   }
497
498   /* create cluster mappings */
499   if (map_add_queue) {
500     struct string_list *q = map_add_queue;
501
502     while(q) {
503       char *clustername = q->string;
504       char *args[2];
505
506       args[0] = canonicalize_hostname(strdup(hostname));
507       args[1] = clustername;
508       status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL);
509       if (status) {
510         com_err(whoami, status, "while adding cluster mapping");
511         exit(1);
512       }
513
514       q = q->next;
515     }
516   }
517
518   /* delete cluster mappings */
519   if (map_remove_queue) {
520     struct string_list *q = map_remove_queue;
521
522     while(q) {
523       char *clustername = q->string;
524       char *args[2];
525
526       args[0] = canonicalize_hostname(strdup(hostname));
527       args[1] = clustername;
528       status = wrap_mr_query("delete_machine_from_cluster", 2, args,
529                              NULL, NULL);
530       if (status) {
531         com_err(whoami, status, "while deleting cluster mapping");
532         exit(1);
533       }
534
535       q = q->next;
536     }
537   }
538
539   /* display list info if requested to */
540   if (info_flag) {
541     struct mqelem *elem = NULL;
542     char *args[5];
543     char *argv[30];
544
545     args[0] = canonicalize_hostname(strdup(hostname));
546     args[1] = args[2] = args[3] = "*";
547     status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
548     if (status) {
549       com_err(whoami, status, "while getting host information");
550       exit(1);
551     }
552     show_host_info(argv);
553   }
554
555   /* list cluster mappings if needed */
556   if (list_map_flag) {
557     char *args[3];
558
559     args[0] = canonicalize_hostname(strdup(hostname));
560     args[1] = "*";
561     status = wrap_mr_query("get_machine_to_cluster_map", 2, args,
562                       show_machine_in_cluster, NULL);
563     if (status)
564       if (status != MR_NO_MATCH) {
565         com_err(whoami, status, "while getting cluster mappings");
566         exit(1);
567       }
568   }
569
570   if (delete_flag) {
571     char *argv[1];
572
573     argv[0] = canonicalize_hostname(strdup(hostname));
574     status = wrap_mr_query("delete_host", 1, argv, NULL, NULL);
575     if (status) {
576       com_err(whoami, status, "while deleting host");
577       exit(1);
578     }
579   }
580
581   /* We're done! */
582   mr_disconnect();
583   exit(success ? 0 : 1);
584 }
585
586 void usage(char **argv)
587 {
588 #define USAGE_OPTIONS_FORMAT "  %-39s%s\n"
589   fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]);
590   fprintf(stderr, "Options are\n");
591   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C   | -create",
592           "-O   | -owner owner");
593   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D   | -delete",
594           "-S   | -status status");
595   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R   | -rename newname",
596           "-V   | -vendor vendor");
597   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a   | -addalias alias",
598           "-M   | -model model");
599   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d   | -deletealias alias",
600           "-L   | -location location");
601   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i   | -info",
602           "-o   | -os os");
603   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-oc  | -opcmt op_cmt",
604           "-c   | -contact contact");
605   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ac  | -admcmt adm_cmt",
606           "-A   | -address address");
607   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-am  | -addmap cluster",
608           "-N   | -network network");
609   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dm  | -deletemap cluster",
610           "-lm  | -listmap");
611   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-db  | -database host[:port]",
612           "-n   | -noauth");
613   fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v   | -verbose",
614           "");
615   exit(1);
616 }
617
618 /* Show alias information */
619
620 static int show_has_aliases;
621
622 int show_alias_info(int argc, char **argv, void *hint)
623 {
624   if(!show_has_aliases++)
625     printf("Aliases:  %s", argv[0]);
626   else
627     printf(", %s", argv[0]);
628
629   return MR_CONT;
630 }
631
632 static char *states[] = {
633   "Reserved (0)",
634   "Active (1)",
635   "None (2)",
636   "Deleted (3)"
637 };
638
639 static char *MacState(int state)
640 {
641   static char buf[BUFSIZ];
642
643   if (state < 0 || state > 3)
644     {
645       sprintf(buf, "Unknown (%d)", state);
646       return buf;
647     }
648   return states[state];
649 }
650
651 /* Retrieve information about a host */
652
653 int store_host_info(int argc, char **argv, void *hint)
654 {
655   int i;
656   char **nargv = hint;
657
658   for(i=0; i<argc; i++)
659     nargv[i] = strdup(argv[i]);
660
661   return MR_CONT;
662 }
663
664 void show_host_info(char **argv)
665 {
666   char tbuf[256];
667   char *args[3];
668   struct mqelem *elem = NULL;
669   int stat;
670
671   printf("Machine:  %s\n", argv[M_NAME]);
672   args[0] = "*";
673   args[1] = argv[M_NAME];
674   show_has_aliases = 0;
675   stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info, &elem);
676   printf("\n");
677   if (stat) {
678     if (stat != MR_NO_MATCH)
679       com_err(whoami, stat, "while getting aliases");
680   } else {
681     printf("\n");
682   }
683   sprintf(tbuf, "%s %s", argv[M_OWNER_TYPE],
684           strcmp(argv[M_OWNER_TYPE], "NONE") ? argv[M_OWNER_NAME] : "");
685   printf("Address:  %-16s    Network:    %-16s\n",
686           argv[M_ADDR], argv[M_SUBNET]);
687   printf("Owner:    %-16s    Use data:   %s\n", tbuf, argv[M_INUSE]);
688   printf("Status:   %-16s    Changed:    %s\n",
689           MacState(atoi(argv[M_STAT])), argv[M_STAT_CHNG]);
690   printf("\n");
691
692   printf("Vendor:   %-16s    Model:      %-20s  OS:  %s\n",
693           argv[M_VENDOR], argv[M_MODEL], argv[M_OS]);
694   printf("Location: %-16s    Contact:    %-20s  Opt: %s\n",
695           argv[M_LOC], argv[M_CONTACT], argv[M_USE]);
696   printf("\nAdm cmt: %s\n", argv[M_ACOMMENT]);
697   printf("Op cmt:  %s\n", argv[M_OCOMMENT]);
698   printf("\n");
699   printf("Created  by %s on %s\n", argv[M_CREATOR], argv[M_CREATED]);
700   printf("Last mod by %s at %s with %s.\n", argv[M_MODBY], argv[M_MODTIME], argv[M_MODWITH]);
701 }
702
703 int show_machine_in_cluster(int argc, char **argv, void *hint)
704 {
705   printf("Machine: %-30s Cluster: %-30s\n", argv[0], argv[1]);
706
707   return MR_CONT;
708 }
709
710 /* Parse a line of input, fetching a member.  NULL is returned if a member
711  * is not found.  ';' is a comment character.
712  */
713
714 struct owner_type *parse_member(char *s)
715 {
716   struct owner_type *m;
717   char *p, *lastchar;
718
719   while (*s && isspace(*s))
720     s++;
721   lastchar = p = s;
722   while (*p && *p != '\n' && *p != ';')
723     {
724       if (isprint(*p) && !isspace(*p))
725         lastchar = p++;
726       else
727         p++;
728     }
729   lastchar++;
730   *lastchar = '\0';
731   if (p == s || strlen(s) == 0)
732     return NULL;
733
734   if (!(m = malloc(sizeof(struct owner_type))))
735     return NULL;
736
737   if ((p = strchr(s, ':')))
738     {
739       *p = '\0';
740       m->name = ++p;
741       if (!strcasecmp("user", s))
742         m->type = M_USER;
743       else if (!strcasecmp("list", s))
744         m->type = M_LIST;
745       else if (!strcasecmp("string", s))
746         m->type = M_STRING;
747       else if (!strcasecmp("kerberos", s))
748         m->type = M_KERBEROS;
749       else if (!strcasecmp("none", s))
750         m->type = M_NONE;
751       else
752         {
753           m->type = M_ANY;
754           *(--p) = ':';
755           m->name = s;
756         }
757       m->name = strdup(m->name);
758     }
759   else
760     {
761       m->name = strdup(s);
762       m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
763     }
764   return m;
765 }
766
767 struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
768   struct string_list *new_list;
769
770   new_list = (struct string_list *)malloc(sizeof(struct string_list *));
771   new_list->next = old_list;
772   new_list->string = s;
773
774   return new_list;
775 }
776
777 int wrap_mr_query(char *handle, int argc, char **argv,
778                   int (*callback)(int, char **, void *), void *callarg) {
779   if (verbose)
780     print_query(handle, argc, argv);
781
782   return mr_query(handle, argc, argv, callback, callarg);
783 }
784
785 void print_query(char *query_name, int argc, char **argv) {
786   int cnt;
787
788   printf("qy %s", query_name);
789   for(cnt=0; cnt<argc; cnt++)
790     printf(" <%s>", argv[cnt]);
791   printf("\n");
792 }
This page took 0.09777 seconds and 5 git commands to generate.