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