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 <mit-copyright.h>
15 #include <moira_site.h>
25 typedef unsigned long in_addr_t;
27 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <netinet/in.h>
31 #include <arpa/inet.h>
42 struct mqelem *q_forw;
43 struct mqelem *q_back;
49 struct string_list *next;
58 /* argument parsing macro */
59 #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b))
61 /* flags from command line */
62 int info_flag, update_flag, create_flag, delete_flag, list_map_flag;
63 int update_alias_flag, update_map_flag, verbose, noauth;
64 int list_container_flag, update_container_flag, unformatted_flag;
66 struct string_list *alias_add_queue, *alias_remove_queue;
67 struct string_list *map_add_queue, *map_remove_queue;
68 struct string_list *container_add_queue, *container_remove_queue;
70 char *hostname, *whoami;
72 char *newname, *address, *network, *h_status, *vendor, *model;
73 char *os, *location, *contact, *billing_contact, *account_number;
74 char *adm_cmt, *op_cmt;
77 struct owner_type *owner;
79 void usage(char **argv);
80 int store_host_info(int argc, char **argv, void *hint);
81 void show_host_info(char **argv);
82 void show_host_info_unformatted(char **argv);
83 int show_machine_in_cluster(int argc, char **argv, void *hint);
84 int show_machine_in_container(int argc, char **argv, void *hint);
85 struct owner_type *parse_member(char *s);
86 struct string_list *add_to_string_list(struct string_list *old_list, char *s);
87 int wrap_mr_query(char *handle, int argc, char **argv,
88 int (*callback)(int, char **, void *), void *callarg);
89 void print_query(char *query_name, int argc, char **argv);
91 int main(int argc, char **argv)
97 /* clear all flags & lists */
98 info_flag = update_flag = create_flag = list_map_flag = update_map_flag = 0;
99 update_alias_flag = verbose = noauth = 0;
100 list_container_flag = update_container_flag = 0;
101 newname = address = network = h_status = vendor = model = NULL;
102 os = location = contact = billing_contact = account_number = adm_cmt = NULL;
105 alias_add_queue = alias_remove_queue = NULL;
106 map_add_queue = map_remove_queue = NULL;
107 container_add_queue = container_remove_queue = NULL;
112 /* parse args, building addlist, dellist, & synclist */
113 while (++arg - argv < argc)
117 if (argis("i", "info"))
119 else if (argis("C", "create"))
121 else if (argis("D", "delete"))
123 else if (argis("R", "rename")) {
124 if (arg - argv < argc - 1) {
131 else if (argis("A", "address")) {
132 if (arg - argv < argc - 1) {
139 else if (argis("O", "owner")) {
140 if (arg - argv < argc - 1) {
143 owner = parse_member(*arg);
147 else if (argis("N", "network")) {
148 if (arg - argv < argc - 1) {
155 else if (argis("S", "status")) {
156 if (arg - argv < argc - 1) {
164 len = strlen(h_status);
165 for(i = 0; i < len; i++) {
166 if(!isdigit(h_status[i])) {
167 printf("Error: status code %s is not numeric.\n", h_status);
174 else if (argis("V", "vendor")) {
175 if (arg - argv < argc - 1) {
182 else if (argis("M", "model")) {
183 if (arg - argv < argc - 1) {
190 else if (argis("o", "os")) {
191 if (arg - argv < argc - 1) {
198 else if (argis("L", "location")) {
199 if (arg - argv < argc - 1) {
206 else if (argis("c", "contact")) {
207 if (arg - argv < argc - 1) {
214 else if (argis("bc", "billingcontact")) {
215 if (arg - argv < argc - 1) {
218 billing_contact = *arg;
222 else if (argis("an", "accountnumber")) {
223 if (arg - argv < argc - 1) {
226 account_number = *arg;
230 else if (argis("ac", "admcmt")) {
231 if (arg - argv < argc - 1) {
238 else if (argis("oc", "opcmt")) {
239 if (arg - argv < argc - 1) {
246 else if (argis("a", "addalias")) {
247 if (arg - argv < argc - 1) {
249 alias_add_queue=add_to_string_list(alias_add_queue, *arg);
254 else if (argis("d", "deletealias")) {
255 if (arg - argv < argc - 1) {
257 alias_remove_queue=add_to_string_list(alias_remove_queue, *arg);
262 else if (argis("am", "addmap")) {
263 if (arg - argv < argc - 1) {
265 map_add_queue=add_to_string_list(map_add_queue, *arg);
270 else if (argis("dm", "deletemap")) {
271 if (arg - argv < argc - 1) {
273 map_remove_queue=add_to_string_list(map_remove_queue, *arg);
278 else if (argis("lm", "listmap"))
280 else if (argis("acn", "addcontainer")) {
281 if (arg - argv < argc - 1) {
283 container_add_queue =
284 add_to_string_list(container_add_queue, *arg);
287 update_container_flag++;
289 else if (argis("dcn", "deletecontainer")) {
290 if (arg - argv < argc - 1) {
292 container_remove_queue =
293 add_to_string_list(container_remove_queue, *arg);
296 update_container_flag++;
298 else if (argis("lcn", "listcontainer"))
299 list_container_flag++;
300 else if (argis("u", "unformatted"))
302 else if (argis("n", "noauth"))
304 else if (argis("v", "verbose"))
306 else if (argis("db", "database"))
308 if (arg - argv < argc - 1)
319 else if (hostname == NULL)
324 if (hostname == NULL)
327 /* default to info_flag if nothing else was specified */
328 if(!(info_flag || update_flag || create_flag || \
329 delete_flag || list_map_flag || update_map_flag || \
330 update_alias_flag || update_container_flag || \
331 list_container_flag)) {
336 status = mrcl_connect(server, "stella", 8, !noauth);
337 if (status == MRCL_AUTH_ERROR)
339 com_err(whoami, 0, "Try the -noauth flag if you don't "
340 "need authentication.");
345 /* Perform the lookup by IP address if that's what we've been handed */
346 if ((ipaddress=inet_addr(hostname)) != -1) {
350 args[1] = strdup(hostname);
351 args[0] = args[2] = args[3] = "*";
352 status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
355 com_err(whoami, status, "while looking up IP address.");
361 /* create if needed */
367 for (cnt = 0; cnt < 17; cnt++) {
371 argv[0] = canonicalize_hostname(strdup(hostname));
384 argv[6] = billing_contact;
386 argv[7] = account_number;
387 /* The use field always gets set to "0" */
406 argv[13] = owner->name;
412 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
413 if (owner->type != M_ANY || status != MR_USER)
418 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
422 argv[12] = "KERBEROS";
423 status = mrcl_validate_kerberos_member(argv[13], &argv[13]);
424 if (mrcl_get_message())
425 mrcl_com_err(whoami);
426 if (status == MRCL_REJECT)
428 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
433 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
442 status = wrap_mr_query("add_host", 16, argv, NULL, NULL);
447 com_err(whoami, status, "while creating host.");
452 else if (update_flag)
458 args[0] = canonicalize_hostname(strdup(hostname));
459 args[1] = args[2] = args[3] = "*";
461 status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv);
464 com_err(whoami, status, "while getting list information");
468 argv[1] = old_argv[0];
469 argv[2] = old_argv[1];
470 argv[3] = old_argv[2];
471 argv[4] = old_argv[3];
472 argv[5] = old_argv[4];
473 argv[6] = old_argv[5];
474 argv[7] = old_argv[6];
475 argv[8] = old_argv[7];
476 argv[9] = old_argv[8];
477 argv[10] = old_argv[9];
478 argv[11] = old_argv[11];
479 argv[12] = old_argv[12];
480 argv[13] = old_argv[13];
481 argv[14] = old_argv[14];
482 argv[15] = old_argv[15];
483 argv[16] = old_argv[16];
485 argv[0] = canonicalize_hostname(strdup(hostname));
487 argv[1] = canonicalize_hostname(strdup(newname));
499 argv[7] = billing_contact;
501 argv[8] = account_number;
515 argv[14] = owner->name;
521 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
522 if (owner->type != M_ANY || status != MR_USER)
527 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
531 argv[13] = "KERBEROS";
532 status = mrcl_validate_kerberos_member(argv[14], &argv[14]);
533 if (mrcl_get_message())
534 mrcl_com_err(whoami);
535 if (status == MRCL_REJECT)
537 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
542 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
547 status = wrap_mr_query("update_host", 17, argv, NULL, NULL);
550 com_err(whoami, status, "while updating host.");
555 /* create aliases if necessary */
556 if (alias_add_queue) {
557 struct string_list *q = alias_add_queue;
560 char *alias = q->string;
563 args[0] = partial_canonicalize_hostname(strdup(alias));
564 args[1] = canonicalize_hostname(strdup(hostname));
565 status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL);
567 com_err(whoami, status, "while adding host alias");
575 /* delete aliases if necessary */
576 if (alias_remove_queue) {
577 struct string_list *q = alias_remove_queue;
580 char *alias = q->string;
583 args[0] = partial_canonicalize_hostname(strdup(alias));
584 args[1] = canonicalize_hostname(strdup(hostname));
585 status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL);
587 com_err(whoami, status, "while deleting host alias");
595 /* create cluster mappings */
597 struct string_list *q = map_add_queue;
600 char *clustername = q->string;
603 args[0] = canonicalize_hostname(strdup(hostname));
604 args[1] = clustername;
605 status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL);
607 com_err(whoami, status, "while adding cluster mapping");
615 /* delete cluster mappings */
616 if (map_remove_queue) {
617 struct string_list *q = map_remove_queue;
620 char *clustername = q->string;
623 args[0] = canonicalize_hostname(strdup(hostname));
624 args[1] = clustername;
625 status = wrap_mr_query("delete_machine_from_cluster", 2, args,
628 com_err(whoami, status, "while deleting cluster mapping");
636 /* add container mappings */
637 if (container_add_queue) {
638 struct string_list *q = container_add_queue;
641 char *containername = q->string;
644 args[0] = canonicalize_hostname(strdup(hostname));
645 args[1] = containername;
646 status = wrap_mr_query("add_machine_to_container", 2, args,
650 com_err(whoami, status, "while adding container mapping");
658 /* delete container mappings */
659 if (container_remove_queue) {
660 struct string_list *q = container_remove_queue;
663 char *containername = q->string;
666 args[0] = canonicalize_hostname(strdup(hostname));
667 args[1] = containername;
668 status = wrap_mr_query("delete_machine_from_container", 2, args,
672 com_err(whoami, status, "while deleting container mapping");
680 /* display list info if requested to */
682 struct mqelem *elem = NULL;
686 args[0] = canonicalize_hostname(strdup(hostname));
687 args[1] = args[2] = args[3] = "*";
688 status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
690 /* We might be looking for an alias of a deleted host. */
691 if (status && status == MR_NO_MATCH) {
692 status = wrap_mr_query("get_hostalias", 2, args, store_host_info, argv);
694 args[0] = strdup(argv[1]);
695 status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
700 com_err(whoami, status, "while getting host information");
704 if (unformatted_flag)
705 show_host_info_unformatted(argv);
707 show_host_info(argv);
708 args[0] = argv[M_SUBNET];
709 status = wrap_mr_query("get_subnet", 1, args, store_host_info, argv);
711 com_err(whoami, status, "while getting subnet information");
712 if (atoi(argv[SN_STATUS]) == SNET_STATUS_PRIVATE_10MBPS ||
713 atoi(argv[SN_STATUS]) == SNET_STATUS_PRIVATE_100MBPS ||
714 atoi(argv[SN_STATUS]) == SNET_STATUS_PRIVATE_1000MBPS)
716 fprintf(stderr, "\nWarning: This host is on a private subnet.\n");
717 fprintf(stderr, "Billing information shown is superseded by billing information for the subnet.\n");
721 /* list cluster mappings if needed */
725 args[0] = canonicalize_hostname(strdup(hostname));
727 status = wrap_mr_query("get_machine_to_cluster_map", 2, args,
728 show_machine_in_cluster, NULL);
730 if (status != MR_NO_MATCH) {
731 com_err(whoami, status, "while getting cluster mappings");
736 /* list container mappings if needed */
737 if (list_container_flag) {
740 argv[0] = canonicalize_hostname(strdup(hostname));
741 status = wrap_mr_query("get_machine_to_container_map", 1, argv,
742 show_machine_in_container, NULL);
745 if (status != MR_NO_MATCH) {
746 com_err(whoami, status, "while getting container mappings");
754 argv[0] = canonicalize_hostname(strdup(hostname));
755 status = wrap_mr_query("delete_host", 1, argv, NULL, NULL);
757 com_err(whoami, status, "while deleting host");
764 exit(success ? 0 : 1);
767 void usage(char **argv)
769 #define USAGE_OPTIONS_FORMAT " %-39s%s\n"
770 fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]);
771 fprintf(stderr, "Options are\n");
772 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C | -create",
773 "-O | -owner owner");
774 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete",
775 "-S | -status status");
776 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R | -rename newname",
777 "-V | -vendor vendor");
778 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -addalias alias",
779 "-M | -model model");
780 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -deletealias alias",
781 "-L | -location location");
782 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info",
784 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-oc | -opcmt op_cmt",
785 "-c | -contact contact");
786 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ac | -admcmt adm_cmt",
787 "-bc | -billingcontact billing_contact");
788 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-an | -accountnumber account_number", "-A | -address address");
789 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-N | -network network",
790 "-am | -addmap cluster");
791 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dm | deletemap cluster",
792 "-acn | -addcontainer container");
793 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dcn | -deletecontainer container",
795 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-lcn | -listcontainer",
796 "-u | -unformatted");
797 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose",
799 fprintf(stderr, " %-39s\n" , "-db | -database host[:port]");
803 /* Show alias information */
805 static int show_has_aliases;
807 int show_alias_info(int argc, char **argv, void *hint)
809 if(!show_has_aliases++)
810 printf("Aliases: %s", argv[0]);
812 printf(", %s", argv[0]);
817 int show_alias_info_unformatted(int argc, char **argv, void *hint)
819 if(!show_has_aliases++)
820 printf("Alias: %s", argv[0]);
822 printf(", %s", argv[0]);
827 static char *states[] = {
834 static char *MacState(int state)
836 static char buf[BUFSIZ];
838 if (state < 0 || state > 3)
840 sprintf(buf, "Unknown (%d)", state);
843 return states[state];
846 /* Retrieve information about a host */
848 int store_host_info(int argc, char **argv, void *hint)
853 for(i=0; i<argc; i++)
854 nargv[i] = strdup(argv[i]);
859 void show_host_info(char **argv)
863 struct mqelem *elem = NULL;
866 printf("Machine: %s\n", argv[M_NAME]);
868 args[1] = argv[M_NAME];
869 show_has_aliases = 0;
870 stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info, &elem);
873 if (stat != MR_NO_MATCH)
874 com_err(whoami, stat, "while getting aliases");
878 sprintf(tbuf, "%s %s", argv[M_OWNER_TYPE],
879 strcmp(argv[M_OWNER_TYPE], "NONE") ? argv[M_OWNER_NAME] : "");
880 printf("Address: %-16s Network: %-16s\n",
881 argv[M_ADDR], argv[M_SUBNET]);
882 printf("Owner: %-16s Use data: %s\n", tbuf, argv[M_INUSE]);
883 printf("Status: %-16s Changed: %s\n",
884 MacState(atoi(argv[M_STAT])), argv[M_STAT_CHNG]);
886 printf("Vendor: %-16s Location: %s\n", argv[M_VENDOR],
888 printf("Model: %-16s Contact: %s\n", argv[M_MODEL],
890 printf("OS: %-16s Billing Contact: %s\n", argv[M_OS],
891 argv[M_BILL_CONTACT]);
892 printf("Opt: %-16s Account Number: %s\n", argv[M_USE],
893 argv[M_ACCT_NUMBER]);
894 printf("\nAdm cmt: %s\n", argv[M_ACOMMENT]);
895 printf("Op cmt: %s\n", argv[M_OCOMMENT]);
897 printf("Created by %s on %s\n", argv[M_CREATOR], argv[M_CREATED]);
898 printf("Last mod by %s at %s with %s.\n", argv[M_MODBY], argv[M_MODTIME], argv[M_MODWITH]);
901 void show_host_info_unformatted(char **argv)
904 struct mqelem *elem = NULL;
907 printf("Machine: %s\n", argv[M_NAME]);
909 args[1] = argv[M_NAME];
910 show_has_aliases = 0;
911 stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info_unformatted,
913 if (stat && stat != MR_NO_MATCH)
914 com_err(whoami, stat, "while getting aliases");
917 printf("Address: %s\n", argv[M_ADDR]);
918 printf("Network: %s\n", argv[M_SUBNET]);
919 printf("Owner Type: %s\n", argv[M_OWNER_TYPE]);
920 printf("Owner: %s\n", argv[M_OWNER_NAME]);
921 printf("Status: %s\n", MacState(atoi(argv[M_STAT])));
922 printf("Changed: %s\n", argv[M_STAT_CHNG]);
923 printf("Use data: %s\n", argv[M_INUSE]);
924 printf("Vendor: %s\n", argv[M_VENDOR]);
925 printf("Model: %s\n", argv[M_MODEL]);
926 printf("OS: %s\n", argv[M_OS]);
927 printf("Location: %s\n", argv[M_LOC]);
928 printf("Contact: %s\n", argv[M_CONTACT]);
929 printf("Billing Contact: %s\n", argv[M_BILL_CONTACT]);
930 printf("Account Number: %s\n", argv[M_ACCT_NUMBER]);
931 printf("Opt: %s\n", argv[M_USE]);
932 printf("Adm cmt: %s\n", argv[M_ACOMMENT]);
933 printf("Op cmt: %s\n", argv[M_OCOMMENT]);
934 printf("Created by: %s\n", argv[M_CREATOR]);
935 printf("Created on: %s\n", argv[M_CREATED]);
936 printf("Last mod by: %s\n", argv[M_MODBY]);
937 printf("Last mod on: %s\n", argv[M_MODTIME]);
938 printf("Last mod with: %s\n", argv[M_MODWITH]);
941 int show_machine_in_cluster(int argc, char **argv, void *hint)
943 printf("Machine: %-30s Cluster: %-30s\n", argv[0], argv[1]);
948 int show_machine_in_container(int argc, char **argv, void *hint)
950 printf("Machine: %-30s Container: %-25s\n", argv[0], argv[1]);
955 /* Parse a line of input, fetching a member. NULL is returned if a member
956 * is not found. ';' is a comment character.
959 struct owner_type *parse_member(char *s)
961 struct owner_type *m;
964 while (*s && isspace(*s))
967 while (*p && *p != '\n' && *p != ';')
969 if (isprint(*p) && !isspace(*p))
976 if (p == s || strlen(s) == 0)
979 if (!(m = malloc(sizeof(struct owner_type))))
982 if ((p = strchr(s, ':')))
986 if (!strcasecmp("user", s))
988 else if (!strcasecmp("list", s))
990 else if (!strcasecmp("kerberos", s))
991 m->type = M_KERBEROS;
992 else if (!strcasecmp("none", s))
1000 m->name = strdup(m->name);
1004 m->name = strdup(s);
1005 m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
1010 struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
1011 struct string_list *new_list;
1013 new_list = (struct string_list *)malloc(sizeof(struct string_list *));
1014 new_list->next = old_list;
1015 new_list->string = s;
1020 int wrap_mr_query(char *handle, int argc, char **argv,
1021 int (*callback)(int, char **, void *), void *callarg) {
1023 print_query(handle, argc, argv);
1025 return mr_query(handle, argc, argv, callback, callarg);
1028 void print_query(char *query_name, int argc, char **argv) {
1031 printf("qy %s", query_name);
1032 for(cnt=0; cnt<argc; cnt++)
1033 printf(" <%s>", argv[cnt]);