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 *subnet_states[] = {
89 "Private, 10 Mbps (2)",
90 "Private, 100 Mbps (3)",
94 "Private, 1000 Mbps (7)",
98 static char *MacState(int state)
100 static char buf[BUFSIZ];
102 if (state < 0 || state > 3)
104 sprintf(buf, "Unknown (%d)", state);
107 return states[state];
110 static char *SubnetState(int state)
112 static char buf[BUFSIZ];
114 if (state < 0 || state > 8)
116 sprintf(buf, "Unknown (%d)", state);
119 return subnet_states[state];
122 /* -------------------- Set Defaults -------------------- */
124 /* Function Name: SetMachineDefaults
125 * Description: sets machine defaults.
126 * Arguments: info - an array to put the defaults into.
127 * name - Canonacalized name of the machine.
128 * Returns: info - the array.
131 static char **SetMachineDefaults(char **info, char *name)
133 info[M_NAME] = strdup(name);
134 info[M_VENDOR] = strdup(M_DEFAULT_TYPE);
135 info[M_MODEL] = strdup(M_DEFAULT_TYPE);
136 info[M_OS] = strdup(M_DEFAULT_TYPE);
137 info[M_LOC] = strdup(M_DEFAULT_TYPE);
138 info[M_CONTACT] = strdup(M_DEFAULT_TYPE);
139 info[M_BILL_CONTACT] = strdup(M_DEFAULT_TYPE);
140 info[M_ACCT_NUMBER] = strdup("");
141 info[M_USE] = strdup("0");
142 info[M_STAT] = strdup("1");
143 info[M_SUBNET] = strdup("NONE");
144 info[M_ADDR] = strdup("unique");
145 info[M_OWNER_TYPE] = strdup("NONE");
146 info[M_OWNER_NAME] = strdup("NONE");
147 info[M_ACOMMENT] = strdup("");
148 info[M_OCOMMENT] = strdup("");
149 info[17] = info[18] = NULL;
153 /* Function Name: SetClusterDefaults
154 * Description: sets Cluster defaults.
155 * Arguments: info - an array to put the defaults into.
156 * name - name of the Cluster.
157 * Returns: info - the array.
160 static char **SetClusterDefaults(char **info, char *name)
162 info[C_NAME] = strdup(name);
163 info[C_DESCRIPT] = strdup(C_DEFAULT_DESCRIPT);
164 info[C_LOCATION] = strdup(C_DEFAULT_LOCATION);
165 info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
169 static char **SetContainerDefaults(char **info, char *name)
171 info[CON_NAME] = strdup(name);
172 info[CON_PUBLIC] = strdup(DEFAULT_NO);
173 info[CON_DESCRIPT] = strdup(CON_DEFAULT_TYPE);
174 info[CON_LOCATION] = strdup(CON_DEFAULT_TYPE);
175 info[CON_CONTACT] = strdup(CON_DEFAULT_TYPE);
176 info[CON_OWNER_TYPE] = strdup("NONE");
177 info[CON_OWNER_NAME] = strdup("NONE");
178 info[CON_MEMACE_TYPE] = strdup("NONE");
179 info[CON_MEMACE_NAME] = strdup("NONE");
180 info[CON_MODBY] = info[CON_MODTIME] = info[CON_MODWITH] = NULL;
181 info[CON_END] = NULL;
185 /* Function Name: SetSubnetDefaults
186 * Description: sets Subnet defaults.
187 * Arguments: info - an array to put the defaults into.
188 * name - name of the Subnet.
189 * Returns: info - the array.
192 static char **SetSubnetDefaults(char **info, char *name)
196 info[SN_NAME] = strdup(name);
197 info[SN_DESC] = strdup("");
198 info[SN_STATUS] = strdup("1");
199 info[SN_CONTACT] = strdup(DEFAULT_NONE);
200 info[SN_ACCT_NUMBER] = strdup("");
201 sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0")));
202 info[SN_ADDRESS] = strdup(buf);
203 sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0")));
204 info[SN_MASK] = strdup(buf);
205 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW)));
206 info[SN_LOW] = strdup(buf);
207 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH)));
208 info[SN_HIGH] = strdup(buf);
209 info[SN_PREFIX] = strdup("");
210 info[SN_ACE_TYPE] = strdup("LIST");
211 info[SN_ACE_NAME] = strdup("network");
212 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
216 /* -------------------- General Functions -------------------- */
218 static char aliasbuf[256];
220 void PrintAliases(char **info)
222 if (strlen(aliasbuf) == 0)
223 sprintf(aliasbuf, "Aliases: %s", info[0]);
226 strcat(aliasbuf, ", ");
227 strcat(aliasbuf, info[0]);
232 /* Function Name: PrintMachInfo
233 * Description: This function Prints out the Machine info in
235 * Arguments: info - array of information about a machine.
236 * Returns: The name of the Machine
239 static char *PrintMachInfo(char **info)
241 char buf[BUFSIZ], tbuf[256];
243 struct mqelem *elem = NULL, *elem2 = NULL;
247 sprintf(buf, "Machine: %s", info[M_NAME]);
250 args[1] = info[M_NAME];
251 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
253 if (stat != MR_NO_MATCH)
254 com_err(program_name, stat, " looking up aliases");
259 Loop(QueueTop(elem), (void (*)(char **)) PrintAliases);
261 Put_message(aliasbuf);
263 sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
264 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
265 sprintf(buf, "Address: %-16s Network: %-16s",
266 info[M_ADDR], info[M_SUBNET]);
268 sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]);
270 sprintf(buf, "Status: %-16s Changed: %s",
271 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
274 sprintf(buf, "Vendor: %-16s Location: %s", info[M_VENDOR],
277 sprintf(buf, "Model: %-16s Contact: %s", info[M_MODEL],
280 sprintf(buf, "OS: %-16s Billing Contact: %s", info[M_OS],
281 info[M_BILL_CONTACT]);
283 sprintf(buf, "Opt: %-16s Account Number: %s", info[M_USE],
284 info[M_ACCT_NUMBER]);
287 sprintf(buf, "Adm cmt: %s", info[M_ACOMMENT]);
289 sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]);
292 sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]);
294 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
296 /* Do a get_subnet for the machine's subnet. We need to know if it's
299 args[0] = info[M_SUBNET];
300 stat = do_mr_query("get_subnet", 1, args, StoreInfo, &elem2);
302 com_err(program_name, stat, " looking up subnet info");
303 else if (atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_10MBPS ||
304 atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_100MBPS ||
305 atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_1000MBPS)
308 sprintf(buf, "Warning: This host is on a private subnet.");
310 sprintf(buf, "Billing information shown is superseded by billing information for the subnet.");
318 /* Function Name: PrintMachine
319 * Description: Prints the name of a machine record
320 * Arguments: info - array of information about the machine.
324 static void PrintMachine(char **info)
328 sprintf(buf, "Machine: %s", info[M_NAME]);
332 /* Function Name: PrintCname
333 * Description: Prints the Data on a host alias
334 * Arguments: info a pointer to the data array.
335 * Returns: The name of the alias.
338 static char *PrintCname(char **info)
342 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
347 /* Function Name: PrintClusterInfo
348 * Description: This function Prints out the cluster info
349 * in a coherent form.
350 * Arguments: info - array of information about a cluster.
351 * Returns: The name of the cluster.
354 static char *PrintClusterInfo(char **info)
359 sprintf(buf, "Cluster: %s", info[C_NAME]);
361 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
363 sprintf(buf, "Location: %s", info[C_LOCATION]);
365 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
370 /* Function Name: PrintClusterData
371 * Description: Prints the Data on a cluster
372 * Arguments: info a pointer to the data array.
373 * Returns: The name of the cluster.
376 static char *PrintClusterData(char **info)
381 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
382 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
384 return info[CD_NAME];
387 /* Function Name: PrintMCMap
388 * Description: Prints the data about a machine to cluster mapping.
389 * Arguments: info a pointer to the data array.
393 static char *PrintMCMap(char **info)
396 sprintf(buf, "Cluster: %-30s Machine: %-20s",
397 info[MAP_CLUSTER], info[MAP_MACHINE]);
399 return ""; /* Used by QueryLoop(). */
402 /* Function Name: PrintSubnetInfo
403 * Description: This function Prints out the subnet info
404 * in a coherent form.
405 * Arguments: info - array of information about a subnet.
406 * Returns: The name of the subnet.
409 static char *PrintSubnetInfo(char **info)
412 struct in_addr addr, mask, low, high;
415 sprintf(buf, " Network: %s", info[SN_NAME]);
417 sprintf(buf, " Description: %s", info[SN_DESC]);
419 sprintf(buf, " Status: %s", SubnetState(atoi(info[SN_STATUS])));
421 sprintf(buf, " Contact: %s", info[SN_CONTACT]);
423 sprintf(buf, " Account Number: %s", info[SN_ACCT_NUMBER]);
425 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
426 mask.s_addr = htonl(atoi(info[SN_MASK]));
427 low.s_addr = htonl(atoi(info[SN_LOW]));
428 high.s_addr = htonl(atoi(info[SN_HIGH]));
429 /* screwy sequence is here because inet_ntoa returns a pointer to
430 a static buf. If it were all one sprintf, the last value would
432 sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr));
433 strcat(buf, inet_ntoa(mask));
434 strcat(buf, "\n High: ");
435 strcat(buf, inet_ntoa(high));
436 strcat(buf, " Low: ");
437 strcat(buf, inet_ntoa(low));
439 sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
441 sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE],
442 strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : "");
444 sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]);
446 return info[SN_NAME];
449 /* Function Name: GetMCInfo.
450 * Description: This function stores info about a machine.
451 * type - type of data we are trying to retrieve.
452 * name1 - the name of argv[0] for the call.
453 * name2 - the name of argv[1] for the call.
454 * Returns: the top element of a queue containing the data or NULL.
457 struct mqelem *GetMCInfo(int type, char *name1, char *name2)
460 struct mqelem *elem = NULL;
467 args[1] = args[2] = args[3] = "*";
468 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
470 if (stat == MR_NO_MATCH)
473 sprintf(buf, "Machine '%s' is not in the database.", name1);
477 com_err(program_name, stat, " in get_machine.");
484 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
486 com_err(program_name, stat, " in get_hostalias.");
491 if ((stat = do_mr_query("get_subnet", 1, &name1, StoreInfo, &elem)))
493 if (stat == MR_NO_MATCH)
496 sprintf(buf, "Network '%s' is not in the database.", name1);
500 com_err(program_name, stat, " in get_subnet.");
505 if ((stat = do_mr_query("get_cluster", 1, &name1, StoreInfo, &elem)))
507 com_err(program_name, stat, " in get_cluster.");
512 args[MAP_MACHINE] = name1;
513 args[MAP_CLUSTER] = name2;
514 if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args,
517 com_err(program_name, stat, " in get_machine_to_cluster_map.");
522 args[CD_NAME] = name1;
523 args[CD_LABEL] = name2;
524 if ((stat = do_mr_query("get_cluster_data", 2, args, StoreInfo, &elem)))
526 com_err(program_name, stat, " in get_cluster_data.");
531 args[CON_NAME] = name1;
532 if ((stat = do_mr_query("get_container", 1, &name1, StoreInfo, &elem)))
534 com_err(program_name, stat, " in get_container.");
540 if ((stat = do_mr_query("get_machine_to_container_map", 1, &name1,
543 com_err(program_name, stat, " in get_machine_to_container_map.");
547 return QueueTop(elem);
550 /* Function Name: AskMCDInfo.
551 * Description: This function askes the user for information about a
552 * machine and saves it into a structure.
553 * Arguments: info - a pointer the information to ask about
554 * type - type of information - MACHINE
558 * name - T/F : change the name of this type.
562 char **AskMCDInfo(char **info, int type, Bool name)
564 char temp_buf[BUFSIZ], *newname, *oldnewname;
569 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
573 sprintf(temp_buf, "Setting the information for the Network %s...",
577 sprintf(temp_buf, "Setting the information for the Cluster %s...",
581 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
585 sprintf(temp_buf, "Setting the Data for the Container %s...",
589 Put_message(temp_buf);
596 newname = strdup(info[M_NAME]);
597 if (GetValueFromUser("The new name for this machine? ", &newname) ==
600 oldnewname = strdup(newname);
601 newname = canonicalize_hostname(newname);
602 if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
604 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
605 oldnewname, newname);
606 Put_message(temp_buf);
611 newname = strdup(info[SN_NAME]);
612 if (GetValueFromUser("The new name for this network? ", &newname) ==
617 newname = strdup(info[C_NAME]);
618 if (GetValueFromUser("The new name for this cluster? ", &newname) ==
623 newname = strdup(info[CON_NAME]);
624 if (GetValueFromUser("The new name for this container? ", &newname)
629 Put_message("Unknown type in AskMCDInfo, programmer botch");
637 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
639 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
641 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
644 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
646 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
649 if (GetValueFromUser("Machine's billing contact",
650 &info[M_BILL_CONTACT]) == SUB_ERROR)
652 if (GetValueFromUser("Machine's billing account number",
653 &info[M_ACCT_NUMBER]) == SUB_ERROR)
658 if (GetValueFromUser("Machine's status (? for help)",
659 &info[M_STAT]) == SUB_ERROR)
661 if (isdigit(info[M_STAT][0]))
663 Put_message("Valid status numbers:");
664 for (i = 0; i < 4; i++)
665 Put_message(states[i]);
668 /* there appears to be some argument mismatch between the client
669 * and the server.. so here is this argument shuffler.
670 * I have since modified this to always shuffle the arguments..
671 * not just do so when performing a modify all fields request.
672 * The SetMachinedefaults() has been changed to reflect this.
673 * pray for us and may we attain enlightenment through structures.
678 /* info did not come from SetMachineDefaults(), which does not
679 * initialize entry 10 (M_STAT_CHNG), therefore we can
682 /* This is an update of an existing machine and the structure
683 * was filled in thru a query to the db which does fill in this
689 info[10] = info[M_SUBNET];
690 info[11] = info[M_ADDR];
691 info[12] = info[M_OWNER_TYPE];
692 info[13] = info[M_OWNER_NAME];
693 info[14] = info[M_ACOMMENT];
694 info[15] = info[M_OCOMMENT];
698 if (GetValueFromUser("Machine's network (or 'none')", &info[10])
702 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
703 &info[11]) == SUB_ERROR)
705 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[12]) ==
708 if (strcmp(info[12], "NONE") &&
709 GetValueFromUser("Owner's Name", &info[13]) == SUB_ERROR)
711 if (!strcmp(info[12], "KERBEROS"))
715 mrcl_validate_kerberos_member(info[13], &canon);
716 if (mrcl_get_message())
717 Put_message(mrcl_get_message());
721 if (GetValueFromUser("Administrative comment", &info[14]) == SUB_ERROR)
723 if (GetValueFromUser("Operational comment", &info[15]) == SUB_ERROR)
726 FreeAndClear(&info[17], TRUE);
727 FreeAndClear(&info[18], TRUE);
730 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
735 if (GetValueFromUser("Network's status (? for help)",
736 &info[SN_STATUS]) == SUB_ERROR)
738 if (isdigit(info[SN_STATUS][0]))
740 Put_message("Valid status numbers:");
741 for (i = 0; i < 9; i++)
742 Put_message(subnet_states[i]);
744 if (GetValueFromUser("Network's contact", &info[SN_CONTACT]) == SUB_ERROR)
746 if (GetValueFromUser("Network's billing account number",
747 &info[SN_ACCT_NUMBER]) == SUB_ERROR)
749 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
751 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
753 if (atoi(info[SN_LOW]) == (int)ntohl(inet_addr(S_DEFAULT_LOW)))
756 unsigned long mask, addr;
758 addr = atoi(info[SN_ADDRESS]);
759 mask = atoi(info[SN_MASK]);
760 low.s_addr = atoi(info[SN_LOW]);
761 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
763 sprintf(temp_buf, "%ld", low.s_addr);
764 info[SN_LOW] = strdup(temp_buf);
766 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
769 if (atoi(info[SN_HIGH]) == (int)ntohl(inet_addr(S_DEFAULT_HIGH)))
772 unsigned long mask, addr;
774 addr = atoi(info[SN_ADDRESS]);
775 mask = atoi(info[SN_MASK]);
776 high.s_addr = atoi(info[SN_HIGH]);
777 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
779 sprintf(temp_buf, "%ld", high.s_addr);
780 info[SN_HIGH] = strdup(temp_buf);
782 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
785 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
787 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
790 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
791 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
793 if (!strcmp(info[SN_ACE_TYPE], "KERBEROS"))
797 mrcl_validate_kerberos_member(info[SN_ACE_NAME], &canon);
798 if (mrcl_get_message())
799 Put_message(mrcl_get_message());
800 free(info[SN_ACE_NAME]);
801 info[SN_ACE_NAME] = canon;
803 FreeAndClear(&info[SN_MODTIME], TRUE);
804 FreeAndClear(&info[SN_MODBY], TRUE);
805 FreeAndClear(&info[SN_MODWITH], TRUE);
808 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
811 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
814 FreeAndClear(&info[C_MODTIME], TRUE);
815 FreeAndClear(&info[C_MODBY], TRUE);
816 FreeAndClear(&info[C_MODWITH], TRUE);
819 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
822 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
826 if (GetYesNoValueFromUser("Is this a public container",
827 &info[CON_PUBLIC]) == SUB_ERROR)
829 if (GetValueFromUser("Container's Description:", &info[CON_DESCRIPT]) ==
832 if (GetValueFromUser("Container's Location:", &info[CON_LOCATION]) ==
835 if (GetValueFromUser("Container's Contact:", &info[CON_CONTACT]) ==
838 if (GetTypeFromUser("Container's owner type", "ace_type",
839 &info[CON_OWNER_TYPE]) == SUB_ERROR)
841 if (strcmp(info[CON_OWNER_TYPE], "NONE") &&
842 GetValueFromUser("Owner's Name", &info[CON_OWNER_NAME]) == SUB_ERROR)
844 if (!strcmp(info[CON_OWNER_TYPE], "KERBEROS"))
848 mrcl_validate_kerberos_member(info[CON_OWNER_NAME], &canon);
849 if (mrcl_get_message())
850 Put_message(mrcl_get_message());
851 free(info[CON_OWNER_NAME]);
852 info[CON_OWNER_NAME] = canon;
854 if (GetTypeFromUser("Container's Membership ACL", "ace_type",
855 &info[CON_MEMACE_TYPE]) == SUB_ERROR)
857 if (strcmp(info[CON_MEMACE_TYPE], "NONE") &&
858 GetValueFromUser("Membership ACL", &info[CON_MEMACE_NAME])
861 if (!strcmp(info[CON_MEMACE_TYPE], "KERBEROS"))
865 mrcl_validate_kerberos_member(info[CON_MEMACE_NAME], &canon);
866 if (mrcl_get_message())
867 Put_message(mrcl_get_message());
868 free(info[CON_MEMACE_NAME]);
869 info[CON_MEMACE_NAME] = canon;
871 FreeAndClear(&info[CON_MODTIME], TRUE);
872 FreeAndClear(&info[CON_MODBY], TRUE);
873 FreeAndClear(&info[CON_MODWITH], TRUE);
878 * Slide the newname into the #2 slot, this screws up all future references
882 SlipInNewName(info, newname);
887 /* ----------- Machine Menu ----------- */
889 /* Function Name: ShowMachineInfo
890 * Description: This function shows the information about a machine.
891 * Arguments: argc, argv - the name of the machine in argv[1].
892 * Returns: DM_NORMAL.
895 int ShowMachineInfo(int argc, char **argv)
900 tmpname = canonicalize_hostname(strdup(argv[1]));
901 top = GetMCInfo(MACHINE, tmpname, NULL);
902 Loop(top, ((void (*)(char **)) PrintMachInfo));
907 /* Function Name: ShowMachineQuery
908 * Description: This function shows the information about a machine.
909 * or group of machines, which may be selected through a
910 * number of criteria.
911 * Arguments: argc, argv - the name of the machine in argv[1],
912 * the address of the machine in argv[2],
913 * the location of the machine in argv[3],
914 * and the contact name in argv[4].
915 * any of these may be wildcards.
916 * Returns: DM_NORMAL.
919 int ShowMachineQuery(int argc, char **argv)
922 struct mqelem *top, *elem = NULL;
925 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
926 !strcmp(argv[3], "") && !strcmp(argv[4], ""))
928 Put_message("You must specify at least one parameter of the query.");
933 args[0] = canonicalize_hostname(strdup(argv[1]));
949 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
951 if (stat == MR_NO_MATCH)
952 Put_message("No machine(s) found matching query in the database.");
954 com_err(program_name, stat, " in get_machine.");
957 top = QueueTop(elem);
958 Loop(top, ((void (*)(char **)) PrintMachInfo));
963 /* Function Name: AddMachine
964 * Description: This function adds a new machine to the database.
965 * Arguments: argc, argv - the name of the network in argv[1].
966 * Returns: DM_NORMAL.
969 int AddMachine(int argc, char **argv)
971 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
973 struct mqelem *elem = NULL;
976 if (!ValidName(argv[1])) /* Checks for wildcards. */
980 * get the network record
983 if (strcasecmp(argv[1], "none") &&
984 (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem)))
986 if (stat == MR_NO_MATCH)
989 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
992 com_err(program_name, stat, " in get_subnet.");
997 * Check to see if this machine already exists.
1000 name = strdup(""); /* want to put prefix here */
1001 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
1004 name = canonicalize_hostname(strdup(name));
1007 xargs[1] = xargs[2] = xargs[3] = "*";
1008 if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL)))
1010 sprintf(buf, "The machine '%s' already exists.", name);
1015 else if (stat != MR_NO_MATCH)
1017 com_err(program_name, stat,
1018 " while checking machine '%s' in AddMachine.", name);
1022 rinfo = SetMachineDefaults(info, name);
1023 rinfo[M_SUBNET] = strdup(argv[1]);
1024 if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
1026 Put_message("Aborted.");
1031 * Actually create the new Machine.
1034 if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL)))
1035 com_err(program_name, stat, " in AddMachine.");
1042 /* Function Name: RealUpdateMachine
1043 * Description: Performs the actual update of the machine data.
1044 * Arguments: info - the information on the machine to update.
1045 * junk - an UNUSED Boolean.
1049 static void RealUpdateMachine(char **info, Bool junk)
1052 char **args = AskMCDInfo(info, MACHINE, TRUE);
1055 Put_message("Aborted.");
1058 if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL)))
1059 com_err(program_name, stat, " in UpdateMachine.");
1061 Put_message("Machine successfully updated.");
1064 /* Function Name: UpdateMachine
1065 * Description: This function adds a new machine to the database.
1066 * Arguments: argc, argv - the name of the machine in argv[1].
1067 * Returns: DM_NORMAL.
1070 int UpdateMachine(int argc, char **argv)
1075 tmpname = canonicalize_hostname(strdup(argv[1]));
1076 top = GetMCInfo(MACHINE, tmpname, NULL);
1077 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
1084 /* Function Name: CheckAndRemoveFromCluster
1085 * Description: This func tests to see if a machine is in a cluster.
1086 * and if so then removes it
1087 * Arguments: name - name of the machine (already Canonicalized).
1088 * ask_user- query the user before removing if from clusters?
1089 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
1092 int CheckAndRemoveFromCluster(char *name, Bool ask_user)
1094 int stat, ret_value;
1096 char *args[10], temp_buf[BUFSIZ], *ptr;
1097 struct mqelem *top, *elem = NULL;
1099 ret_value = SUB_NORMAL; /* initialize ret_value. */
1102 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1103 if (stat && stat != MR_NO_MATCH)
1105 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1108 if (stat == MR_SUCCESS)
1110 elem = top = QueueTop(elem);
1113 sprintf(temp_buf, "%s is assigned to the following clusters.", name);
1114 Put_message(temp_buf);
1115 Loop(top, (void (*)(char **)) PrintMCMap);
1116 ptr = "Remove this machine from ** ALL ** these clusters?";
1117 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1121 Put_message("Aborting...");
1133 char **info = elem->q_data;
1134 if ((stat = do_mr_query("delete_machine_from_cluster",
1135 2, info, NULL, NULL)))
1137 ret_value = SUB_ERROR;
1138 com_err(program_name, stat,
1139 " in delete_machine_from_cluster.");
1141 "Machine %s ** NOT ** removed from cluster %s.",
1142 info[MAP_MACHINE], info[MAP_CLUSTER]);
1143 Put_message(temp_buf);
1145 elem = elem->q_forw;
1152 /* Function Name: CheckAndRemoveCnames
1153 * Description: This func tests to see if a machine has cnames,
1154 * and if so then removes them.
1155 * Arguments: name - name of the machine (already Canonicalized).
1156 * ask_user- query the user before removing cnames?
1157 * Returns: MR_ERROR if machine left with a cname, or mr_error.
1160 int CheckAndRemoveCnames(char *name, Bool ask_user)
1162 int stat, ret_value;
1164 char *args[10], temp_buf[BUFSIZ], *ptr;
1165 struct mqelem *top, *elem = NULL;
1167 ret_value = SUB_NORMAL;
1170 stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem);
1171 if (stat && stat != MR_NO_MATCH)
1173 com_err(program_name, stat, " in get_hostalias.");
1176 if (stat == MR_SUCCESS)
1178 elem = top = QueueTop(elem);
1181 sprintf(temp_buf, "%s has the following cnames.", name);
1182 Put_message(temp_buf);
1183 Loop(top, (void (*)(char **)) PrintCname);
1184 ptr = "Remove ** ALL ** these cnames?";
1185 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1189 Put_message("Aborting...");
1201 char **info = elem->q_data;
1202 if ((stat = do_mr_query("delete_hostalias", 2, info,
1205 ret_value = SUB_ERROR;
1206 com_err(program_name, stat, " in delete_hostalias.");
1208 "Cname %s ** NOT ** removed from host %s.",
1210 Put_message(temp_buf);
1212 elem = elem->q_forw;
1219 /* Function Name: RealDeleteMachine
1220 * Description: Actually Deletes the Machine.
1221 * Arguments: info - nescessary information stored as an array of char *'s
1222 * one_machine - a boolean, true if there is only one item in
1227 static void RealDeleteMachine(char **info, Bool one_machine)
1230 char temp_buf[BUFSIZ];
1232 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
1234 if (!one_machine || Confirm(temp_buf))
1236 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
1238 if (CheckAndRemoveCnames(info[M_NAME], TRUE) != SUB_ERROR)
1240 if ((stat = do_mr_query("delete_host", 1,
1241 &info[M_NAME], NULL, NULL)))
1243 com_err(program_name, stat, " in DeleteMachine.");
1244 sprintf(temp_buf, "%s ** NOT ** deleted.",
1246 Put_message(temp_buf);
1250 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
1251 Put_message(temp_buf);
1258 /* Function Name: DeleteMachine
1259 * Description: This function removes a machine from the data base.
1260 * Arguments: argc, argv - the machines name int argv[1].
1261 * Returns: DM_NORMAL.
1264 /* Perhaps we should remove the cluster if it has no machine now. */
1266 int DeleteMachine(int argc, char **argv)
1271 tmpname = canonicalize_hostname(strdup(argv[1]));
1272 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
1273 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
1280 /* Function Name: ShowCname
1281 * Description: This function shows machine aliases
1282 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1283 * Returns: DM_NORMAL.
1286 int ShowCname(int argc, char **argv)
1289 char *tmpalias, *tmpname;
1291 tmpalias = partial_canonicalize_hostname(strdup(argv[1]));
1292 tmpname = canonicalize_hostname(strdup(argv[2]));
1293 top = GetMCInfo(CNAME, tmpalias, tmpname);
1294 Put_message(""); /* blank line on screen */
1295 Loop(top, ((void (*)(char **)) PrintCname));
1301 int AddCname(int argc, char **argv)
1306 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1307 args[1] = canonicalize_hostname(strdup(argv[2]));
1308 stat = do_mr_query("add_hostalias", 2, args, NULL, NULL);
1314 Put_message("That alias name is already in use.");
1317 Put_message("Permission denied. "
1318 "(Regular users can only add two aliases to a host.");
1321 com_err(program_name, stat, " in add_hostalias");
1327 int DeleteCname(int argc, char **argv)
1332 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1333 args[1] = canonicalize_hostname(strdup(argv[2]));
1334 stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL);
1336 com_err(program_name, stat, " in delete_hostalias");
1341 /* Function Name: AddMachineToCluster
1342 * Description: This function adds a machine to a cluster
1343 * Arguments: argc, argv - The machine name is argv[1].
1344 * The cluster name in argv[2].
1345 * Returns: DM_NORMAL.
1348 int AddMachineToCluster(int argc, char **argv)
1351 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1352 Bool add_it, one_machine, one_cluster;
1353 struct mqelem *melem, *mtop, *celem, *ctop;
1355 machine = canonicalize_hostname(strdup(argv[1]));
1356 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1358 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1360 Put_message(temp_buf);
1364 celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1365 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1368 one_machine = (QueueCount(mtop) == 1);
1369 one_cluster = (QueueCount(ctop) == 1);
1371 /* No good way to use QueryLoop() here, sigh */
1375 char **minfo = melem->q_data;
1378 char **cinfo = celem->q_data;
1379 if (one_machine && one_cluster)
1383 sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1384 minfo[M_NAME], cinfo[C_NAME]);
1385 switch (YesNoQuitQuestion(temp_buf, FALSE))
1394 Put_message("Aborting...");
1402 args[0] = minfo[M_NAME];
1403 args[1] = cinfo[C_NAME];
1404 stat = do_mr_query("add_machine_to_cluster", 2, args,
1411 sprintf(temp_buf, "%s is already in cluster %s",
1412 minfo[M_NAME], cinfo[C_NAME]);
1413 Put_message(temp_buf);
1416 com_err(program_name, stat, " in AddMachineToCluster.");
1420 celem = celem->q_forw;
1422 celem = ctop; /* reset cluster element. */
1423 melem = melem->q_forw;
1430 /* Function Name: RealRemoveMachineFromCluster
1431 * Description: This function actually removes the machine from its
1433 * Arguments: info - all information nescessary to perform the removal.
1434 * one_map - True if there is only one case, and we should
1439 static void RealRemoveMachineFromCluster(char **info, Bool one_map)
1441 char temp_buf[BUFSIZ];
1444 sprintf(temp_buf, "Remove %s from the cluster %s",
1445 info[MAP_MACHINE], info[MAP_CLUSTER]);
1446 if (!one_map || Confirm(temp_buf))
1448 if ((stat = do_mr_query("delete_machine_from_cluster", 2,
1450 com_err(program_name, stat, " in delete_machine_from_cluster");
1453 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1454 info[MAP_MACHINE], info[MAP_CLUSTER]);
1455 Put_message(temp_buf);
1459 Put_message("Machine not removed.");
1462 /* Function Name: RemoveMachineFromCluster
1463 * Description: Removes this machine form a specific cluster.
1464 * Arguments: argc, argv - Name of machine in argv[1].
1465 * Name of cluster in argv[2].
1469 int RemoveMachineFromCluster(int argc, char **argv)
1471 struct mqelem *elem = NULL;
1472 char buf[BUFSIZ], *args[10];
1475 args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1]));
1476 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1478 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1479 argv[1], args[MAP_MACHINE]);
1482 args[MAP_CLUSTER] = argv[2];
1483 args[MAP_END] = NULL;
1485 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1487 if (stat == MR_NO_MATCH)
1489 sprintf(buf, "The machine %s is not in the cluster %s.",
1490 args[MAP_MACHINE], args[MAP_CLUSTER]);
1492 free(args[MAP_MACHINE]);
1495 if (stat != MR_SUCCESS)
1496 com_err(program_name, stat, " in delete_machine_from_cluster");
1498 elem = QueueTop(elem);
1499 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1500 "Remove this machine from this cluster");
1503 free(args[MAP_MACHINE]);
1507 /* ---------- Subnet Menu -------- */
1509 /* Function Name: ShowSubnetInfo
1510 * Description: Gets information about a subnet given its name.
1511 * Arguments: argc, argc - the name of the subnet in in argv[1].
1512 * Returns: DM_NORMAL.
1515 int ShowSubnetInfo(int argc, char **argv)
1519 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1520 Loop(top, (void (*)(char **)) PrintSubnetInfo);
1525 /* Function Name: AddSubnet
1526 * Description: Creates a new subnet.
1527 * Arguments: argc, argv - the name of the new subnet is argv[1].
1528 * Returns: DM_NORMAL.
1531 int AddSubnet(int argc, char **argv)
1533 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1537 * Check to see if this subnet already exists.
1539 if (!ValidName(name))
1542 if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS)
1544 Put_message("This subnet already exists.");
1547 else if (stat != MR_NO_MATCH)
1549 com_err(program_name, stat, " in AddSubnet.");
1552 if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1554 Put_message("Aborted.");
1560 * Actually create the new Subnet.
1562 if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL)))
1563 com_err(program_name, stat, " in AddSubnet.");
1569 /* Function Name: RealUpdateSubnet
1570 * Description: This function actually performs the subnet update.
1571 * Arguments: info - all information nesc. for updating the subnet.
1572 * junk - an UNUSED boolean.
1576 static void RealUpdateSubnet(char **info, Bool junk)
1579 char **args = AskMCDInfo(info, SUBNET, TRUE);
1582 Put_message("Aborted.");
1585 if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL)))
1586 com_err(program_name, stat, " in UpdateSubnet.");
1588 Put_message("Subnet successfully updated.");
1591 /* Function Name: UpdateSubnet
1592 * Description: This Function Updates a subnet
1593 * Arguments: name of the subnet in argv[1].
1594 * Returns: DM_NORMAL.
1597 int UpdateSubnet(int argc, char **argv)
1600 top = GetMCInfo(SUBNET, argv[1], NULL);
1601 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1607 /* Function Name: RealDeleteSubnet
1608 * Description: Actually performs the subnet deletion.
1609 * Arguments: info - all information about this subnet.
1610 * one_subnet - If true then there was only one subnet in
1611 * the queue, and we should confirm.
1615 static void RealDeleteSubnet(char **info, Bool one_subnet)
1618 char temp_buf[BUFSIZ];
1621 "Are you sure the you want to delete the subnet %s (y/n) ?",
1623 if (!one_subnet || Confirm(temp_buf))
1625 if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL)))
1627 com_err(program_name, stat, " in delete_subnet.");
1628 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1629 Put_message(temp_buf);
1633 sprintf(temp_buf, "subnet %s successfully deleted.",
1635 Put_message(temp_buf);
1640 /* Function Name: DeleteSubnet
1641 * Description: This function removes a subnet from the database.
1642 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1643 * Returns: DM_NORMAL.
1646 int DeleteSubnet(int argc, char **argv)
1650 top = GetMCInfo(SUBNET, argv[1], NULL);
1651 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1657 /* ---------- Cluster Menu -------- */
1659 /* Function Name: ShowClusterInfo
1660 * Description: Gets information about a cluser given its name.
1661 * Arguments: argc, argc - the name of the cluster in in argv[1].
1662 * Returns: DM_NORMAL.
1665 int ShowClusterInfo(int argc, char **argv)
1669 top = GetMCInfo(CLUSTER, argv[1], NULL);
1670 Loop(top, (void (*)(char **)) PrintClusterInfo);
1675 /* Function Name: AddCluster
1676 * Description: Creates a new cluster.
1677 * Arguments: argc, argv - the name of the new cluster is argv[1].
1678 * Returns: DM_NORMAL.
1681 int AddCluster(int argc, char **argv)
1683 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1687 * Check to see if this cluster already exists.
1689 if (!ValidName(name))
1692 if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS)
1694 Put_message("This cluster already exists.");
1697 else if (stat != MR_NO_MATCH)
1699 com_err(program_name, stat, " in AddCluster.");
1702 if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1704 Put_message("Aborted.");
1710 * Actually create the new Cluster.
1712 if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL)))
1713 com_err(program_name, stat, " in AddCluster.");
1719 /* Function Name: RealUpdateCluster
1720 * Description: This function actually performs the cluster update.
1721 * Arguments: info - all information nesc. for updating the cluster.
1722 * junk - an UNUSED boolean.
1726 static void RealUpdateCluster(char **info, Bool junk)
1729 char **args = AskMCDInfo(info, CLUSTER, TRUE);
1733 Put_message("Aborted.");
1736 if ((stat = do_mr_query("update_cluster", CountArgs(args),
1738 com_err(program_name, stat, " in UpdateCluster.");
1740 Put_message("Cluster successfully updated.");
1743 /* Function Name: UpdateCluster
1744 * Description: This Function Updates a cluster
1745 * Arguments: name of the cluster in argv[1].
1746 * Returns: DM_NORMAL.
1749 int UpdateCluster(int argc, char **argv)
1752 top = GetMCInfo(CLUSTER, argv[1], NULL);
1753 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1759 /* Function Name: CheckAndRemoveMachine
1760 * Description: This function checks and removes all machines from a
1762 * Arguments: name - name of the cluster.
1763 * ask_first - if TRUE, then we will query the user, before
1765 * Returns: SUB_ERROR if all machines not removed.
1768 int CheckAndRemoveMachines(char *name, Bool ask_first)
1770 int stat, ret_value;
1772 char *args[10], temp_buf[BUFSIZ], *ptr;
1773 struct mqelem *top, *elem = NULL;
1775 ret_value = SUB_NORMAL;
1776 args[MAP_MACHINE] = "*";
1777 args[MAP_CLUSTER] = name;
1778 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1779 if (stat && stat != MR_NO_MATCH)
1781 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1784 if (stat == MR_SUCCESS)
1786 elem = top = QueueTop(elem);
1789 sprintf(temp_buf, "The cluster %s has the following machines in it:",
1791 Put_message(temp_buf);
1794 char **info = elem->q_data;
1795 Print(1, &info[MAP_MACHINE], (char *) NULL);
1796 elem = elem->q_forw;
1798 ptr = "Remove ** ALL ** these machines from this cluster?";
1800 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1804 Put_message("Aborting...");
1817 char **info = elem->q_data;
1818 if ((stat = do_mr_query("delete_machine_from_cluster",
1819 2, info, NULL, NULL)))
1821 ret_value = SUB_ERROR;
1822 com_err(program_name, stat,
1823 " in delete_machine_from_cluster.");
1825 "Machine %s ** NOT ** removed from cluster %s.",
1826 info[MAP_MACHINE], info[MAP_CLUSTER]);
1827 Put_message(temp_buf);
1829 elem = elem->q_forw;
1836 /* Function Name: RealDeleteCluster
1837 * Description: Actually performs the cluster deletion.
1838 * Arguments: info - all information about this cluster.
1839 * one_cluster - If true then there was only one cluster in
1840 * the queue, and we should confirm.
1844 static void RealDeleteCluster(char **info, Bool one_cluster)
1847 char temp_buf[BUFSIZ];
1850 "Are you sure the you want to delete the cluster %s (y/n) ?",
1852 if (!one_cluster || Confirm(temp_buf))
1854 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1856 if ((stat = do_mr_query("delete_cluster", 1,
1857 &info[C_NAME], NULL, NULL)))
1859 com_err(program_name, stat, " in delete_cluster.");
1860 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1861 Put_message(temp_buf);
1865 sprintf(temp_buf, "cluster %s successfully deleted.",
1867 Put_message(temp_buf);
1873 /* Function Name: DeleteCluster
1874 * Description: This function removes a cluster from the database.
1875 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1876 * Returns: DM_NORMAL.
1879 int DeleteCluster(int argc, char **argv)
1883 top = GetMCInfo(CLUSTER, argv[1], NULL);
1884 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1890 /* ----------- Cluster Data Menu -------------- */
1892 /* Function Name: ShowClusterData
1893 * Description: This function shows the services for one cluster.
1894 * Arguments: argc, argv - The name of the cluster is argv[1].
1895 * The label of the data in argv[2].
1896 * Returns: DM_NORMAL.
1899 int ShowClusterData(int argc, char **argv)
1901 struct mqelem *elem, *top;
1904 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1907 info = elem->q_data;
1908 PrintClusterData(info);
1909 elem = elem->q_forw;
1915 /* Function Name: AddClusterData
1916 * Description: This function adds some data to the cluster.
1917 * Arguments: argv, argc: argv[1] - the name of the cluster.
1918 * argv[2] - the label of the data.
1919 * argv[3] - the data.
1920 * Returns: DM_NORMAL.
1923 int AddClusterData(int argc, char **argv)
1927 for (i = 1; i < 4; i++)
1929 if (IS_EMPTY(argv[i]))
1931 Put_message("Cluster data cannot be an empty string.");
1935 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
1936 com_err(program_name, stat, " in AddClusterData.");
1940 /* Function Name: RealRemoveClusterData
1941 * Description: actually removes the cluster data.
1942 * Arguments: info - all info necessary to remove the cluster, in an array
1944 * one_item - if true then the queue has only one elem and we
1949 static void RealRemoveClusterData(char **info, Bool one_item)
1955 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1956 PrintClusterData(info);
1957 if (!one_item || Confirm(temp_ptr))
1959 if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
1961 com_err(program_name, stat, " in DeleteClusterData.");
1962 Put_message("Data not removed.");
1965 Put_message("Removal successful.");
1969 /* Function Name: RemoveClusterData
1970 * Description: This function removes data on a given cluster.
1971 * Arguments: argv, argc: argv[1] - the name of the cluster.
1972 * argv[2] - the label of the data.
1973 * argv[3] - the data.
1974 * Returns: DM_NORMAL.
1977 int RemoveClusterData(int argc, char **argv)
1981 top = GetMCInfo(DATA, argv[1], argv[2]);
1982 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1983 "Remove data from cluster");
1989 /* Function Name: MachineToClusterMap
1990 * Description: This Retrieves the mapping between machine and cluster
1991 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1992 * argv[2] -> cluster name or wildcard.
1996 int MachineToClusterMap(int argc, char **argv)
1998 struct mqelem *elem, *top;
1999 char *tmpname, temp_buf[256];
2001 tmpname = canonicalize_hostname(strdup(argv[1]));
2002 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2004 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2006 Put_message(temp_buf);
2008 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
2010 Put_message(""); /* blank line on screen */
2013 char **info = elem->q_data;
2015 elem = elem->q_forw;
2023 /* Function Name: MachineByOwner
2024 * Description: This function prints all machines which are owned by
2025 * a given user or group.
2027 * Returns: DM_NORMAL.
2030 int MachineByOwner(int argc, char **argv)
2032 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
2035 type = strdup("USER");
2036 if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR)
2039 sprintf(buf, "Name of %s", type);
2040 name = strdup(user);
2041 if (GetValueFromUser(buf, &name) == SUB_ERROR)
2044 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
2047 sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */
2049 type = strdup(temp_buf);
2057 top = GetMachineByOwner(type, name);
2058 Loop(top, PrintMachine);
2064 /* Function Name: GetMachineByOwner
2065 * Description: This function stores information retrieved by
2066 * the get_host_by_owner query
2067 * Arguments: type - an ace_type, argv[0] for the query
2068 * name - name of machine, argv[1] for the query
2069 * Returns: the top element of a queue returning the data, or NULL.
2072 struct mqelem *GetMachineByOwner(char *type, char *name)
2075 struct mqelem *elem = NULL;
2080 if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem)))
2082 com_err(program_name, status, " in get_host_by_owner");
2085 return QueueTop(elem);
2088 int MachineByAcctNumber(int argc, char **argv)
2090 char *args[1], *account_number;
2092 struct mqelem *elem = NULL;
2094 account_number = strdup("");
2095 if (GetValueFromUser("Account Number", &account_number) == SUB_ERROR)
2098 args[0] = account_number;
2099 if (status = do_mr_query("get_host_by_account_number", 1, args, StoreInfo,
2102 com_err(program_name, status, " in get_host_by_account_number");
2105 Loop(QueueTop(elem), (void (*)(char **)) PrintMachInfo);
2111 int ShowContainerInfo(int argc, char **argv)
2115 top = GetMCInfo(CONTAINER, argv[1], NULL);
2116 Loop(top, (void (*)(char **)) PrintContainerInfo);
2121 static char *PrintContainerInfo(char **info)
2123 char buf[BUFSIZ], tbuf[256];
2125 struct mqelem *elem = NULL;
2129 sprintf(buf, "Container: %-16s Public: %s", info[CON_NAME],
2130 atoi(info[CON_PUBLIC]) ? "Yes" : "No");
2132 /* Do a get_container_list to see what the associated list is. */
2133 args[0] = info[CON_NAME];
2134 if (stat = do_mr_query("get_container_list", 1, args, StoreInfo, &elem))
2136 if (stat != MR_NO_MATCH)
2137 com_err(program_name, stat, " looking up container list");
2141 sprintf(buf, "Container's associated list is: LIST %s",
2142 ((char **)elem->q_data)[1]);
2146 sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]);
2148 sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION],
2151 sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE],
2152 strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : "");
2153 sprintf(buf, "Owner: %-16s", tbuf);
2155 sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE],
2156 strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : "");
2157 sprintf(buf, "Membership ACL: %-16s", tbuf);
2160 sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME],
2163 return(info[CON_NAME]);
2166 static char *PrintContainer(char **info)
2170 sprintf(buf, "Container: %s", info[CON_NAME]);
2175 static char *PrintMContMap(char **info)
2178 sprintf(buf, "Container: %-30s Machine: %-20s",
2184 int AddContainer(int argc, char **argv)
2186 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
2189 /* Can't use ValidName() because spaces are allowed in container names */
2192 Put_message("Please use a non-empty name.");
2196 if (strchr(name, '*') || strchr(name, '?'))
2198 Put_message("Wildcards not accepted here.");
2202 /* Check if this cluster already exists. */
2203 if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL))
2206 Put_message("This container already exists.");
2209 else if (stat != MR_NO_MATCH)
2211 com_err(program_name, stat, " in AddContainer.");
2214 if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE)))
2216 Put_message("Aborted.");
2221 /* Create the new container. */
2222 if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL)))
2223 com_err(program_name, stat, " in AddContainer.");
2229 int UpdateContainer(int argc, char **argv)
2232 top = GetMCInfo(CONTAINER, argv[1], NULL);
2233 QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container");
2239 static void RealUpdateContainer(char **info, Bool junk)
2242 char **args = AskMCDInfo(info, CONTAINER, TRUE);
2246 Put_message("Aborted.");
2249 if ((stat = do_mr_query("update_container", CountArgs(args), args,
2251 com_err(program_name, stat, " in UpdateContainer.");
2253 Put_message("Container successfully updated.");
2256 int DeleteContainer(int argc, char **argv)
2260 top = GetMCInfo(CONTAINER, argv[1], NULL);
2261 QueryLoop(top, PrintClusterInfo, RealDeleteContainer,
2262 "Delete the container");
2268 static void RealDeleteContainer(char **info, Bool one_container)
2271 char temp_buf[BUFSIZ];
2274 "Are you sure you want to delete the container %s (y/n) ?",
2276 if (!one_container || Confirm(temp_buf))
2278 if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE)
2281 if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME],
2284 com_err(program_name, stat, " in delete_container.");
2285 sprintf(temp_buf, "Container %s ** NOT ** deleted.",
2287 Put_message(temp_buf);
2291 sprintf(temp_buf, "Container %s successfully deleted.",
2293 Put_message(temp_buf);
2299 int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first)
2301 int stat, ret_value;
2303 char *args[10], temp_buf[BUFSIZ], *ptr;
2304 struct mqelem *top, *elem = NULL;
2306 ret_value = SUB_NORMAL;
2309 stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo,
2311 if (stat && stat != MR_NO_MATCH)
2313 com_err(program_name, stat, " in get_machines_of_container");
2316 if (stat == MR_SUCCESS)
2318 elem = top = QueueTop(elem);
2322 "The container %s has the following machines in it:", name);
2323 Put_message(temp_buf);
2326 char **info = elem->q_data;
2327 Print(1, &info[0], (char *) NULL);
2328 elem = elem->q_forw;
2330 ptr = "Remove ** ALL ** these machines from this container?";
2332 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
2336 Put_message("Aborting...");
2349 char **info = elem->q_data;
2350 if ((stat = do_mr_query("delete_machine_from_container",
2351 2, info, NULL, NULL)))
2353 ret_value = SUB_ERROR;
2354 com_err(program_name, stat,
2355 " in delete_machine_from_container.");
2357 "Machine %s ** NOT ** removed from container %s.",
2359 Put_message(temp_buf);
2361 elem = elem->q_forw;
2368 int GetSubContainers(int argc, char **argv)
2371 struct mqelem *elem = NULL, *top = NULL;
2376 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2381 if (stat = do_mr_query("get_subcontainers_of_container", 2, args,
2383 com_err(program_name, stat, " in get_subcontainers_of_container");
2385 top = QueueTop(elem);
2386 Loop(top, ((void (*)(char **)) PrintContainer));
2391 int MachineToContainerMap(int argc, char **argv)
2393 struct mqelem *elem, *top;
2394 char *tmpname, temp_buf[256];
2396 tmpname = canonicalize_hostname(strdup(argv[1]));
2397 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2399 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2401 Put_message(temp_buf);
2403 top = elem = GetMCInfo(CONTMAP, tmpname, NULL);
2408 char **info = elem->q_data;
2409 PrintMContMap(info);
2410 elem = elem->q_forw;
2418 int AddMachineToContainer(int argc, char **argv)
2421 char *machine, *container, temp_buf[BUFSIZ], *args[10];
2422 Bool add_it, one_machine, one_container;
2423 struct mqelem *melem, *mtop, *celem, *ctop;
2425 machine = canonicalize_hostname(strdup(argv[1]));
2426 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
2428 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2430 Put_message(temp_buf);
2432 container = argv[2];
2434 celem = ctop = GetMCInfo(CONTAINER, container, NULL);
2435 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
2438 one_machine = (QueueCount(mtop) == 1);
2439 one_container = (QueueCount(ctop) == 1);
2443 char **minfo = melem->q_data;
2446 char **cinfo = celem->q_data;
2447 if (one_machine && one_container)
2451 sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?",
2452 minfo[M_NAME], cinfo[CON_NAME]);
2453 switch (YesNoQuestion(temp_buf, FALSE))
2462 Put_message("Aborting...");
2470 args[0] = minfo[M_NAME];
2471 args[1] = cinfo[CON_NAME];
2472 stat = do_mr_query("add_machine_to_container", 2, args, NULL,
2479 sprintf(temp_buf, "%s is already in container %s",
2480 minfo[M_NAME], cinfo[CON_NAME]);
2481 Put_message(temp_buf);
2484 com_err(program_name, stat, " in AddMachineToContainer.");
2488 celem = celem->q_forw;
2491 melem = melem->q_forw;
2498 int RemoveMachineFromContainer(int argc, char **argv)
2500 struct mqelem *elem = NULL;
2501 char buf[BUFSIZ], *args[10];
2504 args[0] = canonicalize_hostname(strdup(argv[1]));
2505 if (strcasecmp(args[0], argv[1]) && *argv[1] != '"')
2507 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
2514 stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo,
2516 if (stat == MR_NO_MATCH)
2518 sprintf(buf, "The machine %s is not in the container %s.",
2524 if (stat != MR_SUCCESS)
2525 com_err(program_name, stat, " in deleter_machine_from_container");
2527 elem = QueueTop(elem);
2528 QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer,
2529 "Remove this machine from this container");
2536 static void RealRemoveMachineFromContainer(char **info, Bool one_contmap)
2538 char temp_buf[BUFSIZ];
2541 sprintf(temp_buf, "Remove %s from the container %s",
2543 if (!one_contmap || Confirm(temp_buf))
2545 if ((stat = do_mr_query("delete_machine_from_container", 2,
2547 com_err(program_name, stat, " in delete_machine_from_container");
2550 sprintf(temp_buf, "%s has been removed from the container %s.",
2552 Put_message(temp_buf);
2556 Put_message("Machine not removed.");
2559 int GetMachinesOfContainer(int argc, char **argv)
2562 struct mqelem *elem = NULL, *top = NULL;
2567 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2572 if (stat = do_mr_query("get_machines_of_container", 2, args,
2574 com_err(program_name, stat, " in get_machines_of_container");
2576 top = QueueTop(elem);
2577 Loop(top, ((void (*)(char **)) PrintMContMap));
2582 int GetTopLevelCont(int argc, char **argv)
2585 struct mqelem *elem = NULL;
2586 if (status = do_mr_query("get_toplevel_containers", 0, NULL, StoreInfo,
2589 com_err(program_name, status, " in get_toplevel_containers");
2592 Loop(QueueTop(elem), (void(*)(char **)) PrintContainer);