1 #if (!defined(lint) && !defined(SABER))
2 static char rcsid_module_c[] = "$Header$";
5 /* This is the file cluster.c for the MOIRA Client, which allows a nieve
6 * user to quickly and easily maintain most parts of the MOIRA database.
10 * By: Chris D. Peterson
16 * Copyright 1988 by the Massachusetts Institute of Technology.
18 * For further information on copyright and distribution
19 * see the file mit-copyright.h
22 /* BTW: for anyone who cares MCD is short for Machine, Cluster, Data. */
27 #include <moira_site.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
31 #include <netinet/in.h>
32 #include <arpa/inet.h>
34 #include <sys/utsname.h>
39 #include "mit-copyright.h"
51 #define M_DEFAULT_TYPE DEFAULT_NONE
53 #define C_DEFAULT_DESCRIPT DEFAULT_NONE
54 #define C_DEFAULT_LOCATION DEFAULT_NONE
56 #define CD_DEFAULT_LABEL DEFAULT_NONE
57 #define CD_DEFAULT_DATA DEFAULT_NONE
59 #define S_DEFAULT_LOW "18.0.0.20"
60 #define S_DEFAULT_HIGH "18.0.2.249"
62 static char *states[] = { "Reserved (0)",
66 static char *uses[] = { "none (0)"};
68 static char *MacState(state)
73 if (state < 0 || state > 3) {
74 sprintf(buf, "Unknown (%d)", state);
77 return(states[state]);
82 /* -------------------- Set Defaults -------------------- */
84 /* Function Name: SetMachineDefaults
85 * Description: sets machine defaults.
86 * Arguments: info - an array to put the defaults into.
87 * name - Canonacalized name of the machine.
88 * Returns: info - the array.
92 SetMachineDefaults(info, name)
95 info[M_NAME] = Strsave(name);
96 info[M_VENDOR] = Strsave(M_DEFAULT_TYPE);
97 info[M_MODEL] = Strsave(M_DEFAULT_TYPE);
98 info[M_OS] = Strsave(M_DEFAULT_TYPE);
99 info[M_LOC] = Strsave(M_DEFAULT_TYPE);
100 info[M_CONTACT] = Strsave(M_DEFAULT_TYPE);
101 info[M_USE] = Strsave("0");
102 info[M_STAT] = Strsave("1");
103 info[M_SUBNET] = Strsave("NONE");
104 info[M_ADDR] = Strsave("unique");
105 info[M_OWNER_TYPE] = Strsave("NONE");
106 info[M_OWNER_NAME] = Strsave("NONE");
107 info[M_ACOMMENT] = Strsave("");
108 info[M_OCOMMENT] = Strsave("");
109 info[15] = info[16] = NULL;
113 /* Function Name: SetClusterDefaults
114 * Description: sets Cluster defaults.
115 * Arguments: info - an array to put the defaults into.
116 * name - name of the Cluster.
117 * Returns: info - the array.
121 SetClusterDefaults(info, name)
124 info[C_NAME] = Strsave(name);
125 info[C_DESCRIPT] = Strsave(C_DEFAULT_DESCRIPT);
126 info[C_LOCATION] = Strsave(C_DEFAULT_LOCATION);
127 info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
131 /* Function Name: SetSubnetDefaults
132 * Description: sets Subnet defaults.
133 * Arguments: info - an array to put the defaults into.
134 * name - name of the Subnet.
135 * Returns: info - the array.
139 SetSubnetDefaults(info, name)
144 info[C_NAME] = Strsave(name);
145 info[SN_DESC] = Strsave("");
146 sprintf(buf, "%d", ntohl(inet_addr("18.255.0.0")));
147 info[SN_ADDRESS] = Strsave(buf);
148 sprintf(buf, "%d", ntohl(inet_addr("255.255.0.0")));
149 info[SN_MASK] = Strsave(buf);
150 sprintf(buf, "%d", ntohl(inet_addr(S_DEFAULT_LOW)));
151 info[SN_LOW] = Strsave(buf);
152 sprintf(buf, "%d", ntohl(inet_addr(S_DEFAULT_HIGH)));
153 info[SN_HIGH] = Strsave(buf);
154 info[SN_PREFIX] = Strsave("");
155 info[SN_ACE_TYPE] = Strsave("LIST");
156 info[SN_ACE_NAME] = Strsave("network");
157 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
161 /* -------------------- General Functions -------------------- */
163 static char aliasbuf[256];
169 if (strlen(aliasbuf) == 0)
170 sprintf(aliasbuf, "Aliases: %s", info[0]);
172 strcat(aliasbuf, ", ");
173 strcat(aliasbuf, info[0]);
178 /* Function Name: PrintMachInfo
179 * Description: This function Prints out the Machine info in
181 * Arguments: info - array of information about a machine.
182 * Returns: The name of the Machine
189 char buf[BUFSIZ], tbuf[256];
191 struct qelem *elem = NULL;
195 sprintf(buf, "Machine: %s", info[M_NAME]);
198 args[1] = info[M_NAME];
199 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, (char *)&elem))
201 if (stat != MR_NO_MATCH)
202 com_err(program_name, stat, " looking up aliases");
205 Loop(QueueTop(elem), (void *) PrintAliases);
207 Put_message(aliasbuf);
209 sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
210 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
211 sprintf(buf, "Address: %-16s Network: %-16s",
212 info[M_ADDR], info[M_SUBNET]);
214 sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]);
216 sprintf(buf, "Status: %-16s Changed: %s",
217 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
221 sprintf(buf, "Vendor: %-16s Model: %-20s OS: %s",
222 info[M_VENDOR], info[M_MODEL], info[M_OS]);
224 sprintf(buf, "Location: %-16s Contact: %-20s Opt: %s",
225 info[M_LOC], info[M_CONTACT], info[M_USE]);
227 sprintf(buf, "\nAdm cmt: %s", info[M_ACOMMENT]);
229 sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]);
232 sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]);
234 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
236 return(info[M_NAME]);
239 /* Function Name: PrintCname
240 * Description: Prints the Data on a host alias
241 * Arguments: info a pointer to the data array.
242 * Returns: The name of the alias.
251 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
256 /* Function Name: PrintClusterInfo
257 * Description: This function Prints out the cluster info
258 * in a coherent form.
259 * Arguments: info - array of information about a cluster.
260 * Returns: The name of the cluster.
264 PrintClusterInfo(info)
270 sprintf(buf, "Cluster: %s", info[C_NAME]);
272 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
274 sprintf(buf, "Location: %s", info[C_LOCATION]);
276 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
278 return(info[C_NAME]);
281 /* Function Name: PrintClusterData
282 * Description: Prints the Data on a cluster
283 * Arguments: info a pointer to the data array.
284 * Returns: The name of the cluster.
288 PrintClusterData(info)
294 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
295 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
297 return(info[CD_NAME]);
300 /* Function Name: PrintMCMap
301 * Description: Prints the data about a machine to cluster mapping.
302 * Arguments: info a pointer to the data array.
311 sprintf(buf, "Cluster: %-30s Machine: %-20s",
312 info[MAP_CLUSTER], info[MAP_MACHINE]);
314 return(""); /* Used by QueryLoop(). */
317 /* Function Name: PrintSubnetInfo
318 * Description: This function Prints out the subnet info
319 * in a coherent form.
320 * Arguments: info - array of information about a subnet.
321 * Returns: The name of the subnet.
325 PrintSubnetInfo(info)
329 struct in_addr addr, mask, low, high;
332 sprintf(buf, " Network: %s", info[SN_NAME]);
334 sprintf(buf, " Description: %s", info[SN_DESC]);
336 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
337 mask.s_addr = htonl(atoi(info[SN_MASK]));
338 low.s_addr = htonl(atoi(info[SN_LOW]));
339 high.s_addr = htonl(atoi(info[SN_HIGH]));
340 /* screwy sequence is here because inet_ntoa returns a pointer to
341 a static buf. If it were all one sprintf, the last value would
343 sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr));
344 strcat(buf, inet_ntoa(mask));
345 strcat(buf, "\n High: ");
346 strcat(buf, inet_ntoa(high));
347 strcat(buf, " Low: ");
348 strcat(buf, inet_ntoa(low));
350 sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
352 sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE],
353 strcmp(info[SN_ACE_TYPE],"NONE") ? info[SN_ACE_NAME] : "");
355 sprintf(buf,MOD_FORMAT,info[SN_MODBY],info[SN_MODTIME],info[SN_MODWITH]);
357 return(info[SN_NAME]);
360 /* Function Name: GetMCInfo.
361 * Description: This function stores info about a machine.
362 * type - type of data we are trying to retrieve.
363 * name1 - the name of argv[0] for the call.
364 * name2 - the name of argv[1] for the call.
365 * Returns: the top element of a queue containing the data or NULL.
369 GetMCInfo(type, name1, name2)
371 char * name1, *name2;
375 struct qelem * elem = NULL;
381 args[1] = args[2] = args[3] = "*";
382 if ( (stat = do_mr_query("get_host", 4, args,
383 StoreInfo, (char *)&elem)) != 0) {
384 if (stat == MR_NO_MATCH) {
386 sprintf(buf, "Machine '%s' is not in the database.", name1);
389 com_err(program_name, stat, " in get_machine.");
396 if ( (stat = do_mr_query("get_hostalias", 2, args,
397 StoreInfo, (char *)&elem)) != 0) {
398 com_err(program_name, stat, " in get_hostalias.");
403 if ( (stat = do_mr_query("get_subnet", 1, &name1,
404 StoreInfo, (char *)&elem)) != 0) {
405 if (stat == MR_NO_MATCH) {
407 sprintf(buf, "Network '%s' is not in the database.", name1);
410 com_err(program_name, stat, " in get_subnet.");
415 if ( (stat = do_mr_query("get_cluster", 1, &name1,
416 StoreInfo, (char *)&elem)) != 0) {
417 com_err(program_name, stat, " in get_cluster.");
422 args[MAP_MACHINE] = name1;
423 args[MAP_CLUSTER] = name2;
424 if ( (stat = do_mr_query("get_machine_to_cluster_map", 2, args,
425 StoreInfo, (char *)&elem)) != 0) {
426 com_err(program_name, stat, " in get_machine_to_cluster_map.");
431 args[CD_NAME] = name1;
432 args[CD_LABEL] = name2;
433 if ( (stat = do_mr_query("get_cluster_data", 2, args,
434 StoreInfo, (char *)&elem)) != 0) {
435 com_err(program_name, stat, " in get_cluster_data.");
439 return(QueueTop(elem));
442 /* Function Name: AskMCDInfo.
443 * Description: This function askes the user for information about a
444 * machine and saves it into a structure.
445 * Arguments: info - a pointer the information to ask about
446 * type - type of information - MACHINE
449 * name - T/F : change the name of this type.
454 AskMCDInfo(info, type, name)
459 char temp_buf[BUFSIZ], *newname, *oldnewname;
463 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
467 sprintf(temp_buf, "Setting the information for the Network %s...",
471 sprintf(temp_buf, "Setting the information for the Cluster %s...",
475 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
479 Put_message(temp_buf);
484 newname = Strsave(info[M_NAME]);
485 if (GetValueFromUser("The new name for this machine? ", &newname) ==
488 oldnewname = Strsave(newname);
489 newname = canonicalize_hostname(newname);
490 if (strcasecmp(newname, oldnewname) && *oldnewname != '"') {
491 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
492 oldnewname, newname);
493 Put_message(temp_buf);
498 newname = Strsave(info[SN_NAME]);
499 if (GetValueFromUser("The new name for this network? ",
500 &newname) == SUB_ERROR)
504 newname = Strsave(info[C_NAME]);
505 if (GetValueFromUser("The new name for this cluster? ",
506 &newname) == SUB_ERROR)
510 Put_message("Unknown type in AskMCDInfo, programmer botch");
517 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
519 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
521 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
524 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
526 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
530 if (GetValueFromUser("Machine's use code", &info[M_USE]) == SUB_ERROR)
535 if (GetValueFromUser("Machine's status (? for help)",
536 &info[M_STAT]) == SUB_ERROR)
538 if (isdigit(info[M_STAT][0])) break;
539 Put_message("Valid status numbers:");
540 for (i = 0; i < 4; i++) Put_message(states[i]);
543 /* there appears to be some argument mismatch between the client
544 * and the server.. so here is this argument shuffler.
545 * I have since modified this to always shuffle the arguments..
546 * not just do so when performing a modify all fields request.
547 * The SetMachinedefaults() has been changed to reflect this.
548 * pray for us and may we attain enlightenment through structures.
551 info[8] = info[M_SUBNET];
552 info[9] = info[M_ADDR];
553 info[10] = info[M_OWNER_TYPE];
554 info[11] = info[M_OWNER_NAME];
555 info[12] = info[M_ACOMMENT];
556 info[13] = info[M_OCOMMENT];
559 if (GetValueFromUser("Machine's network (or 'none')", &info[8])
562 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
563 &info[9]) == SUB_ERROR)
565 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[10]) ==
568 if (strcmp(info[10], "NONE") &&
569 GetValueFromUser("Owner's Name", &info[11]) == SUB_ERROR)
571 if (GetValueFromUser("Administrative comment", &info[12]) == SUB_ERROR)
573 if (GetValueFromUser("Operational comment", &info[13]) == SUB_ERROR)
576 FreeAndClear(&info[15], TRUE);
577 FreeAndClear(&info[16], TRUE);
580 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
582 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
584 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
586 if (atoi(info[SN_LOW]) == ntohl(inet_addr(S_DEFAULT_LOW))) {
588 unsigned long mask, addr;
590 addr = atoi(info[SN_ADDRESS]);
591 mask = atoi(info[SN_MASK]);
592 low.s_addr = atoi(info[SN_LOW]);
593 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
595 sprintf(temp_buf, "%d", low.s_addr);
596 info[SN_LOW] = strsave(temp_buf);
598 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) == SUB_ERROR)
600 if (atoi(info[SN_HIGH]) == ntohl(inet_addr(S_DEFAULT_HIGH))) {
602 unsigned long mask, addr;
604 addr = atoi(info[SN_ADDRESS]);
605 mask = atoi(info[SN_MASK]);
606 high.s_addr = atoi(info[SN_HIGH]);
607 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
609 sprintf(temp_buf, "%d", high.s_addr);
610 info[SN_HIGH] = strsave(temp_buf);
612 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) == SUB_ERROR)
614 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
616 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) == SUB_ERROR)
618 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
619 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
621 FreeAndClear(&info[SN_MODTIME], TRUE);
622 FreeAndClear(&info[SN_MODBY], TRUE);
623 FreeAndClear(&info[SN_MODWITH], TRUE);
626 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
629 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
632 FreeAndClear(&info[C_MODTIME], TRUE);
633 FreeAndClear(&info[C_MODBY], TRUE);
634 FreeAndClear(&info[C_MODWITH], TRUE);
637 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
640 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
646 * Slide the newname into the #2 slot, this screws up all future references
650 SlipInNewName(info, newname);
655 /* ----------- Machine Menu ----------- */
657 /* Function Name: ShowMachineInfo
658 * Description: This function shows the information about a machine.
659 * Arguments: argc, argv - the name of the machine in argv[1].
660 * Returns: DM_NORMAL.
665 ShowMachineInfo(argc, argv)
672 tmpname = canonicalize_hostname(strsave(argv[1]));
673 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
674 Loop(top, ( (void *) PrintMachInfo) );
679 /* Function Name: ShowMachineQuery
680 * Description: This function shows the information about a machine.
681 * or group of machines, which may be selected through a
682 * number of criteria.
683 * Arguments: argc, argv - the name of the machine in argv[1],
684 * the address of the machine in argv[2],
685 * the location of the machine in argv[3],
686 * and the contact name in argv[4].
687 * any of these may be wildcards.
688 * Returns: DM_NORMAL.
693 ShowMachineQuery(argc, argv)
698 struct qelem *top, *elem = NULL;
701 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
702 !strcmp(argv[3], "") && !strcmp(argv[4], "")) {
703 Put_message("You must specify at least one parameter of the query.");
708 args[0] = canonicalize_hostname(strsave(argv[1]));
724 if ((stat = do_mr_query("get_host", 4, args, StoreInfo,
725 (char *)&elem)) != 0) {
726 if (stat == MR_NO_MATCH)
727 Put_message("No machine(s) found matching query in the database.");
729 com_err(program_name, stat, " in get_machine.");
732 top = QueueTop(elem);
733 Loop(top, ( (void *) PrintMachInfo) );
738 /* Function Name: AddMachine
739 * Description: This function adds a new machine to the database.
740 * Arguments: argc, argv - the name of the network in argv[1].
741 * Returns: DM_NORMAL.
746 AddMachine(argc, argv)
750 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
752 struct qelem * elem = NULL;
755 if (!ValidName(argv[1])) /* Checks for wildcards. */
759 * get the network record
762 if (strcasecmp(argv[1], "none") &&
763 (stat = do_mr_query("get_subnet", 1, &argv[1],
764 StoreInfo, (char *)&elem)) != 0) {
765 if (stat == MR_NO_MATCH) {
767 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
770 com_err(program_name, stat, " in get_subnet.");
775 * Check to see if this machine already exists.
778 name = strsave(""); /* want to put prefix here */
779 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
782 name = canonicalize_hostname(strsave(name));
785 xargs[1] = xargs[2] = xargs[3] = "*";
786 if ( (stat = do_mr_query("get_host", 4, xargs, NullFunc, NULL)) == 0) {
787 sprintf(buf, "The machine '%s' already exists.", name);
792 else if (stat != MR_NO_MATCH) {
793 com_err(program_name, stat,
794 " while checking machine '%s' in AddMachine.", name);
798 rinfo = SetMachineDefaults(info, name);
799 rinfo[M_SUBNET] = argv[1];
800 if ((args = AskMCDInfo(rinfo, MACHINE, FALSE)) == NULL) {
801 Put_message("Aborted.");
806 * Actually create the new Machine.
809 if ( (stat = do_mr_query("add_host", CountArgs(args),
810 args, Scream, NULL)) != 0)
811 com_err(program_name, stat, " in AddMachine.");
818 /* Function Name: RealUpdateMachine
819 * Description: Performs the actual update of the machine data.
820 * Arguments: info - the information on the machine to update.
821 * junk - an UNUSED Boolean.
827 RealUpdateMachine(info, junk)
832 char ** args = AskMCDInfo(info, MACHINE, TRUE);
834 Put_message("Aborted.");
837 if ( (stat = do_mr_query("update_host", CountArgs(args),
838 args, Scream, NULL)) != 0)
839 com_err(program_name, stat, " in UpdateMachine.");
841 Put_message("Machine sucessfully updated.");
844 /* Function Name: UpdateMachine
845 * Description: This function adds a new machine to the database.
846 * Arguments: argc, argv - the name of the machine in argv[1].
847 * Returns: DM_NORMAL.
852 UpdateMachine(argc, argv)
859 tmpname = canonicalize_hostname(strsave(argv[1]));
860 top = GetMCInfo( MACHINE, tmpname, (char *) NULL);
861 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
868 /* Function Name: CheckAndRemoveFromCluster
869 * Description: This func tests to see if a machine is in a cluster.
870 * and if so then removes it
871 * Arguments: name - name of the machine (already Canonocalized).
872 * ask_user- query the user before removing if from clusters?
873 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
877 CheckAndRemoveFromCluster(name, ask_user)
881 register int stat, ret_value;
883 char *args[10], temp_buf[BUFSIZ], *ptr;
884 struct qelem *top, *elem = NULL;
886 ret_value = SUB_NORMAL; /* initialize ret_value. */
889 stat = do_mr_query("get_machine_to_cluster_map", 2, args,
890 StoreInfo, (char *)&elem);
891 if (stat && stat != MR_NO_MATCH) {
892 com_err(program_name, stat, " in get_machine_to_cluster_map.");
895 if (stat == MR_SUCCESS) {
896 elem = top = QueueTop(elem);
898 sprintf(temp_buf, "%s is assigned to the following clusters.",
900 Put_message(temp_buf);
901 Loop(top, (void *) PrintMCMap);
902 ptr = "Remove this machine from ** ALL ** these clusters?";
903 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
906 Put_message("Aborting...");
915 while (elem != NULL) {
916 char **info = (char **) elem->q_data;
917 if ( (stat = do_mr_query( "delete_machine_from_cluster",
918 2, info, Scream, NULL)) != 0) {
919 ret_value = SUB_ERROR;
920 com_err(program_name, stat,
921 " in delete_machine_from_cluster.");
923 "Machine %s ** NOT ** removed from cluster %s.",
924 info[MAP_MACHINE], info[MAP_CLUSTER]);
925 Put_message(temp_buf);
934 /* Function Name: RealDeleteMachine
935 * Description: Actually Deletes the Machine.
936 * Arguments: info - nescessary information stored as an array of char *'s
937 * one_machine - a boolean, true if there is only one item in
943 RealDeleteMachine(info, one_machine)
948 char temp_buf[BUFSIZ];
950 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
952 if(!one_machine || Confirm(temp_buf)) {
953 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR) {
954 if ( (stat = do_mr_query("delete_host", 1,
955 &info[M_NAME], Scream, NULL)) != 0) {
956 com_err(program_name, stat, " in DeleteMachine.");
957 sprintf(temp_buf, "%s ** NOT ** deleted.",
959 Put_message(temp_buf);
962 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
963 Put_message(temp_buf);
969 /* Function Name: DeleteMachine
970 * Description: This function removes a machine from the data base.
971 * Arguments: argc, argv - the machines name int argv[1].
972 * Returns: DM_NORMAL.
975 /* Perhaps we should remove the cluster if it has no machine now. */
979 DeleteMachine(argc, argv)
986 tmpname = canonicalize_hostname(strsave(argv[1]));
987 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
988 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
995 char *partial_canonicalize_hostname(s)
999 static char *def_domain = NULL;
1002 struct utsname name;
1007 (void) uname(&name);
1008 strncpy(buf, name.nodename, sizeof(buf));
1010 gethostname(buf, sizeof(buf));
1012 hp = gethostbyname(buf);
1013 cp = (char *) strchr(hp->h_name, '.');
1015 def_domain = strsave(++cp);
1020 if (strchr(s, '.') || strchr(s, '*'))
1022 sprintf(buf, "%s.%s", s, def_domain);
1024 return(strsave(buf));
1028 /* Function Name: ShowCname
1029 * Description: This function shows machine aliases
1030 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1031 * Returns: DM_NORMAL.
1036 ShowCname(argc, argv)
1041 char *tmpalias, *tmpname;
1043 tmpalias = partial_canonicalize_hostname(strsave(argv[1]));
1044 tmpname = canonicalize_hostname(strsave(argv[2]));
1045 top = GetMCInfo(CNAME, tmpalias, tmpname);
1046 Put_message(""); /* blank line on screen */
1047 Loop(top, ( (void *) PrintCname) );
1055 AddCname(argc, argv)
1060 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1061 Bool add_it, one_machine, one_cluster;
1062 struct qelem * melem, *mtop, *celem, *ctop;
1064 args[0] = partial_canonicalize_hostname(strsave(argv[1]));
1065 args[1] = canonicalize_hostname(strsave(argv[2]));
1066 stat = do_mr_query("add_hostalias", 2, args, Scream, NULL);
1071 Put_message("That alias name is already in use.");
1074 Put_message("Permission denied. (Regular users can only add two aliases to a host.");
1077 com_err(program_name, stat, " in add_hostalias");
1085 DeleteCname(argc, argv)
1090 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1091 Bool add_it, one_machine, one_cluster;
1092 struct qelem * melem, *mtop, *celem, *ctop;
1094 args[0] = partial_canonicalize_hostname(strsave(argv[1]));
1095 args[1] = canonicalize_hostname(strsave(argv[2]));
1096 stat = do_mr_query("delete_hostalias", 2, args, Scream, NULL);
1098 com_err(program_name, stat, " in delete_hostalias");
1103 /* Function Name: AddMachineToCluster
1104 * Description: This function adds a machine to a cluster
1105 * Arguments: argc, argv - The machine name is argv[1].
1106 * The cluster name in argv[2].
1107 * Returns: DM_NORMAL.
1112 AddMachineToCluster(argc, argv)
1117 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1118 Bool add_it, one_machine, one_cluster;
1119 struct qelem * melem, *mtop, *celem, *ctop;
1121 machine = canonicalize_hostname(strsave(argv[1]));
1122 if (strcasecmp(machine, argv[1]) && *argv[1] != '"') {
1123 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1125 Put_message(temp_buf);
1129 celem = ctop = GetMCInfo(CLUSTER, cluster, (char *) NULL);
1130 melem = mtop = GetMCInfo(MACHINE, machine, (char *) NULL);
1133 one_machine = (QueueCount(mtop) == 1);
1134 one_cluster = (QueueCount(ctop) == 1);
1136 /* No good way to use QueryLoop() here, sigh */
1138 while (melem != NULL) {
1139 char ** minfo = (char **) melem->q_data;
1140 while (celem != NULL) {
1141 char ** cinfo = (char **) celem->q_data;
1142 if (one_machine && one_cluster)
1145 sprintf(temp_buf,"Add machine %s to cluster %s (y/n/q) ?",
1146 minfo[M_NAME], cinfo[C_NAME]);
1147 switch (YesNoQuitQuestion(temp_buf, FALSE)) {
1155 Put_message("Aborting...");
1162 args[0] = minfo[M_NAME];
1163 args[1] = cinfo[C_NAME];
1164 stat = do_mr_query("add_machine_to_cluster", 2, args,
1170 sprintf(temp_buf, "%s is already in cluster %s",
1171 minfo[M_NAME], cinfo[C_NAME]);
1172 Put_message(temp_buf);
1175 com_err(program_name, stat, " in AddMachineToCluster.");
1179 celem = celem->q_forw;
1181 celem = ctop; /* reset cluster element. */
1182 melem = melem->q_forw;
1189 /* Function Name: RealRemoveMachineFromCluster
1190 * Description: This function actually removes the machine from its
1192 * Arguments: info - all information nescessary to perform the removal.
1193 * one_map - True if there is only one case, and we should
1199 RealRemoveMachineFromCluster(info, one_map)
1203 char temp_buf[BUFSIZ];
1206 sprintf(temp_buf, "Remove %s from the cluster %s",
1207 info[MAP_MACHINE], info[MAP_CLUSTER]);
1208 if (!one_map || Confirm(temp_buf)) {
1209 if ( (stat = do_mr_query("delete_machine_from_cluster", 2,
1210 info, Scream, NULL)) != 0 )
1211 com_err(program_name, stat, " in delete_machine_from_cluster");
1213 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1214 info[MAP_MACHINE], info[MAP_CLUSTER]);
1215 Put_message(temp_buf);
1219 Put_message("Machine not removed.");
1222 /* Function Name: RemoveMachineFromCluster
1223 * Description: Removes this machine form a specific cluster.
1224 * Arguments: argc, argv - Name of machine in argv[1].
1225 * Name of cluster in argv[2].
1231 RemoveMachineFromCluster(argc, argv)
1235 struct qelem *elem = NULL;
1236 char buf[BUFSIZ], * args[10];
1239 args[MAP_MACHINE] = canonicalize_hostname(strsave(argv[1]));
1240 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"') {
1241 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1242 argv[1], args[MAP_MACHINE]);
1245 args[MAP_CLUSTER] = argv[2];
1246 args[MAP_END] = NULL;
1248 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1249 StoreInfo, (char *)&elem);
1250 if (stat == MR_NO_MATCH) {
1251 sprintf(buf, "The machine %s is not is the cluster %s.",
1252 args[MAP_MACHINE], args[MAP_CLUSTER]);
1254 free(args[MAP_MACHINE]);
1257 if (stat != MR_SUCCESS)
1258 com_err(program_name, stat, " in delete_machine_from_cluster");
1260 elem = QueueTop(elem);
1261 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1262 "Remove this machine from this cluster");
1265 free(args[MAP_MACHINE]);
1269 /* ---------- Subnet Menu -------- */
1271 /* Function Name: ShowSubnetInfo
1272 * Description: Gets information about a subnet given its name.
1273 * Arguments: argc, argc - the name of the subnet in in argv[1].
1274 * Returns: DM_NORMAL.
1279 ShowSubnetInfo(argc, argv)
1285 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1286 Loop(top, (void *) PrintSubnetInfo);
1291 /* Function Name: AddSubnet
1292 * Description: Creates a new subnet.
1293 * Arguments: argc, argv - the name of the new subnet is argv[1].
1294 * Returns: DM_NORMAL.
1299 AddSubnet(argc, argv)
1303 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1306 * Check to see if this subnet already exists.
1308 if (!ValidName(name))
1311 if ( (stat = do_mr_query("get_subnet", 1, &name,
1312 NullFunc, NULL)) == MR_SUCCESS) {
1313 Put_message("This subnet already exists.");
1316 else if (stat != MR_NO_MATCH) {
1317 com_err(program_name, stat, " in AddSubnet.");
1320 if ((args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)) ==
1322 Put_message("Aborted.");
1328 * Actually create the new Subnet.
1330 if ( (stat = do_mr_query("add_subnet", CountArgs(args),
1331 args, Scream, NULL)) != 0)
1332 com_err(program_name, stat, " in AddSubnet.");
1338 /* Function Name: RealUpdateSubnet
1339 * Description: This function actually performs the subnet update.
1340 * Arguments: info - all information nesc. for updating the subnet.
1341 * junk - an UNUSED boolean.
1347 RealUpdateSubnet(info, junk)
1352 char ** args = AskMCDInfo(info, SUBNET, TRUE);
1354 Put_message("Aborted.");
1357 if ( (stat = do_mr_query("update_subnet", CountArgs(args),
1358 args, Scream, NULL)) != 0)
1359 com_err(program_name, stat, " in UpdateSubnet.");
1361 Put_message("Subnet successfully updated.");
1364 /* Function Name: UpdateSubnet
1365 * Description: This Function Updates a subnet
1366 * Arguments: name of the subnet in argv[1].
1367 * Returns: DM_NORMAL.
1372 UpdateSubnet(argc, argv)
1377 top = GetMCInfo( SUBNET, argv[1], (char *) NULL );
1378 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1384 /* Function Name: RealDeleteSubnet
1385 * Description: Actually performs the subnet deletion.
1386 * Arguments: info - all information about this subnet.
1387 * one_subnet - If true then there was only one subnet in
1388 * the queue, and we should confirm.
1393 RealDeleteSubnet(info, one_subnet)
1398 char temp_buf[BUFSIZ];
1401 "Are you sure the you want to delete the subnet %s (y/n) ?",
1403 if (!one_subnet || Confirm(temp_buf)) {
1404 if ( (stat = do_mr_query("delete_subnet", 1,
1405 &info[C_NAME], Scream, NULL)) != 0) {
1406 com_err(program_name, stat, " in delete_subnet.");
1407 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.",
1409 Put_message(temp_buf);
1412 sprintf(temp_buf, "subnet %s sucesfully deleted.",
1414 Put_message(temp_buf);
1419 /* Function Name: DeleteSubnet
1420 * Description: This function removes a subnet from the database.
1421 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1422 * Returns: DM_NORMAL.
1427 DeleteSubnet(argc, argv)
1433 top = GetMCInfo( SUBNET, argv[1], (char *) NULL );
1434 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1440 /* ---------- Cluster Menu -------- */
1442 /* Function Name: ShowClusterInfo
1443 * Description: Gets information about a cluser given its name.
1444 * Arguments: argc, argc - the name of the cluster in in argv[1].
1445 * Returns: DM_NORMAL.
1450 ShowClusterInfo(argc, argv)
1456 top = GetMCInfo(CLUSTER, argv[1], (char *) NULL);
1457 Loop(top, (void *) PrintClusterInfo);
1462 /* Function Name: AddCluster
1463 * Description: Creates a new cluster.
1464 * Arguments: argc, argv - the name of the new cluster is argv[1].
1465 * Returns: DM_NORMAL.
1470 AddCluster(argc, argv)
1474 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1477 * Check to see if this cluster already exists.
1479 if (!ValidName(name))
1482 if ( (stat = do_mr_query("get_cluster", 1, &name,
1483 NullFunc, NULL)) == MR_SUCCESS) {
1484 Put_message("This cluster already exists.");
1487 else if (stat != MR_NO_MATCH) {
1488 com_err(program_name, stat, " in AddCluster.");
1491 if ((args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)) ==
1493 Put_message("Aborted.");
1499 * Actually create the new Cluster.
1501 if ( (stat = do_mr_query("add_cluster", CountArgs(args),
1502 args, Scream, NULL)) != 0)
1503 com_err(program_name, stat, " in AddCluster.");
1509 /* Function Name: RealUpdateCluster
1510 * Description: This function actually performs the cluster update.
1511 * Arguments: info - all information nesc. for updating the cluster.
1512 * junk - an UNUSED boolean.
1518 RealUpdateCluster(info, junk)
1523 char ** args = AskMCDInfo(info, CLUSTER, TRUE);
1525 Put_message("Aborted.");
1528 if ( (stat = do_mr_query("update_cluster", CountArgs(args),
1529 args, Scream, NULL)) != 0)
1530 com_err(program_name, stat, " in UpdateCluster.");
1532 Put_message("Cluster successfully updated.");
1535 /* Function Name: UpdateCluster
1536 * Description: This Function Updates a cluster
1537 * Arguments: name of the cluster in argv[1].
1538 * Returns: DM_NORMAL.
1543 UpdateCluster(argc, argv)
1548 top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
1549 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1555 /* Function Name: CheckAndRemoveMachine
1556 * Description: This function checks and removes all machines from a
1558 * Arguments: name - name of the cluster.
1559 * ask_first - if TRUE, then we will query the user, before
1561 * Returns: SUB_ERROR if all machines not removed.
1565 CheckAndRemoveMachines(name, ask_first)
1569 register int stat, ret_value;
1571 char *args[10], temp_buf[BUFSIZ], *ptr;
1572 struct qelem *top, *elem = NULL;
1574 ret_value = SUB_NORMAL;
1575 args[MAP_MACHINE] = "*";
1576 args[MAP_CLUSTER] = name;
1577 stat = do_mr_query("get_machine_to_cluster_map", 2, args,
1578 StoreInfo, (char *)&elem);
1579 if (stat && stat != MR_NO_MATCH) {
1580 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1584 elem = top = QueueTop(elem);
1587 "The cluster %s has the following machines in it:",
1589 Put_message(temp_buf);
1590 while (elem != NULL) {
1591 char **info = (char **) elem->q_data;
1592 Print(1, &info[MAP_MACHINE], (char *) NULL);
1593 elem = elem->q_forw;
1595 ptr = "Remove ** ALL ** these machines from this cluster?";
1597 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1600 Put_message("Aborting...");
1611 char **info = (char **) elem->q_data;
1612 if ( (stat = do_mr_query("delete_machine_from_cluster",
1613 2, info, Scream, NULL)) != 0) {
1614 ret_value = SUB_ERROR;
1615 com_err(program_name, stat,
1616 " in delete_machine_from_cluster.");
1618 "Machine %s ** NOT ** removed from cluster %s.",
1619 info[MAP_MACHINE], info[MAP_CLUSTER]);
1620 Put_message(temp_buf);
1622 elem = elem->q_forw;
1629 /* Function Name: RealDeleteCluster
1630 * Description: Actually performs the cluster deletion.
1631 * Arguments: info - all information about this cluster.
1632 * one_cluster - If true then there was only one cluster in
1633 * the queue, and we should confirm.
1638 RealDeleteCluster(info, one_cluster)
1643 char temp_buf[BUFSIZ];
1646 "Are you sure the you want to delete the cluster %s (y/n) ?",
1648 if (!one_cluster || Confirm(temp_buf)) {
1649 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR) {
1650 if ( (stat = do_mr_query("delete_cluster", 1,
1651 &info[C_NAME], Scream, NULL)) != 0) {
1652 com_err(program_name, stat, " in delete_cluster.");
1653 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.",
1655 Put_message(temp_buf);
1658 sprintf(temp_buf, "cluster %s sucesfully deleted.",
1660 Put_message(temp_buf);
1666 /* Function Name: DeleteCluster
1667 * Description: This function removes a cluster from the database.
1668 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1669 * Returns: DM_NORMAL.
1674 DeleteCluster(argc, argv)
1680 top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
1681 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1687 /* ----------- Cluster Data Menu -------------- */
1689 /* Function Name: ShowClusterData
1690 * Description: This function shows the services for one cluster.
1691 * Arguments: argc, argv - The name of the cluster is argv[1].
1692 * The label of the data in argv[2].
1693 * Returns: DM_NORMAL.
1698 ShowClusterData(argc, argv)
1702 struct qelem *elem, *top;
1705 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1706 while (elem != NULL) {
1707 info = (char **) elem->q_data;
1708 PrintClusterData(info);
1709 elem = elem->q_forw;
1715 /* Function Name: AddClusterData
1716 * Description: This function adds some data to the cluster.
1717 * Arguments: argv, argc: argv[1] - the name of the cluster.
1718 * argv[2] - the label of the data.
1719 * argv[3] - the data.
1720 * Returns: DM_NORMAL.
1725 AddClusterData(argc, argv)
1731 if( (stat = do_mr_query("add_cluster_data", 3, argv + 1,
1732 Scream, (char *) NULL)) != 0)
1733 com_err(program_name, stat, " in AddClusterData.");
1737 /* Function Name: RealRemoveClusterData
1738 * Description: actually removes the cluster data.
1739 * Arguments: info - all info necessary to remove the cluster, in an array
1741 * one_item - if true then the queue has only one elem and we
1747 RealRemoveClusterData(info, one_item)
1755 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1756 PrintClusterData(info);
1757 if (!one_item || Confirm(temp_ptr)) {
1758 if( (stat = do_mr_query("delete_cluster_data", 3, info,
1759 Scream, (char *) NULL)) != 0) {
1760 com_err(program_name, stat, " in DeleteClusterData.");
1761 Put_message("Data not removed.");
1764 Put_message("Removal sucessful.");
1768 /* Function Name: RemoveClusterData
1769 * Description: This function removes data on a given cluster.
1770 * Arguments: argv, argc: argv[1] - the name of the cluster.
1771 * argv[2] - the label of the data.
1772 * argv[3] - the data.
1773 * Returns: DM_NORMAL.
1778 RemoveClusterData(argc, argv)
1784 top = GetMCInfo(DATA, argv[1], argv[2]);
1785 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1786 "Remove data from cluster");
1792 /* Function Name: MachineToClusterMap
1793 * Description: This Retrieves the mapping between machine and cluster
1794 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1795 * argv[2] -> cluster name or wildcard.
1801 MachineToClusterMap(argc,argv)
1805 struct qelem *elem, *top;
1806 char *tmpname, temp_buf[256];
1808 tmpname = canonicalize_hostname(strsave(argv[1]));
1809 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"') {
1810 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1812 Put_message(temp_buf);
1814 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1816 Put_message(""); /* blank line on screen */
1817 while (elem != NULL) {
1818 char ** info = (char **) elem->q_data;
1820 elem = elem->q_forw;