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, unformatted_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, *adm_cmt, *op_cmt;
65 struct owner_type *owner;
67 void usage(char **argv);
68 int store_host_info(int argc, char **argv, void *hint);
69 void show_host_info(char **argv);
70 void show_host_info_unformatted(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 = adm_cmt = op_cmt = NULL;
92 alias_add_queue = alias_remove_queue = NULL;
93 map_add_queue = map_remove_queue = NULL;
94 container_add_queue = container_remove_queue = NULL;
99 /* parse args, building addlist, dellist, & synclist */
100 while (++arg - argv < argc)
104 if (argis("i", "info"))
106 else if (argis("C", "create"))
108 else if (argis("D", "delete"))
110 else if (argis("R", "rename")) {
111 if (arg - argv < argc - 1) {
118 else if (argis("A", "address")) {
119 if (arg - argv < argc - 1) {
126 else if (argis("O", "owner")) {
127 if (arg - argv < argc - 1) {
130 owner = parse_member(*arg);
134 else if (argis("N", "network")) {
135 if (arg - argv < argc - 1) {
142 else if (argis("S", "status")) {
143 if (arg - argv < argc - 1) {
151 len = strlen(h_status);
152 for(i = 0; i < len; i++) {
153 if(!isdigit(h_status[i])) {
154 printf("Error: status code %s is not numeric.\n", h_status);
161 else if (argis("V", "vendor")) {
162 if (arg - argv < argc - 1) {
169 else if (argis("M", "model")) {
170 if (arg - argv < argc - 1) {
177 else if (argis("o", "os")) {
178 if (arg - argv < argc - 1) {
185 else if (argis("L", "location")) {
186 if (arg - argv < argc - 1) {
193 else if (argis("c", "contact")) {
194 if (arg - argv < argc - 1) {
201 else if (argis("bc", "billingcontact")) {
202 if (arg - argv < argc - 1) {
205 billing_contact = *arg;
209 else if (argis("ac", "admcmt")) {
210 if (arg - argv < argc - 1) {
217 else if (argis("oc", "opcmt")) {
218 if (arg - argv < argc - 1) {
225 else if (argis("a", "aliasadd")) {
226 if (arg - argv < argc - 1) {
228 alias_add_queue=add_to_string_list(alias_add_queue, *arg);
233 else if (argis("d", "aliasdelete")) {
234 if (arg - argv < argc - 1) {
236 alias_remove_queue=add_to_string_list(alias_remove_queue, *arg);
241 else if (argis("am", "addmap")) {
242 if (arg - argv < argc - 1) {
244 map_add_queue=add_to_string_list(map_add_queue, *arg);
249 else if (argis("dm", "deletemap")) {
250 if (arg - argv < argc - 1) {
252 map_remove_queue=add_to_string_list(map_remove_queue, *arg);
257 else if (argis("lm", "listmap"))
259 else if (argis("acn", "addcontainer")) {
260 if (arg - argv < argc - 1) {
262 container_add_queue =
263 add_to_string_list(container_add_queue, *arg);
266 update_container_flag++;
268 else if (argis("dcn", "deletecontainer")) {
269 if (arg - argv < argc - 1) {
271 container_remove_queue =
272 add_to_string_list(container_remove_queue, *arg);
275 update_container_flag++;
277 else if (argis("lcn", "listcontainer"))
278 list_container_flag++;
279 else if (argis("u", "unformatted"))
281 else if (argis("n", "noauth"))
283 else if (argis("v", "verbose"))
285 else if (argis("db", "database"))
287 if (arg - argv < argc - 1)
298 else if (hostname == NULL)
303 if (hostname == NULL)
306 /* default to info_flag if nothing else was specified */
307 if(!(info_flag || update_flag || create_flag || \
308 delete_flag || list_map_flag || update_map_flag || \
309 update_alias_flag || update_container_flag || \
310 list_container_flag)) {
315 status = mrcl_connect(server, "stella", 7, !noauth);
316 if (status == MRCL_AUTH_ERROR)
318 com_err(whoami, 0, "Try the -noauth flag if you don't "
319 "need authentication.");
324 /* create if needed */
330 for (cnt = 0; cnt < 16; cnt++) {
334 argv[0] = canonicalize_hostname(strdup(hostname));
347 argv[6] = billing_contact;
348 /* The use field always gets set to "0" */
367 argv[12] = owner->name;
373 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
374 if (owner->type != M_ANY || status != MR_USER)
379 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
383 argv[11] = "KERBEROS";
384 status = mrcl_validate_kerberos_member(argv[12], &argv[12]);
385 if (mrcl_get_message())
386 mrcl_com_err(whoami);
387 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
392 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
401 status = wrap_mr_query("add_host", 15, argv, NULL, NULL);
406 com_err(whoami, status, "while creating host.");
411 else if (update_flag)
417 args[0] = canonicalize_hostname(strdup(hostname));
418 args[1] = args[2] = args[3] = "*";
420 status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv);
423 com_err(whoami, status, "while getting list information");
427 argv[1] = old_argv[0];
428 argv[2] = old_argv[1];
429 argv[3] = old_argv[2];
430 argv[4] = old_argv[3];
431 argv[5] = old_argv[4];
432 argv[6] = old_argv[5];
433 argv[7] = old_argv[6];
434 argv[8] = old_argv[7];
435 argv[9] = old_argv[8];
436 argv[10] = old_argv[10];
437 argv[11] = old_argv[11];
438 argv[12] = old_argv[12];
439 argv[13] = old_argv[13];
440 argv[14] = old_argv[14];
441 argv[15] = old_argv[15];
443 argv[0] = canonicalize_hostname(strdup(hostname));
445 argv[1] = canonicalize_hostname(strdup(newname));
457 argv[7] = billing_contact;
471 argv[13] = owner->name;
477 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
478 if (owner->type != M_ANY || status != MR_USER)
483 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
487 argv[12] = "KERBEROS";
488 status = mrcl_validate_kerberos_member(argv[13], &argv[13]);
489 if (mrcl_get_message())
490 mrcl_com_err(whoami);
491 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
496 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
501 status = wrap_mr_query("update_host", 16, argv, NULL, NULL);
504 com_err(whoami, status, "while updating host.");
509 /* create aliases if necessary */
510 if (alias_add_queue) {
511 struct string_list *q = alias_add_queue;
514 char *alias = q->string;
517 args[0] = partial_canonicalize_hostname(strdup(alias));
518 args[1] = canonicalize_hostname(strdup(hostname));
519 status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL);
521 com_err(whoami, status, "while adding host alias");
529 /* delete aliases if necessary */
530 if (alias_remove_queue) {
531 struct string_list *q = alias_remove_queue;
534 char *alias = q->string;
537 args[0] = partial_canonicalize_hostname(strdup(alias));
538 args[1] = canonicalize_hostname(strdup(hostname));
539 status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL);
541 com_err(whoami, status, "while deleting host alias");
549 /* create cluster mappings */
551 struct string_list *q = map_add_queue;
554 char *clustername = q->string;
557 args[0] = canonicalize_hostname(strdup(hostname));
558 args[1] = clustername;
559 status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL);
561 com_err(whoami, status, "while adding cluster mapping");
569 /* delete cluster mappings */
570 if (map_remove_queue) {
571 struct string_list *q = map_remove_queue;
574 char *clustername = q->string;
577 args[0] = canonicalize_hostname(strdup(hostname));
578 args[1] = clustername;
579 status = wrap_mr_query("delete_machine_from_cluster", 2, args,
582 com_err(whoami, status, "while deleting cluster mapping");
590 /* add container mappings */
591 if (container_add_queue) {
592 struct string_list *q = container_add_queue;
595 char *containername = q->string;
598 args[0] = canonicalize_hostname(strdup(hostname));
599 args[1] = containername;
600 status = wrap_mr_query("add_machine_to_container", 2, args,
604 com_err(whoami, status, "while adding container mapping");
612 /* delete container mappings */
613 if (container_remove_queue) {
614 struct string_list *q = container_remove_queue;
617 char *containername = q->string;
620 args[0] = canonicalize_hostname(strdup(hostname));
621 args[1] = containername;
622 status = wrap_mr_query("delete_machine_from_container", 2, args,
626 com_err(whoami, status, "while deleting container mapping");
634 /* display list info if requested to */
636 struct mqelem *elem = NULL;
640 args[0] = canonicalize_hostname(strdup(hostname));
641 args[1] = args[2] = args[3] = "*";
642 status = wrap_mr_query("get_host", 4, args, store_host_info, argv);
644 com_err(whoami, status, "while getting host information");
647 if (unformatted_flag)
648 show_host_info_unformatted(argv);
650 show_host_info(argv);
653 /* list cluster mappings if needed */
657 args[0] = canonicalize_hostname(strdup(hostname));
659 status = wrap_mr_query("get_machine_to_cluster_map", 2, args,
660 show_machine_in_cluster, NULL);
662 if (status != MR_NO_MATCH) {
663 com_err(whoami, status, "while getting cluster mappings");
668 /* list container mappings if needed */
669 if (list_container_flag) {
672 argv[0] = canonicalize_hostname(strdup(hostname));
673 status = wrap_mr_query("get_machine_to_container_map", 1, argv,
674 show_machine_in_container, NULL);
677 if (status != MR_NO_MATCH) {
678 com_err(whoami, status, "while getting container mappings");
686 argv[0] = canonicalize_hostname(strdup(hostname));
687 status = wrap_mr_query("delete_host", 1, argv, NULL, NULL);
689 com_err(whoami, status, "while deleting host");
696 exit(success ? 0 : 1);
699 void usage(char **argv)
701 #define USAGE_OPTIONS_FORMAT " %-39s%s\n"
702 fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]);
703 fprintf(stderr, "Options are\n");
704 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C | -create",
705 "-O | -owner owner");
706 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete",
707 "-S | -status status");
708 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R | -rename newname",
709 "-V | -vendor vendor");
710 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -addalias alias",
711 "-M | -model model");
712 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -deletealias alias",
713 "-L | -location location");
714 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info",
716 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-oc | -opcmt op_cmt",
717 "-c | -contact contact");
718 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ac | -admcmt adm_cmt",
719 "-bc | -billingcontact billing_contact");
720 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-A | -address address",
721 "-N | -network network");
722 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-am | -addmap cluster",
723 "-dm | deletemap cluster");
724 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-acn | -addcontainer container",
725 "-dcn | -deletecontainer container");
726 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-lm | -listmap",
727 "-lcn | -listcontainer");
728 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-u | -unformatted",
730 fprintf(stderr, USAGE_OPTIONS_FORMAT, "-n | -noauth",
731 "-db | -database host[:port]");
735 /* Show alias information */
737 static int show_has_aliases;
739 int show_alias_info(int argc, char **argv, void *hint)
741 if(!show_has_aliases++)
742 printf("Aliases: %s", argv[0]);
744 printf(", %s", argv[0]);
749 int show_alias_info_unformatted(int argc, char **argv, void *hint)
751 if(!show_has_aliases++)
752 printf("Alias: %s", argv[0]);
754 printf(", %s", argv[0]);
759 static char *states[] = {
766 static char *MacState(int state)
768 static char buf[BUFSIZ];
770 if (state < 0 || state > 3)
772 sprintf(buf, "Unknown (%d)", state);
775 return states[state];
778 /* Retrieve information about a host */
780 int store_host_info(int argc, char **argv, void *hint)
785 for(i=0; i<argc; i++)
786 nargv[i] = strdup(argv[i]);
791 void show_host_info(char **argv)
795 struct mqelem *elem = NULL;
798 printf("Machine: %s\n", argv[M_NAME]);
800 args[1] = argv[M_NAME];
801 show_has_aliases = 0;
802 stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info, &elem);
805 if (stat != MR_NO_MATCH)
806 com_err(whoami, stat, "while getting aliases");
810 sprintf(tbuf, "%s %s", argv[M_OWNER_TYPE],
811 strcmp(argv[M_OWNER_TYPE], "NONE") ? argv[M_OWNER_NAME] : "");
812 printf("Address: %-16s Network: %-16s\n",
813 argv[M_ADDR], argv[M_SUBNET]);
814 printf("Owner: %-16s Use data: %s\n", tbuf, argv[M_INUSE]);
815 printf("Status: %-16s Changed: %s\n",
816 MacState(atoi(argv[M_STAT])), argv[M_STAT_CHNG]);
818 printf("Vendor: %-16s Location: %s\n", argv[M_VENDOR],
820 printf("Model: %-16s Contact: %s\n", argv[M_MODEL],
822 printf("OS: %-16s Billing Contact: %s\n", argv[M_OS],
823 argv[M_BILL_CONTACT]);
824 printf("\nOpt: %s\n", argv[M_USE]);
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 void show_host_info_unformatted(char **argv)
836 struct mqelem *elem = NULL;
839 printf("Machine: %s\n", argv[M_NAME]);
841 args[1] = argv[M_NAME];
842 show_has_aliases = 0;
843 stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info_unformatted,
845 if (stat && stat != MR_NO_MATCH)
846 com_err(whoami, stat, "while getting aliases");
849 printf("Address: %s\n", argv[M_ADDR]);
850 printf("Network: %s\n", argv[M_SUBNET]);
851 printf("Owner Type: %s\n", argv[M_OWNER_TYPE]);
852 printf("Owner: %s\n", argv[M_OWNER_NAME]);
853 printf("Status: %s\n", MacState(atoi(argv[M_STAT])));
854 printf("Changed: %s\n", argv[M_STAT_CHNG]);
855 printf("Use data: %s\n", argv[M_INUSE]);
856 printf("Vendor: %s\n", argv[M_VENDOR]);
857 printf("Model: %s\n", argv[M_MODEL]);
858 printf("OS: %s\n", argv[M_OS]);
859 printf("Location: %s\n", argv[M_LOC]);
860 printf("Contact: %s\n", argv[M_CONTACT]);
861 printf("Billing Contact: %s\n", argv[M_BILL_CONTACT]);
862 printf("Opt: %s\n", argv[M_USE]);
863 printf("Adm cmt: %s\n", argv[M_ACOMMENT]);
864 printf("Op cmt: %s\n", argv[M_OCOMMENT]);
865 printf("Created by: %s\n", argv[M_CREATOR]);
866 printf("Created on: %s\n", argv[M_CREATED]);
867 printf("Last mod by: %s\n", argv[M_MODBY]);
868 printf("Last mod on: %s\n", argv[M_MODTIME]);
869 printf("Last mod with: %s\n", argv[M_MODWITH]);
872 int show_machine_in_cluster(int argc, char **argv, void *hint)
874 printf("Machine: %-30s Cluster: %-30s\n", argv[0], argv[1]);
879 int show_machine_in_container(int argc, char **argv, void *hint)
881 printf("Machine: %-30s Container: %-25s\n", argv[0], argv[1]);
886 /* Parse a line of input, fetching a member. NULL is returned if a member
887 * is not found. ';' is a comment character.
890 struct owner_type *parse_member(char *s)
892 struct owner_type *m;
895 while (*s && isspace(*s))
898 while (*p && *p != '\n' && *p != ';')
900 if (isprint(*p) && !isspace(*p))
907 if (p == s || strlen(s) == 0)
910 if (!(m = malloc(sizeof(struct owner_type))))
913 if ((p = strchr(s, ':')))
917 if (!strcasecmp("user", s))
919 else if (!strcasecmp("list", s))
921 else if (!strcasecmp("kerberos", s))
922 m->type = M_KERBEROS;
923 else if (!strcasecmp("none", s))
931 m->name = strdup(m->name);
936 m->type = strcasecmp(s, "none") ? M_ANY : M_NONE;
941 struct string_list *add_to_string_list(struct string_list *old_list, char *s) {
942 struct string_list *new_list;
944 new_list = (struct string_list *)malloc(sizeof(struct string_list *));
945 new_list->next = old_list;
946 new_list->string = s;
951 int wrap_mr_query(char *handle, int argc, char **argv,
952 int (*callback)(int, char **, void *), void *callarg) {
954 print_query(handle, argc, argv);
956 return mr_query(handle, argc, argv, callback, callarg);
959 void print_query(char *query_name, int argc, char **argv) {
962 printf("qy %s", query_name);
963 for(cnt=0; cnt<argc; cnt++)
964 printf(" <%s>", argv[cnt]);