2 * Command line oriented Moira host tool.
4 * kolya@MIT.EDU, January 2000
6 * Somewhat based on blanche
8 * Copyright (C) 2000, 2001 by the Massachusetts Institute of Technology.
9 * For copying and distribution information, please see the file
13 #include <sys/types.h>
14 #include <sys/socket.h>
16 #include <netinet/in.h>
17 #include <arpa/inet.h>
19 #include <mit-copyright.h>
21 #include <moira_site.h>
38 struct mqelem *q_forw;
39 struct mqelem *q_back;
45 struct string_list *next;
54 /* argument parsing macro */
55 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
57 /* flags from command line */
58 int info_flag, update_flag, create_flag, delete_flag, list_map_flag;
59 int update_alias_flag, update_map_flag, verbose, noauth;
60 int list_container_flag, update_container_flag, unformatted_flag;
62 struct string_list *alias_add_queue, *alias_remove_queue;
63 struct string_list *map_add_queue, *map_remove_queue;
64 struct string_list *container_add_queue, *container_remove_queue;
66 char *hostname, *whoami;
68 char *newname, *address, *network, *h_status, *vendor, *model;
69 char *os, *location, *contact, *billing_contact, *adm_cmt, *op_cmt;
72 struct owner_type *owner;
74 void usage(char **argv);
75 int store_host_info(int argc, char **argv, void *hint);
76 void show_host_info(char **argv);
77 void show_host_info_unformatted(char **argv);
78 int show_machine_in_cluster(int argc, char **argv, void *hint);
79 int show_machine_in_container(int argc, char **argv, void *hint);
80 struct owner_type *parse_member(char *s);
81 struct string_list *add_to_string_list(struct string_list *old_list, char *s);
82 int wrap_mr_query(char *handle, int argc, char **argv,
83 int (*callback)(int, char **, void *), void *callarg);
84 void print_query(char *query_name, int argc, char **argv);
86 int main(int argc, char **argv)
92 /* clear all flags & lists */
93 info_flag = update_flag = create_flag = list_map_flag = update_map_flag = 0;
94 update_alias_flag = verbose = noauth = 0;
95 list_container_flag = update_container_flag = 0;
96 newname = address = network = h_status = vendor = model = NULL;
97 os = location = contact = billing_contact = adm_cmt = op_cmt = NULL;
99 alias_add_queue = alias_remove_queue = NULL;
100 map_add_queue = map_remove_queue = NULL;
101 container_add_queue = container_remove_queue = NULL;
106 /* parse args, building addlist, dellist, & synclist */
107 while (++arg - argv < argc)
111 if (argis("i", "info"))
113 else if (argis("C", "create"))
115 else if (argis("D", "delete"))
117 else if (argis("R", "rename")) {
118 if (arg - argv < argc - 1) {
125 else if (argis("A", "address")) {
126 if (arg - argv < argc - 1) {
133 else if (argis("O", "owner")) {
134 if (arg - argv < argc - 1) {
137 owner = parse_member(*arg);
141 else if (argis("N", "network")) {
142 if (arg - argv < argc - 1) {
149 else if (argis("S", "status")) {
150 if (arg - argv < argc - 1) {
158 len = strlen(h_status);
159 for(i = 0; i < len; i++) {
160 if(!isdigit(h_status[i])) {
161 printf("Error: status code %s is not numeric.\n", h_status);
168 else if (argis("V", "vendor")) {
169 if (arg - argv < argc - 1) {
176 else if (argis("M", "model")) {
177 if (arg - argv < argc - 1) {
184 else if (argis("o", "os")) {
185 if (arg - argv < argc - 1) {
192 else if (argis("L", "location")) {
193 if (arg - argv < argc - 1) {
200 else if (argis("c", "contact")) {
201 if (arg - argv < argc - 1) {
208 else if (argis("bc", "billingcontact")) {
209 if (arg - argv < argc - 1) {
212 billing_contact = *arg;
216 else if (argis("ac", "admcmt")) {
217 if (arg - argv < argc - 1) {
224 else if (argis("oc", "opcmt")) {
225 if (arg - argv < argc - 1) {
232 else if (argis("a", "aliasadd")) {
233 if (arg - argv < argc - 1) {
235 alias_add_queue=add_to_string_list(alias_add_queue, *arg);
240 else if (argis("d", "aliasdelete")) {
241 if (arg - argv < argc - 1) {
243 alias_remove_queue=add_to_string_list(alias_remove_queue, *arg);
248 else if (argis("am", "addmap")) {
249 if (arg - argv < argc - 1) {
251 map_add_queue=add_to_string_list(map_add_queue, *arg);
256 else if (argis("dm", "deletemap")) {
257 if (arg - argv < argc - 1) {
259 map_remove_queue=add_to_string_list(map_remove_queue, *arg);
264 else if (argis("lm", "listmap"))
266 else if (argis("acn", "addcontainer")) {
267 if (arg - argv < argc - 1) {
269 container_add_queue =
270 add_to_string_list(container_add_queue, *arg);
273 update_container_flag++;
275 else if (argis("dcn", "deletecontainer")) {
276 if (arg - argv < argc - 1) {
278 container_remove_queue =
279 add_to_string_list(container_remove_queue, *arg);
282 update_container_flag++;
284 else if (argis("lcn", "listcontainer"))
285 list_container_flag++;
286 else if (argis("u", "unformatted"))
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", 7, !noauth);
323 if (status == MRCL_AUTH_ERROR)
325 com_err(whoami, 0, "Try the -noauth flag if you don't "
326 "need authentication.");
331 /* Perform the lookup by IP address if that's what we've been handed */
332 if ((ipaddress=inet_addr(hostname)) != -1) {
336 args[1] = strdup(hostname);
337 args[0] = args[2] = args[3] = "*";
338 status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
341 com_err(whoami, status, "while looking up IP address.");
347 /* create if needed */
353 for (cnt = 0; cnt < 16; cnt++) {
357 argv[0] = canonicalize_hostname(strdup(hostname));
370 argv[6] = billing_contact;
371 /* The use field always gets set to "0" */
390 argv[12] = owner->name;
396 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
397 if (owner->type != M_ANY || status != MR_USER)
402 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
406 argv[11] = "KERBEROS";
407 status = mrcl_validate_kerberos_member(argv[12], &argv[12]);
408 if (mrcl_get_message())
409 mrcl_com_err(whoami);
410 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
415 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
424 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
429 com_err(whoami, status, "while creating host.");
434 else if (update_flag)
440 args[0] = canonicalize_hostname(strdup(hostname));
441 args[1] = args[2] = args[3] = "*";
443 status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv);
446 com_err(whoami, status, "while getting list information");
450 argv[1] = old_argv[0];
451 argv[2] = old_argv[1];
452 argv[3] = old_argv[2];
453 argv[4] = old_argv[3];
454 argv[5] = old_argv[4];
455 argv[6] = old_argv[5];
456 argv[7] = old_argv[6];
457 argv[8] = old_argv[7];
458 argv[9] = old_argv[8];
459 argv[10] = old_argv[10];
460 argv[11] = old_argv[11];
461 argv[12] = old_argv[12];
462 argv[13] = old_argv[13];
463 argv[14] = old_argv[14];
464 argv[15] = old_argv[15];
466 argv[0] = canonicalize_hostname(strdup(hostname));
468 argv[1] = canonicalize_hostname(strdup(newname));
480 argv[7] = billing_contact;
494 argv[13] = owner->name;
500 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
501 if (owner->type != M_ANY || status != MR_USER)
506 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
510 argv[12] = "KERBEROS";
511 status = mrcl_validate_kerberos_member(argv[13], &argv[13]);
512 if (mrcl_get_message())
513 mrcl_com_err(whoami);
514 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
519 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
524 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
527 com_err(whoami, status, "while updating host.");
532 /* create aliases if necessary */
533 if (alias_add_queue) {
534 struct string_list *q = alias_add_queue;
537 char *alias = q->string;
540 args[0] = partial_canonicalize_hostname(strdup(alias));
541 args[1] = canonicalize_hostname(strdup(hostname));
542 status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL);
544 com_err(whoami, status, "while adding host alias");
552 /* delete aliases if necessary */
553 if (alias_remove_queue) {
554 struct string_list *q = alias_remove_queue;
557 char *alias = q->string;
560 args[0] = partial_canonicalize_hostname(strdup(alias));
561 args[1] = canonicalize_hostname(strdup(hostname));
562 status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL);
564 com_err(whoami, status, "while deleting host alias");
572 /* create cluster mappings */
574 struct string_list *q = map_add_queue;
577 char *clustername = q->string;
580 args[0] = canonicalize_hostname(strdup(hostname));
581 args[1] = clustername;
582 status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL);
584 com_err(whoami, status, "while adding cluster mapping");
592 /* delete cluster mappings */
593 if (map_remove_queue) {
594 struct string_list *q = map_remove_queue;
597 char *clustername = q->string;
600 args[0] = canonicalize_hostname(strdup(hostname));
601 args[1] = clustername;
602 status = wrap_mr_query("delete_machine_from_cluster", 2, args,
605 com_err(whoami, status, "while deleting cluster mapping");
613 /* add container mappings */
614 if (container_add_queue) {
615 struct string_list *q = container_add_queue;
618 char *containername = q->string;
621 args[0] = canonicalize_hostname(strdup(hostname));
622 args[1] = containername;
623 status = wrap_mr_query("add_machine_to_container", 2, args,
627 com_err(whoami, status, "while adding container mapping");
635 /* delete container mappings */
636 if (container_remove_queue) {
637 struct string_list *q = container_remove_queue;
640 char *containername = q->string;
643 args[0] = canonicalize_hostname(strdup(hostname));
644 args[1] = containername;
645 status = wrap_mr_query("delete_machine_from_container", 2, args,
649 com_err(whoami, status, "while deleting container mapping");
657 /* display list info if requested to */
659 struct mqelem *elem = NULL;
663 args[0] = canonicalize_hostname(strdup(hostname));
664 args[1] = args[2] = args[3] = "*";
665 status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
667 com_err(whoami, status, "while getting host information");
670 if (unformatted_flag)
671 show_host_info_unformatted(argv);
673 show_host_info(argv);
676 /* list cluster mappings if needed */
680 args[0] = canonicalize_hostname(strdup(hostname));
682 status = wrap_mr_query("get_machine_to_cluster_map", 2, args,
683 show_machine_in_cluster, NULL);
685 if (status != MR_NO_MATCH) {
686 com_err(whoami, status, "while getting cluster mappings");
691 /* list container mappings if needed */
692 if (list_container_flag) {
695 argv[0] = canonicalize_hostname(strdup(hostname));
696 status = wrap_mr_query("get_machine_to_container_map", 1, argv,
697 show_machine_in_container, NULL);
700 if (status != MR_NO_MATCH) {
701 com_err(whoami, status, "while getting container mappings");
709 argv[0] = canonicalize_hostname(strdup(hostname));
710 status = wrap_mr_query("delete_host", 1, argv, NULL, NULL);
712 com_err(whoami, status, "while deleting host");
719 exit(success ? 0 : 1);
722 void usage(char **argv)
724 #define USAGE_OPTIONS_FORMAT " %-39s%s\n"
725 fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]);
726 fprintf(stderr, "Options are\n");
727 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C | -create",
728 "-O | -owner owner");
729 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete",
730 "-S | -status status");
731 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R | -rename newname",
732 "-V | -vendor vendor");
733 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -addalias alias",
734 "-M | -model model");
735 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -deletealias alias",
736 "-L | -location location");
737 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info",
739 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-oc | -opcmt op_cmt",
740 "-c | -contact contact");
741 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ac | -admcmt adm_cmt",
742 "-bc | -billingcontact billing_contact");
743 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-A | -address address",
744 "-N | -network network");
745 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-am | -addmap cluster",
746 "-dm | deletemap cluster");
747 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-acn | -addcontainer container",
748 "-dcn | -deletecontainer container");
749 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-lm | -listmap",
750 "-lcn | -listcontainer");
751 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-u | -unformatted",
753 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-n | -noauth",
754 "-db | -database host[:port]");
758 /* Show alias information */
760 static int show_has_aliases;
762 int show_alias_info(int argc, char **argv, void *hint)
764 if(!show_has_aliases++)
765 printf("Aliases: %s", argv[0]);
767 printf(", %s", argv[0]);
772 int show_alias_info_unformatted(int argc, char **argv, void *hint)
774 if(!show_has_aliases++)
775 printf("Alias: %s", argv[0]);
777 printf(", %s", argv[0]);
782 static char *states[] = {
789 static char *MacState(int state)
791 static char buf[BUFSIZ];
793 if (state < 0 || state > 3)
795 sprintf(buf, "Unknown (%d)", state);
798 return states[state];
801 /* Retrieve information about a host */
803 int store_host_info(int argc, char **argv, void *hint)
808 for(i=0; i<argc; i++)
809 nargv[i] = strdup(argv[i]);
814 void show_host_info(char **argv)
818 struct mqelem *elem = NULL;
821 printf("Machine: %s\n", argv[M_NAME]);
823 args[1] = argv[M_NAME];
824 show_has_aliases = 0;
825 stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info, &elem);
828 if (stat != MR_NO_MATCH)
829 com_err(whoami, stat, "while getting aliases");
833 sprintf(tbuf, "%s %s", argv[M_OWNER_TYPE],
834 strcmp(argv[M_OWNER_TYPE], "NONE") ? argv[M_OWNER_NAME] : "");
835 printf("Address: %-16s Network: %-16s\n",
836 argv[M_ADDR], argv[M_SUBNET]);
837 printf("Owner: %-16s Use data: %s\n", tbuf, argv[M_INUSE]);
838 printf("Status: %-16s Changed: %s\n",
839 MacState(atoi(argv[M_STAT])), argv[M_STAT_CHNG]);
841 printf("Vendor: %-16s Location: %s\n", argv[M_VENDOR],
843 printf("Model: %-16s Contact: %s\n", argv[M_MODEL],
845 printf("OS: %-16s Billing Contact: %s\n", argv[M_OS],
846 argv[M_BILL_CONTACT]);
847 printf("\nOpt: %s\n", argv[M_USE]);
848 printf("\nAdm cmt: %s\n", argv[M_ACOMMENT]);
849 printf("Op cmt: %s\n", argv[M_OCOMMENT]);
851 printf("Created by %s on %s\n", argv[M_CREATOR], argv[M_CREATED]);
852 printf("Last mod by %s at %s with %s.\n", argv[M_MODBY], argv[M_MODTIME], argv[M_MODWITH]);
855 void show_host_info_unformatted(char **argv)
859 struct mqelem *elem = NULL;
862 printf("Machine: %s\n", argv[M_NAME]);
864 args[1] = argv[M_NAME];
865 show_has_aliases = 0;
866 stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info_unformatted,
868 if (stat && stat != MR_NO_MATCH)
869 com_err(whoami, stat, "while getting aliases");
872 printf("Address: %s\n", argv[M_ADDR]);
873 printf("Network: %s\n", argv[M_SUBNET]);
874 printf("Owner Type: %s\n", argv[M_OWNER_TYPE]);
875 printf("Owner: %s\n", argv[M_OWNER_NAME]);
876 printf("Status: %s\n", MacState(atoi(argv[M_STAT])));
877 printf("Changed: %s\n", argv[M_STAT_CHNG]);
878 printf("Use data: %s\n", argv[M_INUSE]);
879 printf("Vendor: %s\n", argv[M_VENDOR]);
880 printf("Model: %s\n", argv[M_MODEL]);
881 printf("OS: %s\n", argv[M_OS]);
882 printf("Location: %s\n", argv[M_LOC]);
883 printf("Contact: %s\n", argv[M_CONTACT]);
884 printf("Billing Contact: %s\n", argv[M_BILL_CONTACT]);
885 printf("Opt: %s\n", argv[M_USE]);
886 printf("Adm cmt: %s\n", argv[M_ACOMMENT]);
887 printf("Op cmt: %s\n", argv[M_OCOMMENT]);
888 printf("Created by: %s\n", argv[M_CREATOR]);
889 printf("Created on: %s\n", argv[M_CREATED]);
890 printf("Last mod by: %s\n", argv[M_MODBY]);
891 printf("Last mod on: %s\n", argv[M_MODTIME]);
892 printf("Last mod with: %s\n", argv[M_MODWITH]);
895 int show_machine_in_cluster(int argc, char **argv, void *hint)
897 printf("Machine: %-30s Cluster: %-30s\n", argv[0], argv[1]);
902 int show_machine_in_container(int argc, char **argv, void *hint)
904 printf("Machine: %-30s Container: %-25s\n", argv[0], argv[1]);
909 /* Parse a line of input, fetching a member. NULL is returned if a member
910 * is not found. ';' is a comment character.
913 struct owner_type *parse_member(char *s)
915 struct owner_type *m;
918 while (*s && isspace(*s))
921 while (*p && *p != '\n' && *p != ';')
923 if (isprint(*p) && !isspace(*p))
930 if (p == s || strlen(s) == 0)
933 if (!(m = malloc(sizeof(struct owner_type))))
936 if ((p = strchr(s, ':')))
940 if (!strcasecmp("user", s))
942 else if (!strcasecmp("list", s))
944 else if (!strcasecmp("kerberos", s))
945 m->type = M_KERBEROS;
946 else if (!strcasecmp("none", s))
954 m->name = strdup(m->name);
959 m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
964 struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
965 struct string_list *new_list;
967 new_list = (struct string_list *)malloc(sizeof(struct string_list *));
968 new_list->next = old_list;
969 new_list->string = s;
974 int wrap_mr_query(char *handle, int argc, char **argv,
975 int (*callback)(int, char **, void *), void *callarg) {
977 print_query(handle, argc, argv);
979 return mr_query(handle, argc, argv, callback, callarg);
982 void print_query(char *query_name, int argc, char **argv) {
985 printf("qy %s", query_name);
986 for(cnt=0; cnt<argc; cnt++)
987 printf(" <%s>", argv[cnt]);