/* * Command line oriented Moira host tool. * * kolya@MIT.EDU, January 2000 * * Somewhat based on blanche * * Copyright (C) 2000 by the Massachusetts Institute of Technology. * For copying and distribution information, please see the file * . */ #include #include #include #include #include #include #include #include #include RCSID("$Header$"); struct owner_type { int type; char *name; }; struct mqelem { struct mqelem *q_forw; struct mqelem *q_back; void *q_data; }; struct string_list { char *string; struct string_list *next; }; #define M_ANY 0 #define M_USER 1 #define M_LIST 2 #define M_KERBEROS 3 #define M_NONE 4 /* argument parsing macro */ #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b)) /* flags from command line */ int info_flag, update_flag, create_flag, delete_flag, list_map_flag; int update_map_flag, verbose, noauth; struct string_list *alias_add_queue, *alias_remove_queue; struct string_list *map_add_queue, *map_remove_queue; char *hostname, *whoami; char *newname, *address, *network, *h_status, *vendor, *model; char *os, *location, *contact, *adm_cmt, *op_cmt; struct owner_type *owner; void usage(char **argv); int store_host_info(int argc, char **argv, void *hint); void show_host_info(char **argv); int show_machine_in_cluster(int argc, char **argv, void *hint); struct owner_type *parse_member(char *s); struct string_list *add_to_string_list(struct string_list *old_list, char *s); int wrap_mr_query(char *handle, int argc, char **argv, int (*callback)(int, char **, void *), void *callarg); void print_query(char *query_name, int argc, char **argv); int main(int argc, char **argv) { int status, success; char **arg = argv; char *server = NULL; /* clear all flags & lists */ info_flag = update_flag = create_flag = list_map_flag = update_map_flag = 0; verbose = noauth = 0; newname = address = network = h_status = vendor = model = NULL; os = location = contact = adm_cmt = op_cmt = NULL; owner = NULL; alias_add_queue = alias_remove_queue = NULL; map_add_queue = map_remove_queue = NULL; whoami = argv[0]; success = 1; /* parse args, building addlist, dellist, & synclist */ while (++arg - argv < argc) { if (**arg == '-') { if (argis("i", "info")) info_flag++; else if (argis("C", "create")) create_flag++; else if (argis("D", "delete")) delete_flag++; else if (argis("R", "rename")) { if (arg - argv < argc - 1) { arg++; update_flag++; newname = *arg; } else usage(argv); } else if (argis("A", "address")) { if (arg - argv < argc - 1) { arg++; update_flag++; address = *arg; } else usage(argv); } else if (argis("O", "owner")) { if (arg - argv < argc - 1) { arg++; update_flag++; owner = parse_member(*arg); } else usage(argv); } else if (argis("N", "network")) { if (arg - argv < argc - 1) { arg++; update_flag++; network = *arg; } else usage(argv); } else if (argis("S", "status")) { if (arg - argv < argc - 1) { int i; int len; arg++; update_flag++; h_status = *arg; len = strlen(h_status); for(i = 0; i < len; i++) { if(!isdigit(h_status[i])) { printf("Error: status code %s is not numeric.\n", h_status); exit(1); } } } else usage(argv); } else if (argis("V", "vendor")) { if (arg - argv < argc - 1) { arg++; update_flag++; vendor = *arg; } else usage(argv); } else if (argis("M", "model")) { if (arg - argv < argc - 1) { arg++; update_flag++; model = *arg; } else usage(argv); } else if (argis("o", "os")) { if (arg - argv < argc - 1) { arg++; update_flag++; os = *arg; } else usage(argv); } else if (argis("L", "location")) { if (arg - argv < argc - 1) { arg++; update_flag++; location = *arg; } else usage(argv); } else if (argis("c", "contact")) { if (arg - argv < argc - 1) { arg++; update_flag++; contact = *arg; } else usage(argv); } else if (argis("ac", "admcmt")) { if (arg - argv < argc - 1) { arg++; update_flag++; adm_cmt = *arg; } else usage(argv); } else if (argis("oc", "opcmt")) { if (arg - argv < argc - 1) { arg++; update_flag++; op_cmt = *arg; } else usage(argv); } else if (argis("a", "aliasadd")) { if (arg - argv < argc - 1) { arg++; alias_add_queue=add_to_string_list(alias_add_queue, *arg); } else usage(argv); } else if (argis("d", "aliasdelete")) { if (arg - argv < argc - 1) { arg++; alias_remove_queue=add_to_string_list(alias_remove_queue, *arg); } else usage(argv); } else if (argis("am", "addmap")) { if (arg - argv < argc - 1) { arg++; map_add_queue=add_to_string_list(map_add_queue, *arg); } else usage(argv); update_map_flag++; } else if (argis("dm", "deletemap")) { if (arg - argv < argc - 1) { arg++; map_remove_queue=add_to_string_list(map_remove_queue, *arg); } else usage(argv); update_map_flag++; } else if (argis("lm", "listmap")) list_map_flag++; else if (argis("n", "noauth")) noauth++; else if (argis("v", "verbose")) verbose++; else if (argis("db", "database")) { if (arg - argv < argc - 1) { ++arg; server = *arg; } else usage(argv); } else usage(argv); } else if (hostname == NULL) hostname = *arg; else usage(argv); } if (hostname == NULL) usage(argv); /* default to info_flag if nothing else was specified */ if(!(info_flag || update_flag || create_flag || \ delete_flag || list_map_flag || update_map_flag )) { info_flag++; } /* fire up Moira */ status = mrcl_connect(server, "stella", 2, !noauth); if (status == MRCL_AUTH_ERROR) { com_err(whoami, 0, "Try the -noauth flag if you don't " "need authentication."); } if (status) exit(2); /* create if needed */ if (create_flag) { char *argv[30]; int cnt; for (cnt = 0; cnt < 15; cnt++) { argv[cnt] = ""; } argv[0] = canonicalize_hostname(strdup(hostname)); if (vendor) argv[1] = vendor; if (model) argv[2] = model; if (os) argv[3] = os; if (location) argv[4] = location; if (contact) argv[5] = contact; /* The use field always gets set to "0" */ argv[6] = "0"; if (h_status) argv[7] = h_status; else argv[7] = "1"; if (network) argv[8] = network; if (address) argv[9] = address; else argv[9] = "unique"; if (adm_cmt) argv[12] = adm_cmt; if (op_cmt) argv[13] = op_cmt; if (owner) { argv[11] = owner->name; switch (owner->type) { case M_ANY: case M_USER: argv[10] = "USER"; status = wrap_mr_query("add_host", 14, argv, NULL, NULL); if (owner->type != M_ANY || status != MR_USER) break; case M_LIST: argv[10] = "LIST"; status = wrap_mr_query("add_host", 14, argv, NULL, NULL); break; case M_KERBEROS: argv[10] = "KERBEROS"; status = wrap_mr_query("add_host", 14, argv, NULL, NULL); break; case M_NONE: argv[10] = "NONE"; status = wrap_mr_query("add_host", 14, argv, NULL, NULL); break; } } else { argv[10] = "NONE"; argv[11] = "NONE"; status = wrap_mr_query("add_host", 14, argv, NULL, NULL); } if (status) { com_err(whoami, status, "while creating host."); exit(1); } } else if (update_flag) { char *old_argv[30]; char *argv[16]; char *args[5]; args[0] = canonicalize_hostname(strdup(hostname)); args[1] = args[2] = args[3] = "*"; status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv); if (status) { com_err(whoami, status, "while getting list information"); exit(1); } argv[1] = old_argv[0]; argv[2] = old_argv[1]; argv[3] = old_argv[2]; argv[4] = old_argv[3]; argv[5] = old_argv[4]; argv[6] = old_argv[5]; argv[7] = old_argv[6]; argv[8] = old_argv[7]; argv[9] = old_argv[9]; argv[10] = old_argv[10]; argv[11] = old_argv[11]; argv[12] = old_argv[12]; argv[13] = old_argv[13]; argv[14] = old_argv[14]; argv[0] = canonicalize_hostname(strdup(hostname)); if (newname) argv[1] = canonicalize_hostname(strdup(newname)); if (vendor) argv[2] = vendor; if (model) argv[3] = model; if (os) argv[4] = os; if (location) argv[5] = location; if (contact) argv[6] = contact; if (h_status) argv[8] = h_status; if (network) argv[9] = network; if (address) argv[10] = address; if (adm_cmt) argv[13] = adm_cmt; if (op_cmt) argv[14] = op_cmt; if (owner) { argv[12] = owner->name; switch (owner->type) { case M_ANY: case M_USER: argv[11] = "USER"; status = wrap_mr_query("update_host", 15, argv, NULL, NULL); if (owner->type != M_ANY || status != MR_USER) break; case M_LIST: argv[11] = "LIST"; status = wrap_mr_query("update_host", 15, argv, NULL, NULL); break; case M_KERBEROS: argv[11] = "KERBEROS"; status = wrap_mr_query("update_host", 15, argv, NULL, NULL); break; case M_NONE: argv[11] = "NONE"; status = wrap_mr_query("update_host", 15, argv, NULL, NULL); break; } } else status = wrap_mr_query("update_host", 15, argv, NULL, NULL); if (status) com_err(whoami, status, "while updating host."); else if (newname) hostname = newname; } /* create aliases if necessary */ if (alias_add_queue) { struct string_list *q = alias_add_queue; while(q) { char *alias = q->string; char *args[2]; args[0] = partial_canonicalize_hostname(strdup(alias)); args[1] = canonicalize_hostname(strdup(hostname)); status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL); if (status) { com_err(whoami, status, "while adding host alias"); exit(1); } q = q->next; } } /* delete aliases if necessary */ if (alias_remove_queue) { struct string_list *q = alias_remove_queue; while(q) { char *alias = q->string; char *args[2]; args[0] = partial_canonicalize_hostname(strdup(alias)); args[1] = canonicalize_hostname(strdup(hostname)); status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL); if (status) { com_err(whoami, status, "while deleting host alias"); exit(1); } q = q->next; } } /* create cluster mappings */ if (map_add_queue) { struct string_list *q = map_add_queue; while(q) { char *clustername = q->string; char *args[2]; args[0] = canonicalize_hostname(strdup(hostname)); args[1] = clustername; status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL); if (status) { com_err(whoami, status, "while adding cluster mapping"); exit(1); } q = q->next; } } /* delete cluster mappings */ if (map_remove_queue) { struct string_list *q = map_remove_queue; while(q) { char *clustername = q->string; char *args[2]; args[0] = canonicalize_hostname(strdup(hostname)); args[1] = clustername; status = wrap_mr_query("delete_machine_from_cluster", 2, args, NULL, NULL); if (status) { com_err(whoami, status, "while deleting cluster mapping"); exit(1); } q = q->next; } } /* display list info if requested to */ if (info_flag) { struct mqelem *elem = NULL; char *args[5]; char *argv[30]; args[0] = canonicalize_hostname(strdup(hostname)); args[1] = args[2] = args[3] = "*"; status = wrap_mr_query("get_host", 4, args, store_host_info, argv); if (status) { com_err(whoami, status, "while getting host information"); exit(1); } show_host_info(argv); } /* list cluster mappings if needed */ if (list_map_flag) { char *args[3]; args[0] = canonicalize_hostname(strdup(hostname)); args[1] = "*"; status = wrap_mr_query("get_machine_to_cluster_map", 2, args, show_machine_in_cluster, NULL); if (status) if (status != MR_NO_MATCH) { com_err(whoami, status, "while getting cluster mappings"); exit(1); } } if (delete_flag) { char *argv[1]; argv[0] = canonicalize_hostname(strdup(hostname)); status = wrap_mr_query("delete_host", 1, argv, NULL, NULL); if (status) { com_err(whoami, status, "while deleting host"); exit(1); } } /* We're done! */ mr_disconnect(); exit(success ? 0 : 1); } void usage(char **argv) { #define USAGE_OPTIONS_FORMAT " %-39s%s\n" fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]); fprintf(stderr, "Options are\n"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C | -create", "-O | -owner owner"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete", "-S | -status status"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R | -rename newname", "-V | -vendor vendor"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -addalias alias", "-M | -model model"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -deletealias alias", "-L | -location location"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info", "-o | -os os"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-oc | -opcmt op_cmt", "-c | -contact contact"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ac | -admcmt adm_cmt", "-A | -address address"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-am | -addmap cluster", "-N | -network network"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dm | -deletemap cluster", "-lm | -listmap"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-db | -database host[:port]", "-n | -noauth"); fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose", ""); exit(1); } /* Show alias information */ static int show_has_aliases; int show_alias_info(int argc, char **argv, void *hint) { if(!show_has_aliases++) printf("Aliases: %s", argv[0]); else printf(", %s", argv[0]); return MR_CONT; } static char *states[] = { "Reserved (0)", "Active (1)", "None (2)", "Deleted (3)" }; static char *MacState(int state) { static char buf[BUFSIZ]; if (state < 0 || state > 3) { sprintf(buf, "Unknown (%d)", state); return buf; } return states[state]; } /* Retrieve information about a host */ int store_host_info(int argc, char **argv, void *hint) { int i; char **nargv = hint; for(i=0; iname = ++p; if (!strcasecmp("user", s)) m->type = M_USER; else if (!strcasecmp("list", s)) m->type = M_LIST; else if (!strcasecmp("kerberos", s)) m->type = M_KERBEROS; else if (!strcasecmp("none", s)) m->type = M_NONE; else { m->type = M_ANY; *(--p) = ':'; m->name = s; } m->name = strdup(m->name); } else { m->name = strdup(s); m->type = strcasecmp(s, "none") ? M_ANY : M_NONE; } return m; } struct string_list *add_to_string_list(struct string_list *old_list, char *s) { struct string_list *new_list; new_list = (struct string_list *)malloc(sizeof(struct string_list *)); new_list->next = old_list; new_list->string = s; return new_list; } int wrap_mr_query(char *handle, int argc, char **argv, int (*callback)(int, char **, void *), void *callarg) { if (verbose) print_query(handle, argc, argv); return mr_query(handle, argc, argv, callback, callarg); } void print_query(char *query_name, int argc, char **argv) { int cnt; printf("qy %s", query_name); for(cnt=0; cnt", argv[cnt]); printf("\n"); }