3 * This is the file cluster.c for the Moira Client, which allows users
4 * to quickly and easily maintain most parts of the Moira database.
8 * By: Chris D. Peterson
10 * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
11 * For copying and distribution information, please see the file
15 /* BTW: for anyone who cares MCD is short for Machine, Cluster, Data. */
17 #include <mit-copyright.h>
19 #include <moira_site.h>
26 #include <sys/types.h>
29 #include <sys/utsname.h>
33 #include <netinet/in.h>
34 #include <arpa/inet.h>
43 void PrintAliases(char **info);
44 static void PrintMachine(char **info);
45 struct mqelem *GetMCInfo(int type, char *name1, char *name2);
46 struct mqelem *GetMachineByOwner(char *type, char *name);
47 char **AskMCDInfo(char **info, int type, Bool name);
48 int CheckAndRemoveFromCluster(char *name, Bool ask_user);
49 int CheckAndRemoveCnames(char *name, Bool ask_user);
50 int CheckAndRemoveMachines(char *name, Bool ask_first);
52 static char *PrintContainerInfo(char **info);
53 static void RealUpdateContainer(char **info, Bool junk);
54 static void RealDeleteContainer(char **info, Bool one_container);
55 static void RealRemoveMachineFromContainer(char **info, Bool one_contmap);
66 #define M_DEFAULT_TYPE DEFAULT_NONE
68 #define C_DEFAULT_DESCRIPT DEFAULT_NONE
69 #define C_DEFAULT_LOCATION DEFAULT_NONE
71 #define CON_DEFAULT_TYPE DEFAULT_NONE
73 #define CD_DEFAULT_LABEL DEFAULT_NONE
74 #define CD_DEFAULT_DATA DEFAULT_NONE
76 #define S_DEFAULT_LOW "18.0.0.20"
77 #define S_DEFAULT_HIGH "18.0.2.249"
79 static char *states[] = {
86 static char *MacState(int state)
88 static char buf[BUFSIZ];
90 if (state < 0 || state > 3)
92 sprintf(buf, "Unknown (%d)", state);
100 /* -------------------- Set Defaults -------------------- */
102 /* Function Name: SetMachineDefaults
103 * Description: sets machine defaults.
104 * Arguments: info - an array to put the defaults into.
105 * name - Canonacalized name of the machine.
106 * Returns: info - the array.
109 static char **SetMachineDefaults(char **info, char *name)
111 info[M_NAME] = strdup(name);
112 info[M_VENDOR] = strdup(M_DEFAULT_TYPE);
113 info[M_MODEL] = strdup(M_DEFAULT_TYPE);
114 info[M_OS] = strdup(M_DEFAULT_TYPE);
115 info[M_LOC] = strdup(M_DEFAULT_TYPE);
116 info[M_CONTACT] = strdup(M_DEFAULT_TYPE);
117 info[M_BILL_CONTACT] = strdup(M_DEFAULT_TYPE);
118 info[M_USE] = strdup("0");
119 info[M_STAT] = strdup("1");
120 info[M_SUBNET] = strdup("NONE");
121 info[M_ADDR] = strdup("unique");
122 info[M_OWNER_TYPE] = strdup("NONE");
123 info[M_OWNER_NAME] = strdup("NONE");
124 info[M_ACOMMENT] = strdup("");
125 info[M_OCOMMENT] = strdup("");
126 info[16] = info[17] = NULL;
130 /* Function Name: SetClusterDefaults
131 * Description: sets Cluster defaults.
132 * Arguments: info - an array to put the defaults into.
133 * name - name of the Cluster.
134 * Returns: info - the array.
137 static char **SetClusterDefaults(char **info, char *name)
139 info[C_NAME] = strdup(name);
140 info[C_DESCRIPT] = strdup(C_DEFAULT_DESCRIPT);
141 info[C_LOCATION] = strdup(C_DEFAULT_LOCATION);
142 info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
146 static char **SetContainerDefaults(char **info, char *name)
148 info[CON_NAME] = strdup(name);
149 info[CON_DESCRIPT] = strdup(CON_DEFAULT_TYPE);
150 info[CON_LOCATION] = strdup(CON_DEFAULT_TYPE);
151 info[CON_CONTACT] = strdup(CON_DEFAULT_TYPE);
152 info[CON_OWNER_TYPE] = strdup("NONE");
153 info[CON_OWNER_NAME] = strdup("NONE");
154 info[CON_MEMACE_TYPE] = strdup("NONE");
155 info[CON_MEMACE_NAME] = strdup("NONE");
156 info[CON_MODBY] = info[CON_MODTIME] = info[CON_MODWITH] = NULL;
157 info[CON_END] = NULL;
161 /* Function Name: SetSubnetDefaults
162 * Description: sets Subnet defaults.
163 * Arguments: info - an array to put the defaults into.
164 * name - name of the Subnet.
165 * Returns: info - the array.
168 static char **SetSubnetDefaults(char **info, char *name)
172 info[C_NAME] = strdup(name);
173 info[SN_DESC] = strdup("");
174 sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0")));
175 info[SN_ADDRESS] = strdup(buf);
176 sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0")));
177 info[SN_MASK] = strdup(buf);
178 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW)));
179 info[SN_LOW] = strdup(buf);
180 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH)));
181 info[SN_HIGH] = strdup(buf);
182 info[SN_PREFIX] = strdup("");
183 info[SN_ACE_TYPE] = strdup("LIST");
184 info[SN_ACE_NAME] = strdup("network");
185 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
189 /* -------------------- General Functions -------------------- */
191 static char aliasbuf[256];
193 void PrintAliases(char **info)
195 if (strlen(aliasbuf) == 0)
196 sprintf(aliasbuf, "Aliases: %s", info[0]);
199 strcat(aliasbuf, ", ");
200 strcat(aliasbuf, info[0]);
205 /* Function Name: PrintMachInfo
206 * Description: This function Prints out the Machine info in
208 * Arguments: info - array of information about a machine.
209 * Returns: The name of the Machine
212 static char *PrintMachInfo(char **info)
214 char buf[BUFSIZ], tbuf[256];
216 struct mqelem *elem = NULL;
220 sprintf(buf, "Machine: %s", info[M_NAME]);
223 args[1] = info[M_NAME];
224 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
226 if (stat != MR_NO_MATCH)
227 com_err(program_name, stat, " looking up aliases");
232 Loop(QueueTop(elem), (void (*)(char **)) PrintAliases);
234 Put_message(aliasbuf);
236 sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
237 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
238 sprintf(buf, "Address: %-16s Network: %-16s",
239 info[M_ADDR], info[M_SUBNET]);
241 sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]);
243 sprintf(buf, "Status: %-16s Changed: %s",
244 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
248 sprintf(buf, "Vendor: %-16s Location: %s", info[M_VENDOR],
251 sprintf(buf, "Model: %-16s Contact: %s", info[M_MODEL],
254 sprintf(buf, "OS: %-16s Billing Contact: %s", info[M_OS],
255 info[M_BILL_CONTACT]);
258 sprintf(buf, "Opt: %s", info[M_USE]);
261 sprintf(buf, "Adm cmt: %s", info[M_ACOMMENT]);
263 sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]);
266 sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]);
268 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
273 /* Function Name: PrintMachine
274 * Description: Prints the name of a machine record
275 * Arguments: info - array of information about the machine.
279 static void PrintMachine(char **info)
283 sprintf(buf, "Machine: %s", info[M_NAME]);
287 /* Function Name: PrintCname
288 * Description: Prints the Data on a host alias
289 * Arguments: info a pointer to the data array.
290 * Returns: The name of the alias.
293 static char *PrintCname(char **info)
297 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
302 /* Function Name: PrintClusterInfo
303 * Description: This function Prints out the cluster info
304 * in a coherent form.
305 * Arguments: info - array of information about a cluster.
306 * Returns: The name of the cluster.
309 static char *PrintClusterInfo(char **info)
314 sprintf(buf, "Cluster: %s", info[C_NAME]);
316 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
318 sprintf(buf, "Location: %s", info[C_LOCATION]);
320 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
325 /* Function Name: PrintClusterData
326 * Description: Prints the Data on a cluster
327 * Arguments: info a pointer to the data array.
328 * Returns: The name of the cluster.
331 static char *PrintClusterData(char **info)
336 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
337 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
339 return info[CD_NAME];
342 /* Function Name: PrintMCMap
343 * Description: Prints the data about a machine to cluster mapping.
344 * Arguments: info a pointer to the data array.
348 static char *PrintMCMap(char **info)
351 sprintf(buf, "Cluster: %-30s Machine: %-20s",
352 info[MAP_CLUSTER], info[MAP_MACHINE]);
354 return ""; /* Used by QueryLoop(). */
357 /* Function Name: PrintSubnetInfo
358 * Description: This function Prints out the subnet info
359 * in a coherent form.
360 * Arguments: info - array of information about a subnet.
361 * Returns: The name of the subnet.
364 static char *PrintSubnetInfo(char **info)
367 struct in_addr addr, mask, low, high;
370 sprintf(buf, " Network: %s", info[SN_NAME]);
372 sprintf(buf, " Description: %s", info[SN_DESC]);
374 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
375 mask.s_addr = htonl(atoi(info[SN_MASK]));
376 low.s_addr = htonl(atoi(info[SN_LOW]));
377 high.s_addr = htonl(atoi(info[SN_HIGH]));
378 /* screwy sequence is here because inet_ntoa returns a pointer to
379 a static buf. If it were all one sprintf, the last value would
381 sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr));
382 strcat(buf, inet_ntoa(mask));
383 strcat(buf, "\n High: ");
384 strcat(buf, inet_ntoa(high));
385 strcat(buf, " Low: ");
386 strcat(buf, inet_ntoa(low));
388 sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
390 sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE],
391 strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : "");
393 sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]);
395 return info[SN_NAME];
398 /* Function Name: GetMCInfo.
399 * Description: This function stores info about a machine.
400 * type - type of data we are trying to retrieve.
401 * name1 - the name of argv[0] for the call.
402 * name2 - the name of argv[1] for the call.
403 * Returns: the top element of a queue containing the data or NULL.
406 struct mqelem *GetMCInfo(int type, char *name1, char *name2)
409 struct mqelem *elem = NULL;
416 args[1] = args[2] = args[3] = "*";
417 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
419 if (stat == MR_NO_MATCH)
422 sprintf(buf, "Machine '%s' is not in the database.", name1);
426 com_err(program_name, stat, " in get_machine.");
433 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
435 com_err(program_name, stat, " in get_hostalias.");
440 if ((stat = do_mr_query("get_subnet", 1, &name1, StoreInfo, &elem)))
442 if (stat == MR_NO_MATCH)
445 sprintf(buf, "Network '%s' is not in the database.", name1);
449 com_err(program_name, stat, " in get_subnet.");
454 if ((stat = do_mr_query("get_cluster", 1, &name1, StoreInfo, &elem)))
456 com_err(program_name, stat, " in get_cluster.");
461 args[MAP_MACHINE] = name1;
462 args[MAP_CLUSTER] = name2;
463 if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args,
466 com_err(program_name, stat, " in get_machine_to_cluster_map.");
471 args[CD_NAME] = name1;
472 args[CD_LABEL] = name2;
473 if ((stat = do_mr_query("get_cluster_data", 2, args, StoreInfo, &elem)))
475 com_err(program_name, stat, " in get_cluster_data.");
480 args[CON_NAME] = name1;
481 if ((stat = do_mr_query("get_container", 1, &name1, StoreInfo, &elem)))
483 com_err(program_name, stat, " in get_container.");
489 if ((stat = do_mr_query("get_machine_to_container_map", 1, &name1,
492 com_err(program_name, stat, " in get_machine_to_container_map.");
496 return QueueTop(elem);
499 /* Function Name: AskMCDInfo.
500 * Description: This function askes the user for information about a
501 * machine and saves it into a structure.
502 * Arguments: info - a pointer the information to ask about
503 * type - type of information - MACHINE
507 * name - T/F : change the name of this type.
511 char **AskMCDInfo(char **info, int type, Bool name)
513 char temp_buf[BUFSIZ], *newname, *oldnewname;
518 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
522 sprintf(temp_buf, "Setting the information for the Network %s...",
526 sprintf(temp_buf, "Setting the information for the Cluster %s...",
530 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
534 sprintf(temp_buf, "Setting the Data for the Container %s...",
538 Put_message(temp_buf);
545 newname = strdup(info[M_NAME]);
546 if (GetValueFromUser("The new name for this machine? ", &newname) ==
549 oldnewname = strdup(newname);
550 newname = canonicalize_hostname(newname);
551 if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
553 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
554 oldnewname, newname);
555 Put_message(temp_buf);
560 newname = strdup(info[SN_NAME]);
561 if (GetValueFromUser("The new name for this network? ", &newname) ==
566 newname = strdup(info[C_NAME]);
567 if (GetValueFromUser("The new name for this cluster? ", &newname) ==
572 newname = strdup(info[CON_NAME]);
573 if (GetValueFromUser("The new name for this container? ", &newname)
578 Put_message("Unknown type in AskMCDInfo, programmer botch");
586 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
588 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
590 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
593 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
595 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
598 if (GetValueFromUser("Machine's billing contact",
599 &info[M_BILL_CONTACT]) == SUB_ERROR)
604 if (GetValueFromUser("Machine's status (? for help)",
605 &info[M_STAT]) == SUB_ERROR)
607 if (isdigit(info[M_STAT][0]))
609 Put_message("Valid status numbers:");
610 for (i = 0; i < 4; i++)
611 Put_message(states[i]);
614 /* there appears to be some argument mismatch between the client
615 * and the server.. so here is this argument shuffler.
616 * I have since modified this to always shuffle the arguments..
617 * not just do so when performing a modify all fields request.
618 * The SetMachinedefaults() has been changed to reflect this.
619 * pray for us and may we attain enlightenment through structures.
624 /* info did not come from SetMachineDefaults(), which does not
625 * initialize entry 8 (M_STAT_CHNG), therefore we can
628 /* This is an update of an existing machine and the structure
629 * was filled in thru a query to the db which does fill in this
635 info[9] = info[M_SUBNET];
636 info[10] = info[M_ADDR];
637 info[11] = info[M_OWNER_TYPE];
638 info[12] = info[M_OWNER_NAME];
639 info[13] = info[M_ACOMMENT];
640 info[14] = info[M_OCOMMENT];
644 if (GetValueFromUser("Machine's network (or 'none')", &info[9])
648 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
649 &info[10]) == SUB_ERROR)
651 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[11]) ==
654 if (strcmp(info[11], "NONE") &&
655 GetValueFromUser("Owner's Name", &info[12]) == SUB_ERROR)
657 if (!strcmp(info[11], "KERBEROS"))
661 mrcl_validate_kerberos_member(info[12], &canon);
662 if (mrcl_get_message())
663 Put_message(mrcl_get_message());
667 if (GetValueFromUser("Administrative comment", &info[13]) == SUB_ERROR)
669 if (GetValueFromUser("Operational comment", &info[14]) == SUB_ERROR)
672 FreeAndClear(&info[16], TRUE);
673 FreeAndClear(&info[17], TRUE);
676 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
678 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
680 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
682 if (atoi(info[SN_LOW]) == (int)ntohl(inet_addr(S_DEFAULT_LOW)))
685 unsigned long mask, addr;
687 addr = atoi(info[SN_ADDRESS]);
688 mask = atoi(info[SN_MASK]);
689 low.s_addr = atoi(info[SN_LOW]);
690 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
692 sprintf(temp_buf, "%ld", low.s_addr);
693 info[SN_LOW] = strdup(temp_buf);
695 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
698 if (atoi(info[SN_HIGH]) == (int)ntohl(inet_addr(S_DEFAULT_HIGH)))
701 unsigned long mask, addr;
703 addr = atoi(info[SN_ADDRESS]);
704 mask = atoi(info[SN_MASK]);
705 high.s_addr = atoi(info[SN_HIGH]);
706 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
708 sprintf(temp_buf, "%ld", high.s_addr);
709 info[SN_HIGH] = strdup(temp_buf);
711 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
714 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
716 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
719 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
720 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
722 if (!strcmp(info[SN_ACE_TYPE], "KERBEROS"))
726 mrcl_validate_kerberos_member(info[SN_ACE_NAME], &canon);
727 if (mrcl_get_message())
728 Put_message(mrcl_get_message());
729 free(info[SN_ACE_NAME]);
730 info[SN_ACE_NAME] = canon;
732 FreeAndClear(&info[SN_MODTIME], TRUE);
733 FreeAndClear(&info[SN_MODBY], TRUE);
734 FreeAndClear(&info[SN_MODWITH], TRUE);
737 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
740 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
743 FreeAndClear(&info[C_MODTIME], TRUE);
744 FreeAndClear(&info[C_MODBY], TRUE);
745 FreeAndClear(&info[C_MODWITH], TRUE);
748 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
751 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
755 if (GetValueFromUser("Container's Description:", &info[CON_DESCRIPT]) ==
758 if (GetValueFromUser("Container's Location:", &info[CON_LOCATION]) ==
761 if (GetValueFromUser("Container's Contact:", &info[CON_CONTACT]) ==
764 if (GetTypeFromUser("Container's owner type", "ace_type",
765 &info[CON_OWNER_TYPE]) == SUB_ERROR)
767 if (strcmp(info[CON_OWNER_TYPE], "NONE") &&
768 GetValueFromUser("Owner's Name", &info[CON_OWNER_NAME]) == SUB_ERROR)
770 if (!strcmp(info[CON_OWNER_TYPE], "KERBEROS"))
774 mrcl_validate_kerberos_member(info[CON_OWNER_NAME], &canon);
775 if (mrcl_get_message())
776 Put_message(mrcl_get_message());
777 free(info[CON_OWNER_NAME]);
778 info[CON_OWNER_NAME] = canon;
780 if (GetTypeFromUser("Container's Membership ACL", "ace_type",
781 &info[CON_MEMACE_TYPE]) == SUB_ERROR)
783 if (strcmp(info[CON_MEMACE_TYPE], "NONE") &&
784 GetValueFromUser("Membership ACL", &info[CON_MEMACE_NAME])
787 if (!strcmp(info[CON_MEMACE_TYPE], "KERBEROS"))
791 mrcl_validate_kerberos_member(info[CON_MEMACE_NAME], &canon);
792 if (mrcl_get_message())
793 Put_message(mrcl_get_message());
794 free(info[CON_MEMACE_NAME]);
795 info[CON_MEMACE_NAME] = canon;
797 FreeAndClear(&info[CON_MODTIME], TRUE);
798 FreeAndClear(&info[CON_MODBY], TRUE);
799 FreeAndClear(&info[CON_MODWITH], TRUE);
804 * Slide the newname into the #2 slot, this screws up all future references
808 SlipInNewName(info, newname);
813 /* ----------- Machine Menu ----------- */
815 /* Function Name: ShowMachineInfo
816 * Description: This function shows the information about a machine.
817 * Arguments: argc, argv - the name of the machine in argv[1].
818 * Returns: DM_NORMAL.
821 int ShowMachineInfo(int argc, char **argv)
826 tmpname = canonicalize_hostname(strdup(argv[1]));
827 top = GetMCInfo(MACHINE, tmpname, NULL);
828 Loop(top, ((void (*)(char **)) PrintMachInfo));
833 /* Function Name: ShowMachineQuery
834 * Description: This function shows the information about a machine.
835 * or group of machines, which may be selected through a
836 * number of criteria.
837 * Arguments: argc, argv - the name of the machine in argv[1],
838 * the address of the machine in argv[2],
839 * the location of the machine in argv[3],
840 * and the contact name in argv[4].
841 * any of these may be wildcards.
842 * Returns: DM_NORMAL.
845 int ShowMachineQuery(int argc, char **argv)
848 struct mqelem *top, *elem = NULL;
851 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
852 !strcmp(argv[3], "") && !strcmp(argv[4], ""))
854 Put_message("You must specify at least one parameter of the query.");
859 args[0] = canonicalize_hostname(strdup(argv[1]));
875 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
877 if (stat == MR_NO_MATCH)
878 Put_message("No machine(s) found matching query in the database.");
880 com_err(program_name, stat, " in get_machine.");
883 top = QueueTop(elem);
884 Loop(top, ((void (*)(char **)) PrintMachInfo));
889 /* Function Name: AddMachine
890 * Description: This function adds a new machine to the database.
891 * Arguments: argc, argv - the name of the network in argv[1].
892 * Returns: DM_NORMAL.
895 int AddMachine(int argc, char **argv)
897 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
899 struct mqelem *elem = NULL;
902 if (!ValidName(argv[1])) /* Checks for wildcards. */
906 * get the network record
909 if (strcasecmp(argv[1], "none") &&
910 (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem)))
912 if (stat == MR_NO_MATCH)
915 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
918 com_err(program_name, stat, " in get_subnet.");
923 * Check to see if this machine already exists.
926 name = strdup(""); /* want to put prefix here */
927 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
930 name = canonicalize_hostname(strdup(name));
933 xargs[1] = xargs[2] = xargs[3] = "*";
934 if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL)))
936 sprintf(buf, "The machine '%s' already exists.", name);
941 else if (stat != MR_NO_MATCH)
943 com_err(program_name, stat,
944 " while checking machine '%s' in AddMachine.", name);
948 rinfo = SetMachineDefaults(info, name);
949 rinfo[M_SUBNET] = strdup(argv[1]);
950 if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
952 Put_message("Aborted.");
957 * Actually create the new Machine.
960 if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL)))
961 com_err(program_name, stat, " in AddMachine.");
968 /* Function Name: RealUpdateMachine
969 * Description: Performs the actual update of the machine data.
970 * Arguments: info - the information on the machine to update.
971 * junk - an UNUSED Boolean.
975 static void RealUpdateMachine(char **info, Bool junk)
978 char **args = AskMCDInfo(info, MACHINE, TRUE);
981 Put_message("Aborted.");
984 if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL)))
985 com_err(program_name, stat, " in UpdateMachine.");
987 Put_message("Machine successfully updated.");
990 /* Function Name: UpdateMachine
991 * Description: This function adds a new machine to the database.
992 * Arguments: argc, argv - the name of the machine in argv[1].
993 * Returns: DM_NORMAL.
996 int UpdateMachine(int argc, char **argv)
1001 tmpname = canonicalize_hostname(strdup(argv[1]));
1002 top = GetMCInfo(MACHINE, tmpname, NULL);
1003 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
1010 /* Function Name: CheckAndRemoveFromCluster
1011 * Description: This func tests to see if a machine is in a cluster.
1012 * and if so then removes it
1013 * Arguments: name - name of the machine (already Canonicalized).
1014 * ask_user- query the user before removing if from clusters?
1015 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
1018 int CheckAndRemoveFromCluster(char *name, Bool ask_user)
1020 int stat, ret_value;
1022 char *args[10], temp_buf[BUFSIZ], *ptr;
1023 struct mqelem *top, *elem = NULL;
1025 ret_value = SUB_NORMAL; /* initialize ret_value. */
1028 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1029 if (stat && stat != MR_NO_MATCH)
1031 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1034 if (stat == MR_SUCCESS)
1036 elem = top = QueueTop(elem);
1039 sprintf(temp_buf, "%s is assigned to the following clusters.", name);
1040 Put_message(temp_buf);
1041 Loop(top, (void (*)(char **)) PrintMCMap);
1042 ptr = "Remove this machine from ** ALL ** these clusters?";
1043 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1047 Put_message("Aborting...");
1059 char **info = elem->q_data;
1060 if ((stat = do_mr_query("delete_machine_from_cluster",
1061 2, info, NULL, NULL)))
1063 ret_value = SUB_ERROR;
1064 com_err(program_name, stat,
1065 " in delete_machine_from_cluster.");
1067 "Machine %s ** NOT ** removed from cluster %s.",
1068 info[MAP_MACHINE], info[MAP_CLUSTER]);
1069 Put_message(temp_buf);
1071 elem = elem->q_forw;
1078 /* Function Name: CheckAndRemoveCnames
1079 * Description: This func tests to see if a machine has cnames,
1080 * and if so then removes them.
1081 * Arguments: name - name of the machine (already Canonicalized).
1082 * ask_user- query the user before removing cnames?
1083 * Returns: MR_ERROR if machine left with a cname, or mr_error.
1086 int CheckAndRemoveCnames(char *name, Bool ask_user)
1088 int stat, ret_value;
1090 char *args[10], temp_buf[BUFSIZ], *ptr;
1091 struct mqelem *top, *elem = NULL;
1093 ret_value = SUB_NORMAL;
1096 stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem);
1097 if (stat && stat != MR_NO_MATCH)
1099 com_err(program_name, stat, " in get_hostalias.");
1102 if (stat == MR_SUCCESS)
1104 elem = top = QueueTop(elem);
1107 sprintf(temp_buf, "%s has the following cnames.", name);
1108 Put_message(temp_buf);
1109 Loop(top, (void (*)(char **)) PrintCname);
1110 ptr = "Remove ** ALL ** these cnames?";
1111 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1115 Put_message("Aborting...");
1127 char **info = elem->q_data;
1128 if ((stat = do_mr_query("delete_hostalias", 2, info,
1131 ret_value = SUB_ERROR;
1132 com_err(program_name, stat, " in delete_hostalias.");
1134 "Cname %s ** NOT ** removed from host %s.",
1136 Put_message(temp_buf);
1138 elem = elem->q_forw;
1145 /* Function Name: RealDeleteMachine
1146 * Description: Actually Deletes the Machine.
1147 * Arguments: info - nescessary information stored as an array of char *'s
1148 * one_machine - a boolean, true if there is only one item in
1153 static void RealDeleteMachine(char **info, Bool one_machine)
1156 char temp_buf[BUFSIZ];
1158 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
1160 if (!one_machine || Confirm(temp_buf))
1162 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
1164 if (CheckAndRemoveCnames(info[M_NAME], TRUE) != SUB_ERROR)
1166 if ((stat = do_mr_query("delete_host", 1,
1167 &info[M_NAME], NULL, NULL)))
1169 com_err(program_name, stat, " in DeleteMachine.");
1170 sprintf(temp_buf, "%s ** NOT ** deleted.",
1172 Put_message(temp_buf);
1176 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
1177 Put_message(temp_buf);
1184 /* Function Name: DeleteMachine
1185 * Description: This function removes a machine from the data base.
1186 * Arguments: argc, argv - the machines name int argv[1].
1187 * Returns: DM_NORMAL.
1190 /* Perhaps we should remove the cluster if it has no machine now. */
1192 int DeleteMachine(int argc, char **argv)
1197 tmpname = canonicalize_hostname(strdup(argv[1]));
1198 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
1199 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
1206 /* Function Name: ShowCname
1207 * Description: This function shows machine aliases
1208 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1209 * Returns: DM_NORMAL.
1212 int ShowCname(int argc, char **argv)
1215 char *tmpalias, *tmpname;
1217 tmpalias = partial_canonicalize_hostname(strdup(argv[1]));
1218 tmpname = canonicalize_hostname(strdup(argv[2]));
1219 top = GetMCInfo(CNAME, tmpalias, tmpname);
1220 Put_message(""); /* blank line on screen */
1221 Loop(top, ((void (*)(char **)) PrintCname));
1227 int AddCname(int argc, char **argv)
1232 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1233 args[1] = canonicalize_hostname(strdup(argv[2]));
1234 stat = do_mr_query("add_hostalias", 2, args, NULL, NULL);
1240 Put_message("That alias name is already in use.");
1243 Put_message("Permission denied. "
1244 "(Regular users can only add two aliases to a host.");
1247 com_err(program_name, stat, " in add_hostalias");
1253 int DeleteCname(int argc, char **argv)
1258 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1259 args[1] = canonicalize_hostname(strdup(argv[2]));
1260 stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL);
1262 com_err(program_name, stat, " in delete_hostalias");
1267 /* Function Name: AddMachineToCluster
1268 * Description: This function adds a machine to a cluster
1269 * Arguments: argc, argv - The machine name is argv[1].
1270 * The cluster name in argv[2].
1271 * Returns: DM_NORMAL.
1274 int AddMachineToCluster(int argc, char **argv)
1277 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1278 Bool add_it, one_machine, one_cluster;
1279 struct mqelem *melem, *mtop, *celem, *ctop;
1281 machine = canonicalize_hostname(strdup(argv[1]));
1282 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1284 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1286 Put_message(temp_buf);
1290 celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1291 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1294 one_machine = (QueueCount(mtop) == 1);
1295 one_cluster = (QueueCount(ctop) == 1);
1297 /* No good way to use QueryLoop() here, sigh */
1301 char **minfo = melem->q_data;
1304 char **cinfo = celem->q_data;
1305 if (one_machine && one_cluster)
1309 sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1310 minfo[M_NAME], cinfo[C_NAME]);
1311 switch (YesNoQuitQuestion(temp_buf, FALSE))
1320 Put_message("Aborting...");
1328 args[0] = minfo[M_NAME];
1329 args[1] = cinfo[C_NAME];
1330 stat = do_mr_query("add_machine_to_cluster", 2, args,
1337 sprintf(temp_buf, "%s is already in cluster %s",
1338 minfo[M_NAME], cinfo[C_NAME]);
1339 Put_message(temp_buf);
1342 com_err(program_name, stat, " in AddMachineToCluster.");
1346 celem = celem->q_forw;
1348 celem = ctop; /* reset cluster element. */
1349 melem = melem->q_forw;
1356 /* Function Name: RealRemoveMachineFromCluster
1357 * Description: This function actually removes the machine from its
1359 * Arguments: info - all information nescessary to perform the removal.
1360 * one_map - True if there is only one case, and we should
1365 static void RealRemoveMachineFromCluster(char **info, Bool one_map)
1367 char temp_buf[BUFSIZ];
1370 sprintf(temp_buf, "Remove %s from the cluster %s",
1371 info[MAP_MACHINE], info[MAP_CLUSTER]);
1372 if (!one_map || Confirm(temp_buf))
1374 if ((stat = do_mr_query("delete_machine_from_cluster", 2,
1376 com_err(program_name, stat, " in delete_machine_from_cluster");
1379 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1380 info[MAP_MACHINE], info[MAP_CLUSTER]);
1381 Put_message(temp_buf);
1385 Put_message("Machine not removed.");
1388 /* Function Name: RemoveMachineFromCluster
1389 * Description: Removes this machine form a specific cluster.
1390 * Arguments: argc, argv - Name of machine in argv[1].
1391 * Name of cluster in argv[2].
1395 int RemoveMachineFromCluster(int argc, char **argv)
1397 struct mqelem *elem = NULL;
1398 char buf[BUFSIZ], *args[10];
1401 args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1]));
1402 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1404 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1405 argv[1], args[MAP_MACHINE]);
1408 args[MAP_CLUSTER] = argv[2];
1409 args[MAP_END] = NULL;
1411 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1413 if (stat == MR_NO_MATCH)
1415 sprintf(buf, "The machine %s is not in the cluster %s.",
1416 args[MAP_MACHINE], args[MAP_CLUSTER]);
1418 free(args[MAP_MACHINE]);
1421 if (stat != MR_SUCCESS)
1422 com_err(program_name, stat, " in delete_machine_from_cluster");
1424 elem = QueueTop(elem);
1425 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1426 "Remove this machine from this cluster");
1429 free(args[MAP_MACHINE]);
1433 /* ---------- Subnet Menu -------- */
1435 /* Function Name: ShowSubnetInfo
1436 * Description: Gets information about a subnet given its name.
1437 * Arguments: argc, argc - the name of the subnet in in argv[1].
1438 * Returns: DM_NORMAL.
1441 int ShowSubnetInfo(int argc, char **argv)
1445 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1446 Loop(top, (void (*)(char **)) PrintSubnetInfo);
1451 /* Function Name: AddSubnet
1452 * Description: Creates a new subnet.
1453 * Arguments: argc, argv - the name of the new subnet is argv[1].
1454 * Returns: DM_NORMAL.
1457 int AddSubnet(int argc, char **argv)
1459 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1463 * Check to see if this subnet already exists.
1465 if (!ValidName(name))
1468 if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS)
1470 Put_message("This subnet already exists.");
1473 else if (stat != MR_NO_MATCH)
1475 com_err(program_name, stat, " in AddSubnet.");
1478 if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1480 Put_message("Aborted.");
1486 * Actually create the new Subnet.
1488 if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL)))
1489 com_err(program_name, stat, " in AddSubnet.");
1495 /* Function Name: RealUpdateSubnet
1496 * Description: This function actually performs the subnet update.
1497 * Arguments: info - all information nesc. for updating the subnet.
1498 * junk - an UNUSED boolean.
1502 static void RealUpdateSubnet(char **info, Bool junk)
1505 char **args = AskMCDInfo(info, SUBNET, TRUE);
1508 Put_message("Aborted.");
1511 if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL)))
1512 com_err(program_name, stat, " in UpdateSubnet.");
1514 Put_message("Subnet successfully updated.");
1517 /* Function Name: UpdateSubnet
1518 * Description: This Function Updates a subnet
1519 * Arguments: name of the subnet in argv[1].
1520 * Returns: DM_NORMAL.
1523 int UpdateSubnet(int argc, char **argv)
1526 top = GetMCInfo(SUBNET, argv[1], NULL);
1527 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1533 /* Function Name: RealDeleteSubnet
1534 * Description: Actually performs the subnet deletion.
1535 * Arguments: info - all information about this subnet.
1536 * one_subnet - If true then there was only one subnet in
1537 * the queue, and we should confirm.
1541 static void RealDeleteSubnet(char **info, Bool one_subnet)
1544 char temp_buf[BUFSIZ];
1547 "Are you sure the you want to delete the subnet %s (y/n) ?",
1549 if (!one_subnet || Confirm(temp_buf))
1551 if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL)))
1553 com_err(program_name, stat, " in delete_subnet.");
1554 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1555 Put_message(temp_buf);
1559 sprintf(temp_buf, "subnet %s successfully deleted.",
1561 Put_message(temp_buf);
1566 /* Function Name: DeleteSubnet
1567 * Description: This function removes a subnet from the database.
1568 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1569 * Returns: DM_NORMAL.
1572 int DeleteSubnet(int argc, char **argv)
1576 top = GetMCInfo(SUBNET, argv[1], NULL);
1577 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1583 /* ---------- Cluster Menu -------- */
1585 /* Function Name: ShowClusterInfo
1586 * Description: Gets information about a cluser given its name.
1587 * Arguments: argc, argc - the name of the cluster in in argv[1].
1588 * Returns: DM_NORMAL.
1591 int ShowClusterInfo(int argc, char **argv)
1595 top = GetMCInfo(CLUSTER, argv[1], NULL);
1596 Loop(top, (void (*)(char **)) PrintClusterInfo);
1601 /* Function Name: AddCluster
1602 * Description: Creates a new cluster.
1603 * Arguments: argc, argv - the name of the new cluster is argv[1].
1604 * Returns: DM_NORMAL.
1607 int AddCluster(int argc, char **argv)
1609 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1613 * Check to see if this cluster already exists.
1615 if (!ValidName(name))
1618 if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS)
1620 Put_message("This cluster already exists.");
1623 else if (stat != MR_NO_MATCH)
1625 com_err(program_name, stat, " in AddCluster.");
1628 if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1630 Put_message("Aborted.");
1636 * Actually create the new Cluster.
1638 if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL)))
1639 com_err(program_name, stat, " in AddCluster.");
1645 /* Function Name: RealUpdateCluster
1646 * Description: This function actually performs the cluster update.
1647 * Arguments: info - all information nesc. for updating the cluster.
1648 * junk - an UNUSED boolean.
1652 static void RealUpdateCluster(char **info, Bool junk)
1655 char **args = AskMCDInfo(info, CLUSTER, TRUE);
1659 Put_message("Aborted.");
1662 if ((stat = do_mr_query("update_cluster", CountArgs(args),
1664 com_err(program_name, stat, " in UpdateCluster.");
1666 Put_message("Cluster successfully updated.");
1669 /* Function Name: UpdateCluster
1670 * Description: This Function Updates a cluster
1671 * Arguments: name of the cluster in argv[1].
1672 * Returns: DM_NORMAL.
1675 int UpdateCluster(int argc, char **argv)
1678 top = GetMCInfo(CLUSTER, argv[1], NULL);
1679 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1685 /* Function Name: CheckAndRemoveMachine
1686 * Description: This function checks and removes all machines from a
1688 * Arguments: name - name of the cluster.
1689 * ask_first - if TRUE, then we will query the user, before
1691 * Returns: SUB_ERROR if all machines not removed.
1694 int CheckAndRemoveMachines(char *name, Bool ask_first)
1696 int stat, ret_value;
1698 char *args[10], temp_buf[BUFSIZ], *ptr;
1699 struct mqelem *top, *elem = NULL;
1701 ret_value = SUB_NORMAL;
1702 args[MAP_MACHINE] = "*";
1703 args[MAP_CLUSTER] = name;
1704 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1705 if (stat && stat != MR_NO_MATCH)
1707 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1710 if (stat == MR_SUCCESS)
1712 elem = top = QueueTop(elem);
1715 sprintf(temp_buf, "The cluster %s has the following machines in it:",
1717 Put_message(temp_buf);
1720 char **info = elem->q_data;
1721 Print(1, &info[MAP_MACHINE], (char *) NULL);
1722 elem = elem->q_forw;
1724 ptr = "Remove ** ALL ** these machines from this cluster?";
1726 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1730 Put_message("Aborting...");
1743 char **info = elem->q_data;
1744 if ((stat = do_mr_query("delete_machine_from_cluster",
1745 2, info, NULL, NULL)))
1747 ret_value = SUB_ERROR;
1748 com_err(program_name, stat,
1749 " in delete_machine_from_cluster.");
1751 "Machine %s ** NOT ** removed from cluster %s.",
1752 info[MAP_MACHINE], info[MAP_CLUSTER]);
1753 Put_message(temp_buf);
1755 elem = elem->q_forw;
1762 /* Function Name: RealDeleteCluster
1763 * Description: Actually performs the cluster deletion.
1764 * Arguments: info - all information about this cluster.
1765 * one_cluster - If true then there was only one cluster in
1766 * the queue, and we should confirm.
1770 static void RealDeleteCluster(char **info, Bool one_cluster)
1773 char temp_buf[BUFSIZ];
1776 "Are you sure the you want to delete the cluster %s (y/n) ?",
1778 if (!one_cluster || Confirm(temp_buf))
1780 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1782 if ((stat = do_mr_query("delete_cluster", 1,
1783 &info[C_NAME], NULL, NULL)))
1785 com_err(program_name, stat, " in delete_cluster.");
1786 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1787 Put_message(temp_buf);
1791 sprintf(temp_buf, "cluster %s successfully deleted.",
1793 Put_message(temp_buf);
1799 /* Function Name: DeleteCluster
1800 * Description: This function removes a cluster from the database.
1801 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1802 * Returns: DM_NORMAL.
1805 int DeleteCluster(int argc, char **argv)
1809 top = GetMCInfo(CLUSTER, argv[1], NULL);
1810 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1816 /* ----------- Cluster Data Menu -------------- */
1818 /* Function Name: ShowClusterData
1819 * Description: This function shows the services for one cluster.
1820 * Arguments: argc, argv - The name of the cluster is argv[1].
1821 * The label of the data in argv[2].
1822 * Returns: DM_NORMAL.
1825 int ShowClusterData(int argc, char **argv)
1827 struct mqelem *elem, *top;
1830 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1833 info = elem->q_data;
1834 PrintClusterData(info);
1835 elem = elem->q_forw;
1841 /* Function Name: AddClusterData
1842 * Description: This function adds some data to the cluster.
1843 * Arguments: argv, argc: argv[1] - the name of the cluster.
1844 * argv[2] - the label of the data.
1845 * argv[3] - the data.
1846 * Returns: DM_NORMAL.
1849 int AddClusterData(int argc, char **argv)
1853 for (i = 1; i < 4; i++)
1855 if (IS_EMPTY(argv[i]))
1857 Put_message("Cluster data cannot be an empty string.");
1861 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
1862 com_err(program_name, stat, " in AddClusterData.");
1866 /* Function Name: RealRemoveClusterData
1867 * Description: actually removes the cluster data.
1868 * Arguments: info - all info necessary to remove the cluster, in an array
1870 * one_item - if true then the queue has only one elem and we
1875 static void RealRemoveClusterData(char **info, Bool one_item)
1881 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1882 PrintClusterData(info);
1883 if (!one_item || Confirm(temp_ptr))
1885 if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
1887 com_err(program_name, stat, " in DeleteClusterData.");
1888 Put_message("Data not removed.");
1891 Put_message("Removal successful.");
1895 /* Function Name: RemoveClusterData
1896 * Description: This function removes data on a given cluster.
1897 * Arguments: argv, argc: argv[1] - the name of the cluster.
1898 * argv[2] - the label of the data.
1899 * argv[3] - the data.
1900 * Returns: DM_NORMAL.
1903 int RemoveClusterData(int argc, char **argv)
1907 top = GetMCInfo(DATA, argv[1], argv[2]);
1908 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1909 "Remove data from cluster");
1915 /* Function Name: MachineToClusterMap
1916 * Description: This Retrieves the mapping between machine and cluster
1917 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1918 * argv[2] -> cluster name or wildcard.
1922 int MachineToClusterMap(int argc, char **argv)
1924 struct mqelem *elem, *top;
1925 char *tmpname, temp_buf[256];
1927 tmpname = canonicalize_hostname(strdup(argv[1]));
1928 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
1930 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1932 Put_message(temp_buf);
1934 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1936 Put_message(""); /* blank line on screen */
1939 char **info = elem->q_data;
1941 elem = elem->q_forw;
1949 /* Function Name: MachineByOwner
1950 * Description: This function prints all machines which are owned by
1951 * a given user or group.
1953 * Returns: DM_NORMAL.
1956 int MachineByOwner(int argc, char **argv)
1958 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
1961 type = strdup("USER");
1962 if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR)
1965 sprintf(buf, "Name of %s", type);
1966 name = strdup(user);
1967 if (GetValueFromUser(buf, &name) == SUB_ERROR)
1970 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
1973 sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */
1975 type = strdup(temp_buf);
1983 top = GetMachineByOwner(type, name);
1984 Loop(top, PrintMachine);
1990 /* Function Name: GetMachineByOwner
1991 * Description: This function stores information retrieved by
1992 * the get_host_by_owner query
1993 * Arguments: type - an ace_type, argv[0] for the query
1994 * name - name of machine, argv[1] for the query
1995 * Returns: the top element of a queue returning the data, or NULL.
1998 struct mqelem *GetMachineByOwner(char *type, char *name)
2001 struct mqelem *elem = NULL;
2006 if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem)))
2008 com_err(program_name, status, " in get_host_by_owner");
2011 return QueueTop(elem);
2014 int ShowContainerInfo(int argc, char **argv)
2018 top = GetMCInfo(CONTAINER, argv[1], NULL);
2019 Loop(top, (void (*)(char **)) PrintContainerInfo);
2024 static char *PrintContainerInfo(char **info)
2026 char buf[BUFSIZ], tbuf[256];
2029 sprintf(buf, "Container: %-16s", info[CON_NAME]);
2031 sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]);
2033 sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION],
2036 sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE],
2037 strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : "");
2038 sprintf(buf, "Owner: %-16s", tbuf);
2040 sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE],
2041 strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : "");
2042 sprintf(buf, "Membership ACL: %-16s", tbuf);
2045 sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME],
2048 return info[CON_NAME];
2051 static char *PrintContainer(char **info)
2055 sprintf(buf, "Container: %s", info[CON_NAME]);
2059 static char *PrintMContMap(char **info)
2062 sprintf(buf, "Container: %-30s Machine: %-20s",
2068 int AddContainer(int argc, char **argv)
2070 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
2073 if (!ValidName(name))
2076 /* Check if this cluster already exists. */
2077 if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL))
2080 Put_message("This container already exists.");
2083 else if (stat != MR_NO_MATCH)
2085 com_err(program_name, stat, " in AddContainer.");
2088 if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE)))
2090 Put_message("Aborted.");
2095 /* Create the new container. */
2096 if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL)))
2097 com_err(program_name, stat, " in AddContainer.");
2103 int UpdateContainer(int argc, char **argv)
2106 top = GetMCInfo(CONTAINER, argv[1], NULL);
2107 QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container");
2113 static void RealUpdateContainer(char **info, Bool junk)
2116 char **args = AskMCDInfo(info, CONTAINER, TRUE);
2120 Put_message("Aborted.");
2123 if ((stat = do_mr_query("update_container", CountArgs(args), args,
2125 com_err(program_name, stat, " in UpdateContainer.");
2127 Put_message("Container successfully updated.");
2130 int DeleteContainer(int argc, char **argv)
2134 top = GetMCInfo(CONTAINER, argv[1], NULL);
2135 QueryLoop(top, PrintClusterInfo, RealDeleteContainer,
2136 "Delete the container");
2142 static void RealDeleteContainer(char **info, Bool one_container)
2145 char temp_buf[BUFSIZ];
2148 "Are you sure you want to delete the container %s (y/n) ?",
2150 if (!one_container || Confirm(temp_buf))
2152 if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE)
2155 if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME],
2158 com_err(program_name, stat, " in delete_container.");
2159 sprintf(temp_buf, "Container %s ** NOT ** deleted.",
2161 Put_message(temp_buf);
2165 sprintf(temp_buf, "Container %s successfully deleted.",
2167 Put_message(temp_buf);
2173 int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first)
2175 int stat, ret_value;
2177 char *args[10], temp_buf[BUFSIZ], *ptr;
2178 struct mqelem *top, *elem = NULL;
2180 ret_value = SUB_NORMAL;
2183 stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo,
2185 if (stat && stat != MR_NO_MATCH)
2187 com_err(program_name, stat, " in get_machines_of_container");
2190 if (stat == MR_SUCCESS)
2192 elem = top = QueueTop(elem);
2196 "The container %s has the following machines in it:", name);
2197 Put_message(temp_buf);
2200 char **info = elem->q_data;
2201 Print(1, &info[0], (char *) NULL);
2202 elem = elem->q_forw;
2204 ptr = "Remove ** ALL ** these machines from this container?";
2206 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
2210 Put_message("Aborting...");
2223 char **info = elem->q_data;
2224 if ((stat = do_mr_query("delete_machine_from_container",
2225 2, info, NULL, NULL)))
2227 ret_value = SUB_ERROR;
2228 com_err(program_name, stat,
2229 " in delete_machine_from_container.");
2231 "Machine %s ** NOT ** removed from container %s.",
2233 Put_message(temp_buf);
2235 elem = elem->q_forw;
2242 int GetSubContainers(int argc, char **argv)
2245 struct mqelem *elem = NULL, *top = NULL;
2250 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2255 if (stat = do_mr_query("get_subcontainers_of_container", 2, args,
2257 com_err(program_name, stat, " in get_subcontainers_of_container");
2259 top = QueueTop(elem);
2260 Loop(top, ((void (*)(char **)) PrintContainer));
2265 int MachineToContainerMap(int argc, char **argv)
2267 struct mqelem *elem, *top;
2268 char *tmpname, temp_buf[256];
2270 tmpname = canonicalize_hostname(strdup(argv[1]));
2271 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2273 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2275 Put_message(temp_buf);
2277 top = elem = GetMCInfo(CONTMAP, tmpname, NULL);
2282 char **info = elem->q_data;
2283 PrintMContMap(info);
2284 elem = elem->q_forw;
2292 int AddMachineToContainer(int argc, char **argv)
2295 char *machine, *container, temp_buf[BUFSIZ], *args[10];
2296 Bool add_it, one_machine, one_container;
2297 struct mqelem *melem, *mtop, *celem, *ctop;
2299 machine = canonicalize_hostname(strdup(argv[1]));
2300 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
2302 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2304 Put_message(temp_buf);
2306 container = argv[2];
2308 celem = ctop = GetMCInfo(CONTAINER, container, NULL);
2309 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
2312 one_machine = (QueueCount(mtop) == 1);
2313 one_container = (QueueCount(ctop) == 1);
2317 char **minfo = melem->q_data;
2320 char **cinfo = celem->q_data;
2321 if (one_machine && one_container)
2325 sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?",
2326 minfo[M_NAME], cinfo[CON_NAME]);
2327 switch (YesNoQuestion(temp_buf, FALSE))
2336 Put_message("Aborting...");
2344 args[0] = minfo[M_NAME];
2345 args[1] = cinfo[CON_NAME];
2346 stat = do_mr_query("add_machine_to_container", 2, args, NULL,
2353 sprintf(temp_buf, "%s is already in container %s",
2354 minfo[M_NAME], cinfo[CON_NAME]);
2355 Put_message(temp_buf);
2358 com_err(program_name, stat, " in AddMachineToContainer.");
2362 celem = celem->q_forw;
2365 melem = melem->q_forw;
2372 int RemoveMachineFromContainer(int argc, char **argv)
2374 struct mqelem *elem = NULL;
2375 char buf[BUFSIZ], *args[10];
2378 args[0] = canonicalize_hostname(strdup(argv[1]));
2379 if (strcasecmp(args[0], argv[1]) && *argv[1] != '"')
2381 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
2388 stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo,
2390 if (stat == MR_NO_MATCH)
2392 sprintf(buf, "The machine %s is not in the container %s.",
2398 if (stat != MR_SUCCESS)
2399 com_err(program_name, stat, " in deleter_machine_from_container");
2401 elem = QueueTop(elem);
2402 QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer,
2403 "Remove this machine from this container");
2410 static void RealRemoveMachineFromContainer(char **info, Bool one_contmap)
2412 char temp_buf[BUFSIZ];
2415 sprintf(temp_buf, "Remove %s from the container %s",
2417 if (!one_contmap || Confirm(temp_buf))
2419 if ((stat = do_mr_query("delete_machine_from_container", 2,
2421 com_err(program_name, stat, " in delete_machine_from_container");
2424 sprintf(temp_buf, "%s has been removed from the container %s.",
2426 Put_message(temp_buf);
2430 Put_message("Machine not removed.");
2433 int GetMachinesOfContainer(int argc, char **argv)
2436 struct mqelem *elem = NULL, *top = NULL;
2441 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2446 if (stat = do_mr_query("get_machines_of_container", 2, args,
2448 com_err(program_name, stat, " in get_machines_of_container");
2450 top = QueueTop(elem);
2451 Loop(top, ((void (*)(char **)) PrintMContMap));