]> andersk Git - moira.git/blame - clients/stella/stella.c
stella, a command line client for manipulating the machine table.
[moira.git] / clients / stella / stella.c
CommitLineData
80e8aa14 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
24RCSID("$Header$");
25
26struct owner_type {
27 int type;
28 char *name;
29};
30
31struct mqelem {
32 struct mqelem *q_forw;
33 struct mqelem *q_back;
34 void *q_data;
35};
36
37struct 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 */
54int info_flag, update_flag, create_flag, delete_flag, list_map_flag;
55int update_map_flag, verbose, noauth;
56
57struct string_list *alias_add_queue, *alias_remove_queue;
58struct string_list *map_add_queue, *map_remove_queue;
59
60char *hostname, *whoami;
61
62char *newname, *address, *network, *h_status, *vendor, *model;
63char *os, *location, *contact, *adm_cmt, *op_cmt;
64
65struct owner_type *owner;
66
67void usage(char **argv);
68int store_host_info(int argc, char **argv, void *hint);
69void show_host_info(char **argv);
70int show_machine_in_cluster(int argc, char **argv, void *hint);
71struct owner_type *parse_member(char *s);
72struct string_list *add_to_string_list(struct string_list *old_list, char *s);
73int wrap_mr_query(char *handle, int argc, char **argv,
74 int (*callback)(int, char **, void *), void *callarg);
75void print_query(char *query_name, int argc, char **argv);
76
77int 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
585void 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
618static int show_has_aliases;
619
620int 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
630static char *states[] = {
631 "Reserved (0)",
632 "Active (1)",
633 "None (2)",
634 "Deleted (3)"
635};
636
637static 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
651int 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
662void 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
701int 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
712struct 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
765struct 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
775int 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
783void 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.146837 seconds and 5 git commands to generate.