2 * Command line oriented Moira host tool.
4 * kolya@MIT.EDU, January 2000
6 * Somewhat based on blanche
8 * Copyright (C) 2000 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, please see the file
13 #include <mit-copyright.h>
15 #include <moira_site.h>
32 struct mqelem *q_forw;
33 struct mqelem *q_back;
39 struct string_list *next;
48 /* argument parsing macro */
49 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
51 /* flags from command line */
52 int info_flag, update_flag, create_flag, delete_flag, list_map_flag;
53 int update_alias_flag, update_map_flag, verbose, noauth;
54 int list_container_flag, update_container_flag;
56 struct string_list *alias_add_queue, *alias_remove_queue;
57 struct string_list *map_add_queue, *map_remove_queue;
58 struct string_list *container_add_queue, *container_remove_queue;
60 char *hostname, *whoami;
62 char *newname, *address, *network, *h_status, *vendor, *model;
63 char *os, *location, *contact, *billing_contact, *account_number;
64 char *adm_cmt, *op_cmt;
66 struct owner_type *owner;
68 void usage(char **argv);
69 int store_host_info(int argc, char **argv, void *hint);
70 void show_host_info(char **argv);
71 int show_machine_in_cluster(int argc, char **argv, void *hint);
72 int show_machine_in_container(int argc, char **argv, void *hint);
73 struct owner_type *parse_member(char *s);
74 struct string_list *add_to_string_list(struct string_list *old_list, char *s);
75 int wrap_mr_query(char *handle, int argc, char **argv,
76 int (*callback)(int, char **, void *), void *callarg);
77 void print_query(char *query_name, int argc, char **argv);
79 int main(int argc, char **argv)
85 /* clear all flags & lists */
86 info_flag = update_flag = create_flag = list_map_flag = update_map_flag = 0;
87 update_alias_flag = verbose = noauth = 0;
88 list_container_flag = update_container_flag = 0;
89 newname = address = network = h_status = vendor = model = NULL;
90 os = location = contact = billing_contact = account_number = adm_cmt = NULL;
93 alias_add_queue = alias_remove_queue = NULL;
94 map_add_queue = map_remove_queue = NULL;
95 container_add_queue = container_remove_queue = NULL;
100 /* parse args, building addlist, dellist, & synclist */
101 while (++arg - argv < argc)
105 if (argis("i", "info"))
107 else if (argis("C", "create"))
109 else if (argis("D", "delete"))
111 else if (argis("R", "rename")) {
112 if (arg - argv < argc - 1) {
119 else if (argis("A", "address")) {
120 if (arg - argv < argc - 1) {
127 else if (argis("O", "owner")) {
128 if (arg - argv < argc - 1) {
131 owner = parse_member(*arg);
135 else if (argis("N", "network")) {
136 if (arg - argv < argc - 1) {
143 else if (argis("S", "status")) {
144 if (arg - argv < argc - 1) {
152 len = strlen(h_status);
153 for(i = 0; i < len; i++) {
154 if(!isdigit(h_status[i])) {
155 printf("Error: status code %s is not numeric.\n", h_status);
162 else if (argis("V", "vendor")) {
163 if (arg - argv < argc - 1) {
170 else if (argis("M", "model")) {
171 if (arg - argv < argc - 1) {
178 else if (argis("o", "os")) {
179 if (arg - argv < argc - 1) {
186 else if (argis("L", "location")) {
187 if (arg - argv < argc - 1) {
194 else if (argis("c", "contact")) {
195 if (arg - argv < argc - 1) {
202 else if (argis("bc", "billingcontact")) {
203 if (arg - argv < argc - 1) {
206 billing_contact = *arg;
210 else if (argis("an", "accountnumber")) {
211 if (arg - argv < argc - 1) {
214 account_number = *arg;
218 else if (argis("ac", "admcmt")) {
219 if (arg - argv < argc - 1) {
226 else if (argis("oc", "opcmt")) {
227 if (arg - argv < argc - 1) {
234 else if (argis("a", "aliasadd")) {
235 if (arg - argv < argc - 1) {
237 alias_add_queue=add_to_string_list(alias_add_queue, *arg);
242 else if (argis("d", "aliasdelete")) {
243 if (arg - argv < argc - 1) {
245 alias_remove_queue=add_to_string_list(alias_remove_queue, *arg);
250 else if (argis("am", "addmap")) {
251 if (arg - argv < argc - 1) {
253 map_add_queue=add_to_string_list(map_add_queue, *arg);
258 else if (argis("dm", "deletemap")) {
259 if (arg - argv < argc - 1) {
261 map_remove_queue=add_to_string_list(map_remove_queue, *arg);
266 else if (argis("lm", "listmap"))
268 else if (argis("acn", "addcontainer")) {
269 if (arg - argv < argc - 1) {
271 container_add_queue =
272 add_to_string_list(container_add_queue, *arg);
275 update_container_flag++;
277 else if (argis("dcn", "deletecontainer")) {
278 if (arg - argv < argc - 1) {
280 container_remove_queue =
281 add_to_string_list(container_remove_queue, *arg);
284 update_container_flag++;
286 else if (argis("lcn", "listcontainer"))
287 list_container_flag++;
288 else if (argis("n", "noauth"))
290 else if (argis("v", "verbose"))
292 else if (argis("db", "database"))
294 if (arg - argv < argc - 1)
305 else if (hostname == NULL)
310 if (hostname == NULL)
313 /* default to info_flag if nothing else was specified */
314 if(!(info_flag || update_flag || create_flag || \
315 delete_flag || list_map_flag || update_map_flag || \
316 update_alias_flag || update_container_flag || \
317 list_container_flag)) {
322 status = mrcl_connect(server, "stella", 8, !noauth);
323 if (status == MRCL_AUTH_ERROR)
325 com_err(whoami, 0, "Try the -noauth flag if you don't "
326 "need authentication.");
331 /* create if needed */
337 for (cnt = 0; cnt < 17; cnt++) {
341 argv[0] = canonicalize_hostname(strdup(hostname));
354 argv[6] = billing_contact;
356 argv[7] = account_number;
357 /* The use field always gets set to "0" */
376 argv[13] = owner->name;
382 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
383 if (owner->type != M_ANY || status != MR_USER)
388 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
392 argv[12] = "KERBEROS";
393 status = mrcl_validate_kerberos_member(argv[13], &argv[13]);
394 if (mrcl_get_message())
395 mrcl_com_err(whoami);
396 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
401 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
410 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
415 com_err(whoami, status, "while creating host.");
420 else if (update_flag)
426 args[0] = canonicalize_hostname(strdup(hostname));
427 args[1] = args[2] = args[3] = "*";
429 status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv);
432 com_err(whoami, status, "while getting list information");
436 argv[1] = old_argv[0];
437 argv[2] = old_argv[1];
438 argv[3] = old_argv[2];
439 argv[4] = old_argv[3];
440 argv[5] = old_argv[4];
441 argv[6] = old_argv[5];
442 argv[7] = old_argv[6];
443 argv[8] = old_argv[7];
444 argv[9] = old_argv[8];
445 argv[10] = old_argv[9];
446 argv[11] = old_argv[11];
447 argv[12] = old_argv[12];
448 argv[13] = old_argv[13];
449 argv[14] = old_argv[14];
450 argv[15] = old_argv[15];
451 argv[16] = old_argv[16];
453 argv[0] = canonicalize_hostname(strdup(hostname));
455 argv[1] = canonicalize_hostname(strdup(newname));
467 argv[7] = billing_contact;
469 argv[8] = account_number;
483 argv[14] = owner->name;
489 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
490 if (owner->type != M_ANY || status != MR_USER)
495 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
499 argv[13] = "KERBEROS";
500 status = mrcl_validate_kerberos_member(argv[14], &argv[14]);
501 if (mrcl_get_message())
502 mrcl_com_err(whoami);
503 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
508 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
513 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
516 com_err(whoami, status, "while updating host.");
521 /* create aliases if necessary */
522 if (alias_add_queue) {
523 struct string_list *q = alias_add_queue;
526 char *alias = q->string;
529 args[0] = partial_canonicalize_hostname(strdup(alias));
530 args[1] = canonicalize_hostname(strdup(hostname));
531 status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL);
533 com_err(whoami, status, "while adding host alias");
541 /* delete aliases if necessary */
542 if (alias_remove_queue) {
543 struct string_list *q = alias_remove_queue;
546 char *alias = q->string;
549 args[0] = partial_canonicalize_hostname(strdup(alias));
550 args[1] = canonicalize_hostname(strdup(hostname));
551 status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL);
553 com_err(whoami, status, "while deleting host alias");
561 /* create cluster mappings */
563 struct string_list *q = map_add_queue;
566 char *clustername = q->string;
569 args[0] = canonicalize_hostname(strdup(hostname));
570 args[1] = clustername;
571 status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL);
573 com_err(whoami, status, "while adding cluster mapping");
581 /* delete cluster mappings */
582 if (map_remove_queue) {
583 struct string_list *q = map_remove_queue;
586 char *clustername = q->string;
589 args[0] = canonicalize_hostname(strdup(hostname));
590 args[1] = clustername;
591 status = wrap_mr_query("delete_machine_from_cluster", 2, args,
594 com_err(whoami, status, "while deleting cluster mapping");
602 /* add container mappings */
603 if (container_add_queue) {
604 struct string_list *q = container_add_queue;
607 char *containername = q->string;
610 args[0] = canonicalize_hostname(strdup(hostname));
611 args[1] = containername;
612 status = wrap_mr_query("add_machine_to_container", 2, args,
616 com_err(whoami, status, "while adding container mapping");
624 /* delete container mappings */
625 if (container_remove_queue) {
626 struct string_list *q = container_remove_queue;
629 char *containername = q->string;
632 args[0] = canonicalize_hostname(strdup(hostname));
633 args[1] = containername;
634 status = wrap_mr_query("delete_machine_from_container", 2, args,
638 com_err(whoami, status, "while deleting container mapping");
646 /* display list info if requested to */
648 struct mqelem *elem = NULL;
652 args[0] = canonicalize_hostname(strdup(hostname));
653 args[1] = args[2] = args[3] = "*";
654 status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
656 com_err(whoami, status, "while getting host information");
659 show_host_info(argv);
662 /* list cluster mappings if needed */
666 args[0] = canonicalize_hostname(strdup(hostname));
668 status = wrap_mr_query("get_machine_to_cluster_map", 2, args,
669 show_machine_in_cluster, NULL);
671 if (status != MR_NO_MATCH) {
672 com_err(whoami, status, "while getting cluster mappings");
677 /* list container mappings if needed */
678 if (list_container_flag) {
681 argv[0] = canonicalize_hostname(strdup(hostname));
682 status = wrap_mr_query("get_machine_to_container_map", 1, argv,
683 show_machine_in_container, NULL);
686 if (status != MR_NO_MATCH) {
687 com_err(whoami, status, "while getting container mappings");
695 argv[0] = canonicalize_hostname(strdup(hostname));
696 status = wrap_mr_query("delete_host", 1, argv, NULL, NULL);
698 com_err(whoami, status, "while deleting host");
705 exit(success ? 0 : 1);
708 void usage(char **argv)
710 #define USAGE_OPTIONS_FORMAT " %-39s%s\n"
711 fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]);
712 fprintf(stderr, "Options are\n");
713 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C | -create",
714 "-O | -owner owner");
715 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete",
716 "-S | -status status");
717 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R | -rename newname",
718 "-V | -vendor vendor");
719 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -addalias alias",
720 "-M | -model model");
721 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -deletealias alias",
722 "-L | -location location");
723 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info",
725 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-oc | -opcmt op_cmt",
726 "-c | -contact contact");
727 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ac | -admcmt adm_cmt",
728 "-bc | -billingcontact billing_contact");
729 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-an | -accountnumber account_number", "-A | -address address");
730 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-N | -network network",
731 "-am | -addmap cluster");
732 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dm | deletemap cluster",
733 "-acn | -addcontainer container");
734 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dcn | -deletecontainer container",
736 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-lcn | -listcontainer",
737 "-u | -unformatted");
738 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose",
740 fprintf(stderr, " %-39s\n" , "-db | -database host[:port]");
744 /* Show alias information */
746 static int show_has_aliases;
748 int show_alias_info(int argc, char **argv, void *hint)
750 if(!show_has_aliases++)
751 printf("Aliases: %s", argv[0]);
753 printf(", %s", argv[0]);
758 static char *states[] = {
765 static char *MacState(int state)
767 static char buf[BUFSIZ];
769 if (state < 0 || state > 3)
771 sprintf(buf, "Unknown (%d)", state);
774 return states[state];
777 /* Retrieve information about a host */
779 int store_host_info(int argc, char **argv, void *hint)
784 for(i=0; i<argc; i++)
785 nargv[i] = strdup(argv[i]);
790 void show_host_info(char **argv)
794 struct mqelem *elem = NULL;
797 printf("Machine: %s\n", argv[M_NAME]);
799 args[1] = argv[M_NAME];
800 show_has_aliases = 0;
801 stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info, &elem);
804 if (stat != MR_NO_MATCH)
805 com_err(whoami, stat, "while getting aliases");
809 sprintf(tbuf, "%s %s", argv[M_OWNER_TYPE],
810 strcmp(argv[M_OWNER_TYPE], "NONE") ? argv[M_OWNER_NAME] : "");
811 printf("Address: %-16s Network: %-16s\n",
812 argv[M_ADDR], argv[M_SUBNET]);
813 printf("Owner: %-16s Use data: %s\n", tbuf, argv[M_INUSE]);
814 printf("Status: %-16s Changed: %s\n",
815 MacState(atoi(argv[M_STAT])), argv[M_STAT_CHNG]);
817 printf("Vendor: %-16s Location: %s\n", argv[M_VENDOR],
819 printf("Model: %-16s Contact: %s\n", argv[M_MODEL],
821 printf("OS: %-16s Billing Contact: %s\n", argv[M_OS],
822 argv[M_BILL_CONTACT]);
823 printf("Opt: %-16s Account Number: %s\n", argv[M_USE],
824 argv[M_ACCT_NUMBER]);
825 printf("\nAdm cmt: %s\n", argv[M_ACOMMENT]);
826 printf("Op cmt: %s\n", argv[M_OCOMMENT]);
828 printf("Created by %s on %s\n", argv[M_CREATOR], argv[M_CREATED]);
829 printf("Last mod by %s at %s with %s.\n", argv[M_MODBY], argv[M_MODTIME], argv[M_MODWITH]);
832 int show_machine_in_cluster(int argc, char **argv, void *hint)
834 printf("Machine: %-30s Cluster: %-30s\n", argv[0], argv[1]);
839 int show_machine_in_container(int argc, char **argv, void *hint)
841 printf("Machine: %-30s Container: %-25s\n", argv[0], argv[1]);
846 /* Parse a line of input, fetching a member. NULL is returned if a member
847 * is not found. ';' is a comment character.
850 struct owner_type *parse_member(char *s)
852 struct owner_type *m;
855 while (*s && isspace(*s))
858 while (*p && *p != '\n' && *p != ';')
860 if (isprint(*p) && !isspace(*p))
867 if (p == s || strlen(s) == 0)
870 if (!(m = malloc(sizeof(struct owner_type))))
873 if ((p = strchr(s, ':')))
877 if (!strcasecmp("user", s))
879 else if (!strcasecmp("list", s))
881 else if (!strcasecmp("kerberos", s))
882 m->type = M_KERBEROS;
883 else if (!strcasecmp("none", s))
891 m->name = strdup(m->name);
896 m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
901 struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
902 struct string_list *new_list;
904 new_list = (struct string_list *)malloc(sizeof(struct string_list *));
905 new_list->next = old_list;
906 new_list->string = s;
911 int wrap_mr_query(char *handle, int argc, char **argv,
912 int (*callback)(int, char **, void *), void *callarg) {
914 print_query(handle, argc, argv);
916 return mr_query(handle, argc, argv, callback, callarg);
919 void print_query(char *query_name, int argc, char **argv) {
922 printf("qy %s", query_name);
923 for(cnt=0; cnt<argc; cnt++)
924 printf(" <%s>", argv[cnt]);