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 "mit-copyright.h"
46 #define M_DEFAULT_TYPE DEFAULT_NONE
48 #define C_DEFAULT_DESCRIPT DEFAULT_NONE
49 #define C_DEFAULT_LOCATION DEFAULT_NONE
51 #define CD_DEFAULT_LABEL DEFAULT_NONE
52 #define CD_DEFAULT_DATA DEFAULT_NONE
55 static char *states[] = { "Reserved (0)",
60 static char *MacState(state)
65 if (state < 0 || state > 3) {
66 sprintf(buf, "Unknown (%d)", state);
69 return(states[state]);
74 /* -------------------- Set Defaults -------------------- */
76 /* Function Name: SetMachineDefaults
77 * Description: sets machine defaults.
78 * Arguments: info - an array to put the defaults into.
79 * name - Canonacalized name of the machine.
80 * Returns: info - the array.
84 SetMachineDefaults(info, name)
87 info[M_NAME] = Strsave(name);
88 info[M_VENDOR] = Strsave(M_DEFAULT_TYPE);
89 info[M_MODEL] = Strsave(M_DEFAULT_TYPE);
90 info[M_OS] = Strsave(M_DEFAULT_TYPE);
91 info[M_LOC] = Strsave(M_DEFAULT_TYPE);
92 info[M_CONTACT] = Strsave(M_DEFAULT_TYPE);
93 info[M_USE] = Strsave("0");
94 info[M_STAT] = Strsave("1");
95 info[8] = Strsave("NONE");
96 info[9] = Strsave("unique");
97 info[10] = Strsave("NONE");
98 info[11] = Strsave("NONE");
99 info[12] = Strsave("");
100 info[13] = Strsave("");
101 info[14] = info[15] = info[16] = NULL;
105 /* Function Name: SetClusterDefaults
106 * Description: sets Cluster defaults.
107 * Arguments: info - an array to put the defaults into.
108 * name - name of the Cluster.
109 * Returns: info - the array.
113 SetClusterDefaults(info, name)
116 info[C_NAME] = Strsave(name);
117 info[C_DESCRIPT] = Strsave(C_DEFAULT_DESCRIPT);
118 info[C_LOCATION] = Strsave(C_DEFAULT_LOCATION);
119 info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
123 /* Function Name: SetSubnetDefaults
124 * Description: sets Subnet defaults.
125 * Arguments: info - an array to put the defaults into.
126 * name - name of the Subnet.
127 * Returns: info - the array.
131 SetSubnetDefaults(info, name)
136 info[C_NAME] = Strsave(name);
137 info[SN_DESC] = Strsave("");
138 sprintf(buf, "%d", ntohl(inet_addr("18.0.0.0")));
139 info[SN_ADDRESS] = Strsave(buf);
140 sprintf(buf, "%d", ntohl(inet_addr("255.255.0.0")));
141 info[SN_MASK] = Strsave(buf);
142 sprintf(buf, "%d", ntohl(inet_addr("18.0.0.10")));
143 info[SN_LOW] = Strsave(buf);
144 sprintf(buf, "%d", ntohl(inet_addr("18.0.1.252")));
145 info[SN_HIGH] = Strsave(buf);
146 info[SN_ACE_TYPE] = Strsave("LIST");
147 info[SN_ACE_NAME] = Strsave("network_acl");
148 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
152 /* -------------------- General Functions -------------------- */
154 /* Function Name: PrintMachInfo
155 * Description: This function Prints out the Machine info in
157 * Arguments: info - array of information about a machine.
158 * Returns: The name of the Machine
168 sprintf(buf, "Machine: %s Vendor: %s, Model: %s, OS: %s",
169 info[M_NAME], info[M_VENDOR], info[M_MODEL], info[M_OS]);
171 sprintf(buf, "Location: %s, Contact: %s, Owner: %s %s",
172 info[M_LOC], info[M_CONTACT], info[M_OWNER_TYPE],
173 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
175 sprintf(buf, "Address: %s, Subnet: %s, Use code: %s",
176 info[M_ADDR], info[M_SUBNET], info[M_USE]);
178 sprintf(buf, "Status: %s, Status Changed %s",
179 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
181 sprintf(buf, "Created on %s by %s", info[M_CREATED], info[M_CREATOR]);
183 sprintf(buf, "Last known use %s", info[M_INUSE]);
185 sprintf(buf, "Admin cmt: %s; Op cmt: %s",
186 info[M_ACOMMENT], info[M_OCOMMENT]);
188 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
190 return(info[M_NAME]);
193 /* Function Name: PrintCname
194 * Description: Prints the Data on a host alias
195 * Arguments: info a pointer to the data array.
196 * Returns: The name of the alias.
205 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
210 /* Function Name: PrintClusterInfo
211 * Description: This function Prints out the cluster info
212 * in a coherent form.
213 * Arguments: info - array of information about a cluster.
214 * Returns: The name of the cluster.
218 PrintClusterInfo(info)
224 sprintf(buf, "Cluster: %s", info[C_NAME]);
226 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
228 sprintf(buf, "Location: %s", info[C_LOCATION]);
230 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
232 return(info[C_NAME]);
235 /* Function Name: PrintClusterData
236 * Description: Prints the Data on a cluster
237 * Arguments: info a pointer to the data array.
238 * Returns: The name of the cluster.
242 PrintClusterData(info)
248 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
249 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
251 return(info[CD_NAME]);
254 /* Function Name: PrintMCMap
255 * Description: Prints the data about a machine to cluster mapping.
256 * Arguments: info a pointer to the data array.
265 sprintf(buf, "Cluster: %-30s Machine: %-20s",
266 info[MAP_CLUSTER], info[MAP_MACHINE]);
268 return(""); /* Used by QueryLoop(). */
271 /* Function Name: PrintSubnetInfo
272 * Description: This function Prints out the subnet info
273 * in a coherent form.
274 * Arguments: info - array of information about a subnet.
275 * Returns: The name of the subnet.
279 PrintSubnetInfo(info)
283 struct in_addr addr, mask, low, high;
286 sprintf(buf, "Subnet: %s", info[SN_NAME]);
288 sprintf(buf, "Description: %s", info[SN_DESC]);
290 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
291 mask.s_addr = htonl(atoi(info[SN_MASK]));
292 low.s_addr = htonl(atoi(info[SN_LOW]));
293 high.s_addr = htonl(atoi(info[SN_HIGH]));
294 /* screwy sequence is here because inet_ntoa returns a pointer to
295 a static buf. If it were all one sprintf, the last value would
297 sprintf(buf, "Address %s, Mask ", inet_ntoa(addr));
298 strcat(buf, inet_ntoa(mask));
299 strcat(buf, ", High ");
300 strcat(buf, inet_ntoa(high));
301 strcat(buf, ", Low ");
302 strcat(buf, inet_ntoa(low));
304 sprintf(buf, "Owner: %s %s", info[SN_ACE_TYPE],
305 strcmp(info[SN_ACE_TYPE],"NONE") ? info[SN_ACE_NAME] : "");
307 sprintf(buf,MOD_FORMAT,info[SN_MODBY],info[SN_MODTIME],info[SN_MODWITH]);
309 return(info[SN_NAME]);
312 /* Function Name: GetMCInfo.
313 * Description: This function stores info about a machine.
314 * type - type of data we are trying to retrieve.
315 * name1 - the name of argv[0] for the call.
316 * name2 - the name of argv[1] for the call.
317 * Returns: the top element of a queue containing the data or NULL.
321 GetMCInfo(type, name1, name2)
323 char * name1, *name2;
327 struct qelem * elem = NULL;
333 args[1] = args[2] = args[3] = "*";
334 if ( (stat = do_mr_query("get_host", 4, args,
335 StoreInfo, (char *)&elem)) != 0) {
336 if (stat == MR_NO_MATCH) {
338 sprintf(buf, "Machine '%s' is not in the database.", name1);
341 com_err(program_name, stat, " in get_machine.");
348 if ( (stat = do_mr_query("get_hostalias", 2, args,
349 StoreInfo, (char *)&elem)) != 0) {
350 com_err(program_name, stat, " in get_hostalias.");
355 if ( (stat = do_mr_query("get_subnet", 1, &name1,
356 StoreInfo, (char *)&elem)) != 0) {
357 if (stat == MR_NO_MATCH) {
359 sprintf(buf, "Subnet '%s' is not in the database.", name1);
362 com_err(program_name, stat, " in get_subnet.");
367 if ( (stat = do_mr_query("get_cluster", 1, &name1,
368 StoreInfo, (char *)&elem)) != 0) {
369 com_err(program_name, stat, " in get_cluster.");
374 args[MAP_MACHINE] = name1;
375 args[MAP_CLUSTER] = name2;
376 if ( (stat = do_mr_query("get_machine_to_cluster_map", 2, args,
377 StoreInfo, (char *)&elem)) != 0) {
378 com_err(program_name, stat, " in get_machine_to_cluster_map.");
383 args[CD_NAME] = name1;
384 args[CD_LABEL] = name2;
385 if ( (stat = do_mr_query("get_cluster_data", 2, args,
386 StoreInfo, (char *)&elem)) != 0) {
387 com_err(program_name, stat, " in get_cluster_data.");
391 return(QueueTop(elem));
394 /* Function Name: AskMCDInfo.
395 * Description: This function askes the user for information about a
396 * machine and saves it into a structure.
397 * Arguments: info - a pointer the information to ask about
398 * type - type of information - MACHINE
401 * name - T/F : change the name of this type.
406 AskMCDInfo(info, type, name)
411 char temp_buf[BUFSIZ], *newname, *oldnewname;
415 sprintf(temp_buf, "Setting the information for the Machine %s.",
419 sprintf(temp_buf, "Setting the information for the Subnet %s.",
423 sprintf(temp_buf, "Setting the information for the Cluster %s.",
427 sprintf(temp_buf, "Setting the Data for the Cluster %s.",
431 Put_message(temp_buf);
436 newname = Strsave(info[M_NAME]);
437 if (GetValueFromUser("The new name for this machine? ", &newname) ==
440 oldnewname = Strsave(newname);
441 newname = canonicalize_hostname(newname);
442 if (strcasecmp(newname, oldnewname) && *oldnewname != '"') {
443 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
444 oldnewname, newname);
445 Put_message(temp_buf);
450 newname = Strsave(info[SN_NAME]);
451 if (GetValueFromUser("The new name for this subnet? ",
452 &newname) == SUB_ERROR)
456 newname = Strsave(info[C_NAME]);
457 if (GetValueFromUser("The new name for this cluster? ",
458 &newname) == SUB_ERROR)
462 Put_message("Unknown type in AskMCDInfo, programmer botch");
469 if (GetValueFromUser("Machine's Vendor", &info[M_VENDOR]) == SUB_ERROR)
471 if (GetValueFromUser("Machine's Model", &info[M_MODEL]) == SUB_ERROR)
473 if (GetValueFromUser("Machine's Operating System", &info[M_OS]) ==
476 if (GetValueFromUser("Location of Machine", &info[M_LOC]) == SUB_ERROR)
478 if (GetValueFromUser("Contact for Machine", &info[M_CONTACT]) ==
481 if (GetValueFromUser("Machine's Use Code", &info[M_USE]) == SUB_ERROR)
485 if (GetValueFromUser("Machine's Status (? for help)",
486 &info[M_STAT]) == SUB_ERROR)
488 if (isdigit(info[M_STAT][0])) break;
489 Put_message("Valid status numbers:");
490 for (i = 0; i < 4; i++) Put_message(states[i]);
494 info[8] = info[M_SUBNET];
495 info[9] = info[M_ADDR];
496 info[10] = info[M_OWNER_TYPE];
497 info[11] = info[M_OWNER_NAME];
498 info[12] = info[M_ACOMMENT];
499 info[13] = info[M_OCOMMENT];
501 if (GetValueFromUser("Machine's subnet (or 'none')", &info[8])
504 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
505 &info[9]) == SUB_ERROR)
507 if (GetTypeFromUser("Machine's Owner Type", "ace_type", &info[10]) ==
510 if (strcmp(info[10], "NONE") &&
511 GetValueFromUser("Owner's Name", &info[11]) == SUB_ERROR)
513 if (GetValueFromUser("Administrative Comment", &info[12]) == SUB_ERROR)
515 if (GetValueFromUser("Operational Comment", &info[13]) == SUB_ERROR)
518 FreeAndClear(&info[15], TRUE);
519 FreeAndClear(&info[16], TRUE);
522 if (GetValueFromUser("Subnet Description", &info[SN_DESC]) == SUB_ERROR)
524 if (GetAddressFromUser("Subnet Address", &info[SN_ADDRESS]) == SUB_ERROR)
526 if (GetAddressFromUser("Subnet Mask", &info[SN_MASK]) == SUB_ERROR)
528 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) == SUB_ERROR)
530 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) == SUB_ERROR)
532 if (GetTypeFromUser("Owner Type", "ace_type", &info[SN_ACE_TYPE]) == SUB_ERROR)
534 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
535 GetValueFromUser("Owner Name", &info[SN_ACE_NAME]) == SUB_ERROR)
537 FreeAndClear(&info[SN_MODTIME], TRUE);
538 FreeAndClear(&info[SN_MODBY], TRUE);
539 FreeAndClear(&info[SN_MODWITH], TRUE);
542 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
545 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
548 FreeAndClear(&info[C_MODTIME], TRUE);
549 FreeAndClear(&info[C_MODBY], TRUE);
550 FreeAndClear(&info[C_MODWITH], TRUE);
553 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
556 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
562 * Slide the newname into the #2 slot, this screws up all future references
566 SlipInNewName(info, newname);
571 /* ----------- Machine Menu ----------- */
573 /* Function Name: ShowMachineInfo
574 * Description: This function shows the information about a machine.
575 * Arguments: argc, argv - the name of the machine in argv[1].
576 * Returns: DM_NORMAL.
581 ShowMachineInfo(argc, argv)
588 tmpname = canonicalize_hostname(strsave(argv[1]));
589 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
590 Loop(top, ( (void *) PrintMachInfo) );
595 /* Function Name: ShowMachineQuery
596 * Description: This function shows the information about a machine.
597 * or group of machines, which may be selected through a
598 * number of criteria.
599 * Arguments: argc, argv - the name of the machine in argv[1],
600 * the address of the machine in argv[2],
601 * the location of the machine in argv[3],
602 * and the contact name in argv[4].
603 * any of these may be wildcards.
604 * Returns: DM_NORMAL.
609 ShowMachineQuery(argc, argv)
614 struct qelem *top, *elem = NULL;
617 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
618 !strcmp(argv[3], "") && !strcmp(argv[4], "")) {
619 Put_message("You must specify at least one parameter of the query.");
624 args[0] = canonicalize_hostname(strsave(argv[1]));
640 if ((stat = do_mr_query("get_host", 4, args, StoreInfo,
641 (char *)&elem)) != 0) {
642 if (stat == MR_NO_MATCH)
643 Put_message("No machine(s) found matching query in the database.");
645 com_err(program_name, stat, " in get_machine.");
648 top = QueueTop(elem);
649 Loop(top, ( (void *) PrintMachInfo) );
654 /* Function Name: AddMachine
655 * Description: This function adds a new machine to the database.
656 * Arguments: argc, argv - the name of the machine in argv[1].
657 * Returns: DM_NORMAL.
662 AddMachine(argc, argv)
666 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
669 if (!ValidName(argv[1])) /* Checks for wildcards. */
672 * Check to see if this machine already exists.
674 name = canonicalize_hostname(strsave(argv[1]));
677 xargs[1] = xargs[2] = xargs[3] = "*";
678 if ( (stat = do_mr_query("get_host", 4, xargs, NullFunc, NULL)) == 0) {
679 sprintf(buf, "The machine '%s' already exists.", name);
684 else if (stat != MR_NO_MATCH) {
685 com_err(program_name, stat,
686 " while checking machine '%s' in AddMachine.", name);
691 if ((args = AskMCDInfo(SetMachineDefaults(info, name), MACHINE, FALSE)) ==
693 Put_message("Aborted.");
698 * Actually create the new Machine.
701 if ( (stat = do_mr_query("add_host", CountArgs(args),
702 args, Scream, NULL)) != 0)
703 com_err(program_name, stat, " in AddMachine.");
710 /* Function Name: RealUpdateMachine
711 * Description: Performs the actual update of the machine data.
712 * Arguments: info - the information on the machine to update.
713 * junk - an UNUSED Boolean.
719 RealUpdateMachine(info, junk)
724 char ** args = AskMCDInfo(info, MACHINE, TRUE);
726 Put_message("Aborted.");
729 if ( (stat = do_mr_query("update_host", CountArgs(args),
730 args, Scream, NULL)) != 0)
731 com_err(program_name, stat, " in UpdateMachine.");
733 Put_message("Machine sucessfully updated.");
736 /* Function Name: UpdateMachine
737 * Description: This function adds a new machine to the database.
738 * Arguments: argc, argv - the name of the machine in argv[1].
739 * Returns: DM_NORMAL.
744 UpdateMachine(argc, argv)
751 tmpname = canonicalize_hostname(strsave(argv[1]));
752 top = GetMCInfo( MACHINE, tmpname, (char *) NULL);
753 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
760 /* Function Name: CheckAndRemoveFromCluster
761 * Description: This func tests to see if a machine is in a cluster.
762 * and if so then removes it
763 * Arguments: name - name of the machine (already Canonocalized).
764 * ask_user- query the user before removing if from clusters?
765 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
769 CheckAndRemoveFromCluster(name, ask_user)
773 register int stat, ret_value;
775 char *args[10], temp_buf[BUFSIZ], *ptr;
776 struct qelem *top, *elem = NULL;
778 ret_value = SUB_NORMAL; /* initialize ret_value. */
781 stat = do_mr_query("get_machine_to_cluster_map", 2, args,
782 StoreInfo, (char *)&elem);
783 if (stat && stat != MR_NO_MATCH) {
784 com_err(program_name, stat, " in get_machine_to_cluster_map.");
787 if (stat == MR_SUCCESS) {
788 elem = top = QueueTop(elem);
790 sprintf(temp_buf, "%s is assigned to the following clusters.",
792 Put_message(temp_buf);
793 Loop(top, (void *) PrintMCMap);
794 ptr = "Remove this machine from ** ALL ** these clusters?";
795 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
798 Put_message("Aborting...");
807 while (elem != NULL) {
808 char **info = (char **) elem->q_data;
809 if ( (stat = do_mr_query( "delete_machine_from_cluster",
810 2, info, Scream, NULL)) != 0) {
811 ret_value = SUB_ERROR;
812 com_err(program_name, stat,
813 " in delete_machine_from_cluster.");
815 "Machine %s ** NOT ** removed from cluster %s.",
816 info[MAP_MACHINE], info[MAP_CLUSTER]);
817 Put_message(temp_buf);
826 /* Function Name: RealDeleteMachine
827 * Description: Actually Deletes the Machine.
828 * Arguments: info - nescessary information stored as an array of char *'s
829 * one_machine - a boolean, true if there is only one item in
835 RealDeleteMachine(info, one_machine)
840 char temp_buf[BUFSIZ];
842 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
844 if(!one_machine || Confirm(temp_buf)) {
845 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR) {
846 if ( (stat = do_mr_query("delete_host", 1,
847 &info[M_NAME], Scream, NULL)) != 0) {
848 com_err(program_name, stat, " in DeleteMachine.");
849 sprintf(temp_buf, "%s ** NOT ** deleted.",
851 Put_message(temp_buf);
854 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
855 Put_message(temp_buf);
861 /* Function Name: DeleteMachine
862 * Description: This function removes a machine from the data base.
863 * Arguments: argc, argv - the machines name int argv[1].
864 * Returns: DM_NORMAL.
867 /* Perhaps we should remove the cluster if it has no machine now. */
871 DeleteMachine(argc, argv)
878 tmpname = canonicalize_hostname(strsave(argv[1]));
879 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
880 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
886 /* Function Name: ShowCname
887 * Description: This function shows machine aliases
888 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
889 * Returns: DM_NORMAL.
894 ShowCname(argc, argv)
899 char *tmpalias, *tmpname;
901 tmpalias = canonicalize_hostname(strsave(argv[1]));
902 tmpname = canonicalize_hostname(strsave(argv[2]));
903 top = GetMCInfo(CNAME, tmpalias, tmpname);
904 Put_message(""); /* blank line on screen */
905 Loop(top, ( (void *) PrintCname) );
918 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
919 Bool add_it, one_machine, one_cluster;
920 struct qelem * melem, *mtop, *celem, *ctop;
922 args[0] = canonicalize_hostname(strsave(argv[1]));
923 args[1] = canonicalize_hostname(strsave(argv[2]));
924 stat = do_mr_query("add_hostalias", 2, args, Scream, NULL);
929 Put_message("That alias name is already in use.");
932 Put_message("Permission denied. (Regular users can only add two aliases to a host.");
935 com_err(program_name, stat, " in add_hostalias");
943 DeleteCname(argc, argv)
948 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
949 Bool add_it, one_machine, one_cluster;
950 struct qelem * melem, *mtop, *celem, *ctop;
952 args[0] = canonicalize_hostname(strsave(argv[1]));
953 args[1] = canonicalize_hostname(strsave(argv[2]));
954 stat = do_mr_query("delete_hostalias", 2, args, Scream, NULL);
956 com_err(program_name, stat, " in delete_hostalias");
961 /* Function Name: AddMachineToCluster
962 * Description: This function adds a machine to a cluster
963 * Arguments: argc, argv - The machine name is argv[1].
964 * The cluster name in argv[2].
965 * Returns: DM_NORMAL.
970 AddMachineToCluster(argc, argv)
975 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
976 Bool add_it, one_machine, one_cluster;
977 struct qelem * melem, *mtop, *celem, *ctop;
979 machine = canonicalize_hostname(strsave(argv[1]));
980 if (strcasecmp(machine, argv[1]) && *argv[1] != '"') {
981 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
983 Put_message(temp_buf);
987 celem = ctop = GetMCInfo(CLUSTER, cluster, (char *) NULL);
988 melem = mtop = GetMCInfo(MACHINE, machine, (char *) NULL);
991 one_machine = (QueueCount(mtop) == 1);
992 one_cluster = (QueueCount(ctop) == 1);
994 /* No good way to use QueryLoop() here, sigh */
996 while (melem != NULL) {
997 char ** minfo = (char **) melem->q_data;
998 while (celem != NULL) {
999 char ** cinfo = (char **) celem->q_data;
1000 if (one_machine && one_cluster)
1003 sprintf(temp_buf,"Add machine %s to cluster %s (y/n/q) ?",
1004 minfo[M_NAME], cinfo[C_NAME]);
1005 switch (YesNoQuitQuestion(temp_buf, FALSE)) {
1013 Put_message("Aborting...");
1020 args[0] = minfo[M_NAME];
1021 args[1] = cinfo[C_NAME];
1022 stat = do_mr_query("add_machine_to_cluster", 2, args,
1028 sprintf(temp_buf, "%s is already in cluster %s",
1029 minfo[M_NAME], cinfo[C_NAME]);
1030 Put_message(temp_buf);
1033 com_err(program_name, stat, " in AddMachineToCluster.");
1037 celem = celem->q_forw;
1039 celem = ctop; /* reset cluster element. */
1040 melem = melem->q_forw;
1047 /* Function Name: RealRemoveMachineFromCluster
1048 * Description: This function actually removes the machine from its
1050 * Arguments: info - all information nescessary to perform the removal.
1051 * one_map - True if there is only one case, and we should
1057 RealRemoveMachineFromCluster(info, one_map)
1061 char temp_buf[BUFSIZ];
1064 sprintf(temp_buf, "Remove %s from the cluster %s",
1065 info[MAP_MACHINE], info[MAP_CLUSTER]);
1066 if (!one_map || Confirm(temp_buf)) {
1067 if ( (stat = do_mr_query("delete_machine_from_cluster", 2,
1068 info, Scream, NULL)) != 0 )
1069 com_err(program_name, stat, " in delete_machine_from_cluster");
1071 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1072 info[MAP_MACHINE], info[MAP_CLUSTER]);
1073 Put_message(temp_buf);
1077 Put_message("Machine not removed.");
1080 /* Function Name: RemoveMachineFromCluster
1081 * Description: Removes this machine form a specific cluster.
1082 * Arguments: argc, argv - Name of machine in argv[1].
1083 * Name of cluster in argv[2].
1089 RemoveMachineFromCluster(argc, argv)
1093 struct qelem *elem = NULL;
1094 char buf[BUFSIZ], * args[10];
1097 args[MAP_MACHINE] = canonicalize_hostname(strsave(argv[1]));
1098 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"') {
1099 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1100 argv[1], args[MAP_MACHINE]);
1103 args[MAP_CLUSTER] = argv[2];
1104 args[MAP_END] = NULL;
1106 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1107 StoreInfo, (char *)&elem);
1108 if (stat == MR_NO_MATCH) {
1109 sprintf(buf, "The machine %s is not is the cluster %s.",
1110 args[MAP_MACHINE], args[MAP_CLUSTER]);
1112 free(args[MAP_MACHINE]);
1115 if (stat != MR_SUCCESS)
1116 com_err(program_name, stat, " in delete_machine_from_cluster");
1118 elem = QueueTop(elem);
1119 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1120 "Remove this machine from this cluster");
1123 free(args[MAP_MACHINE]);
1127 /* ---------- Subnet Menu -------- */
1129 /* Function Name: ShowSubnetInfo
1130 * Description: Gets information about a subnet given its name.
1131 * Arguments: argc, argc - the name of the subnet in in argv[1].
1132 * Returns: DM_NORMAL.
1137 ShowSubnetInfo(argc, argv)
1143 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1144 Loop(top, (void *) PrintSubnetInfo);
1149 /* Function Name: AddSubnet
1150 * Description: Creates a new subnet.
1151 * Arguments: argc, argv - the name of the new subnet is argv[1].
1152 * Returns: DM_NORMAL.
1157 AddSubnet(argc, argv)
1161 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1164 * Check to see if this subnet already exists.
1166 if (!ValidName(name))
1169 if ( (stat = do_mr_query("get_subnet", 1, &name,
1170 NullFunc, NULL)) == MR_SUCCESS) {
1171 Put_message("This subnet already exists.");
1174 else if (stat != MR_NO_MATCH) {
1175 com_err(program_name, stat, " in AddSubnet.");
1178 if ((args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)) ==
1180 Put_message("Aborted.");
1186 * Actually create the new Subnet.
1188 if ( (stat = do_mr_query("add_subnet", CountArgs(args),
1189 args, Scream, NULL)) != 0)
1190 com_err(program_name, stat, " in AddSubnet.");
1196 /* Function Name: RealUpdateSubnet
1197 * Description: This function actually performs the subnet update.
1198 * Arguments: info - all information nesc. for updating the subnet.
1199 * junk - an UNUSED boolean.
1205 RealUpdateSubnet(info, junk)
1210 char ** args = AskMCDInfo(info, SUBNET, TRUE);
1212 Put_message("Aborted.");
1215 if ( (stat = do_mr_query("update_subnet", CountArgs(args),
1216 args, Scream, NULL)) != 0)
1217 com_err(program_name, stat, " in UpdateSubnet.");
1219 Put_message("Subnet successfully updated.");
1222 /* Function Name: UpdateSubnet
1223 * Description: This Function Updates a subnet
1224 * Arguments: name of the subnet in argv[1].
1225 * Returns: DM_NORMAL.
1230 UpdateSubnet(argc, argv)
1235 top = GetMCInfo( SUBNET, argv[1], (char *) NULL );
1236 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1242 /* Function Name: RealDeleteSubnet
1243 * Description: Actually performs the subnet deletion.
1244 * Arguments: info - all information about this subnet.
1245 * one_subnet - If true then there was only one subnet in
1246 * the queue, and we should confirm.
1251 RealDeleteSubnet(info, one_subnet)
1256 char temp_buf[BUFSIZ];
1259 "Are you sure the you want to delete the subnet %s (y/n) ?",
1261 if (!one_subnet || Confirm(temp_buf)) {
1262 if ( (stat = do_mr_query("delete_subnet", 1,
1263 &info[C_NAME], Scream, NULL)) != 0) {
1264 com_err(program_name, stat, " in delete_subnet.");
1265 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.",
1267 Put_message(temp_buf);
1270 sprintf(temp_buf, "subnet %s sucesfully deleted.",
1272 Put_message(temp_buf);
1277 /* Function Name: DeleteSubnet
1278 * Description: This function removes a subnet from the database.
1279 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1280 * Returns: DM_NORMAL.
1285 DeleteSubnet(argc, argv)
1291 top = GetMCInfo( SUBNET, argv[1], (char *) NULL );
1292 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1298 /* ---------- Cluster Menu -------- */
1300 /* Function Name: ShowClusterInfo
1301 * Description: Gets information about a cluser given its name.
1302 * Arguments: argc, argc - the name of the cluster in in argv[1].
1303 * Returns: DM_NORMAL.
1308 ShowClusterInfo(argc, argv)
1314 top = GetMCInfo(CLUSTER, argv[1], (char *) NULL);
1315 Loop(top, (void *) PrintClusterInfo);
1320 /* Function Name: AddCluster
1321 * Description: Creates a new cluster.
1322 * Arguments: argc, argv - the name of the new cluster is argv[1].
1323 * Returns: DM_NORMAL.
1328 AddCluster(argc, argv)
1332 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1335 * Check to see if this cluster already exists.
1337 if (!ValidName(name))
1340 if ( (stat = do_mr_query("get_cluster", 1, &name,
1341 NullFunc, NULL)) == MR_SUCCESS) {
1342 Put_message("This cluster already exists.");
1345 else if (stat != MR_NO_MATCH) {
1346 com_err(program_name, stat, " in AddCluster.");
1349 if ((args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)) ==
1351 Put_message("Aborted.");
1357 * Actually create the new Cluster.
1359 if ( (stat = do_mr_query("add_cluster", CountArgs(args),
1360 args, Scream, NULL)) != 0)
1361 com_err(program_name, stat, " in AddCluster.");
1367 /* Function Name: RealUpdateCluster
1368 * Description: This function actually performs the cluster update.
1369 * Arguments: info - all information nesc. for updating the cluster.
1370 * junk - an UNUSED boolean.
1376 RealUpdateCluster(info, junk)
1381 char ** args = AskMCDInfo(info, CLUSTER, TRUE);
1383 Put_message("Aborted.");
1386 if ( (stat = do_mr_query("update_cluster", CountArgs(args),
1387 args, Scream, NULL)) != 0)
1388 com_err(program_name, stat, " in UpdateCluster.");
1390 Put_message("Cluster successfully updated.");
1393 /* Function Name: UpdateCluster
1394 * Description: This Function Updates a cluster
1395 * Arguments: name of the cluster in argv[1].
1396 * Returns: DM_NORMAL.
1401 UpdateCluster(argc, argv)
1406 top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
1407 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1413 /* Function Name: CheckAndRemoveMachine
1414 * Description: This function checks and removes all machines from a
1416 * Arguments: name - name of the cluster.
1417 * ask_first - if TRUE, then we will query the user, before
1419 * Returns: SUB_ERROR if all machines not removed.
1423 CheckAndRemoveMachines(name, ask_first)
1427 register int stat, ret_value;
1429 char *args[10], temp_buf[BUFSIZ], *ptr;
1430 struct qelem *top, *elem = NULL;
1432 ret_value = SUB_NORMAL;
1433 args[MAP_MACHINE] = "*";
1434 args[MAP_CLUSTER] = name;
1435 stat = do_mr_query("get_machine_to_cluster_map", 2, args,
1436 StoreInfo, (char *)&elem);
1437 if (stat && stat != MR_NO_MATCH) {
1438 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1442 elem = top = QueueTop(elem);
1445 "The cluster %s has the following machines in it:",
1447 Put_message(temp_buf);
1448 while (elem != NULL) {
1449 char **info = (char **) elem->q_data;
1450 Print(1, &info[MAP_MACHINE], (char *) NULL);
1451 elem = elem->q_forw;
1453 ptr = "Remove ** ALL ** these machines from this cluster?";
1455 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1458 Put_message("Aborting...");
1469 char **info = (char **) elem->q_data;
1470 if ( (stat = do_mr_query("delete_machine_from_cluster",
1471 2, info, Scream, NULL)) != 0) {
1472 ret_value = SUB_ERROR;
1473 com_err(program_name, stat,
1474 " in delete_machine_from_cluster.");
1476 "Machine %s ** NOT ** removed from cluster %s.",
1477 info[MAP_MACHINE], info[MAP_CLUSTER]);
1478 Put_message(temp_buf);
1480 elem = elem->q_forw;
1487 /* Function Name: RealDeleteCluster
1488 * Description: Actually performs the cluster deletion.
1489 * Arguments: info - all information about this cluster.
1490 * one_cluster - If true then there was only one cluster in
1491 * the queue, and we should confirm.
1496 RealDeleteCluster(info, one_cluster)
1501 char temp_buf[BUFSIZ];
1504 "Are you sure the you want to delete the cluster %s (y/n) ?",
1506 if (!one_cluster || Confirm(temp_buf)) {
1507 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR) {
1508 if ( (stat = do_mr_query("delete_cluster", 1,
1509 &info[C_NAME], Scream, NULL)) != 0) {
1510 com_err(program_name, stat, " in delete_cluster.");
1511 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.",
1513 Put_message(temp_buf);
1516 sprintf(temp_buf, "cluster %s sucesfully deleted.",
1518 Put_message(temp_buf);
1524 /* Function Name: DeleteCluster
1525 * Description: This function removes a cluster from the database.
1526 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1527 * Returns: DM_NORMAL.
1532 DeleteCluster(argc, argv)
1538 top = GetMCInfo( CLUSTER, argv[1], (char *) NULL );
1539 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1545 /* ----------- Cluster Data Menu -------------- */
1547 /* Function Name: ShowClusterData
1548 * Description: This function shows the services for one cluster.
1549 * Arguments: argc, argv - The name of the cluster is argv[1].
1550 * The label of the data in argv[2].
1551 * Returns: DM_NORMAL.
1556 ShowClusterData(argc, argv)
1560 struct qelem *elem, *top;
1563 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1564 while (elem != NULL) {
1565 info = (char **) elem->q_data;
1566 PrintClusterData(info);
1567 elem = elem->q_forw;
1573 /* Function Name: AddClusterData
1574 * Description: This function adds some data to the cluster.
1575 * Arguments: argv, argc: argv[1] - the name of the cluster.
1576 * argv[2] - the label of the data.
1577 * argv[3] - the data.
1578 * Returns: DM_NORMAL.
1583 AddClusterData(argc, argv)
1589 if( (stat = do_mr_query("add_cluster_data", 3, argv + 1,
1590 Scream, (char *) NULL)) != 0)
1591 com_err(program_name, stat, " in AddClusterData.");
1595 /* Function Name: RealRemoveClusterData
1596 * Description: actually removes the cluster data.
1597 * Arguments: info - all info necessary to remove the cluster, in an array
1599 * one_item - if true then the queue has only one elem and we
1605 RealRemoveClusterData(info, one_item)
1613 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1614 PrintClusterData(info);
1615 if (!one_item || Confirm(temp_ptr)) {
1616 if( (stat = do_mr_query("delete_cluster_data", 3, info,
1617 Scream, (char *) NULL)) != 0) {
1618 com_err(program_name, stat, " in DeleteClusterData.");
1619 Put_message("Data not removed.");
1622 Put_message("Removal sucessful.");
1626 /* Function Name: RemoveClusterData
1627 * Description: This function removes data on a given cluster.
1628 * Arguments: argv, argc: argv[1] - the name of the cluster.
1629 * argv[2] - the label of the data.
1630 * argv[3] - the data.
1631 * Returns: DM_NORMAL.
1636 RemoveClusterData(argc, argv)
1642 top = GetMCInfo(DATA, argv[1], argv[2]);
1643 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1644 "Remove data from cluster");
1650 /* Function Name: MachineToClusterMap
1651 * Description: This Retrieves the mapping between machine and cluster
1652 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1653 * argv[2] -> cluster name or wildcard.
1659 MachineToClusterMap(argc,argv)
1663 struct qelem *elem, *top;
1664 char *tmpname, temp_buf[256];
1666 tmpname = canonicalize_hostname(strsave(argv[1]));
1667 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"') {
1668 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1670 Put_message(temp_buf);
1672 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1674 Put_message(""); /* blank line on screen */
1675 while (elem != NULL) {
1676 char ** info = (char **) elem->q_data;
1678 elem = elem->q_forw;