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;
570 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
574 sprintf(temp_buf, "Setting the information for the Network %s...",
578 sprintf(temp_buf, "Setting the information for the Cluster %s...",
582 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
586 sprintf(temp_buf, "Setting the Data for the Container %s...",
590 Put_message(temp_buf);
597 newname = strdup(info[M_NAME]);
598 if (GetValueFromUser("The new name for this machine? ", &newname) ==
601 oldnewname = strdup(newname);
602 newname = canonicalize_hostname(newname);
603 if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
605 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
606 oldnewname, newname);
607 Put_message(temp_buf);
612 newname = strdup(info[SN_NAME]);
613 if (GetValueFromUser("The new name for this network? ", &newname) ==
618 newname = strdup(info[C_NAME]);
619 if (GetValueFromUser("The new name for this cluster? ", &newname) ==
624 newname = strdup(info[CON_NAME]);
625 if (GetValueFromUser("The new name for this container? ", &newname)
630 Put_message("Unknown type in AskMCDInfo, programmer botch");
638 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
640 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
642 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
645 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
647 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
650 if (GetValueFromUser("Machine's billing contact",
651 &info[M_BILL_CONTACT]) == SUB_ERROR)
653 if (GetValueFromUser("Machine's billing account number",
654 &info[M_ACCT_NUMBER]) == SUB_ERROR)
659 if (GetValueFromUser("Machine's status (? for help)",
660 &info[M_STAT]) == SUB_ERROR)
662 if (isdigit(info[M_STAT][0]))
664 Put_message("Valid status numbers:");
665 for (i = 0; i < 4; i++)
666 Put_message(states[i]);
669 /* there appears to be some argument mismatch between the client
670 * and the server.. so here is this argument shuffler.
671 * I have since modified this to always shuffle the arguments..
672 * not just do so when performing a modify all fields request.
673 * The SetMachinedefaults() has been changed to reflect this.
674 * pray for us and may we attain enlightenment through structures.
679 /* info did not come from SetMachineDefaults(), which does not
680 * initialize entry 10 (M_STAT_CHNG), therefore we can
683 /* This is an update of an existing machine and the structure
684 * was filled in thru a query to the db which does fill in this
690 info[10] = strdup(info[M_SUBNET]);
691 info[11] = strdup(info[M_ADDR]);
692 info[12] = strdup(info[M_OWNER_TYPE]);
693 info[13] = strdup(info[M_OWNER_NAME]);
694 info[14] = strdup(info[M_ACOMMENT]);
695 info[15] = strdup(info[M_OCOMMENT]);
699 if (GetValueFromUser("Machine's network (or 'none')", &info[10])
703 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
704 &info[11]) == SUB_ERROR)
706 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[12]) ==
709 if (strcmp(info[12], "NONE") &&
710 GetValueFromUser("Owner's Name", &info[13]) == SUB_ERROR)
712 if (!strcmp(info[12], "KERBEROS"))
716 status = mrcl_validate_kerberos_member(info[13], &canon);
717 if (mrcl_get_message())
718 Put_message(mrcl_get_message());
719 if (status == MRCL_REJECT)
724 if (GetValueFromUser("Administrative comment", &info[14]) == SUB_ERROR)
726 if (GetValueFromUser("Operational comment", &info[15]) == SUB_ERROR)
729 FreeAndClear(&info[17], TRUE);
730 FreeAndClear(&info[18], TRUE);
733 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
738 if (GetValueFromUser("Network's status (? for help)",
739 &info[SN_STATUS]) == SUB_ERROR)
741 if (isdigit(info[SN_STATUS][0]))
743 Put_message("Valid status numbers:");
744 for (i = 0; i < 9; i++)
745 Put_message(subnet_states[i]);
747 if (GetValueFromUser("Network's contact", &info[SN_CONTACT]) == SUB_ERROR)
749 if (GetValueFromUser("Network's billing account number",
750 &info[SN_ACCT_NUMBER]) == SUB_ERROR)
752 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
754 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
756 if (atoi(info[SN_LOW]) == (int)ntohl(inet_addr(S_DEFAULT_LOW)))
759 unsigned long mask, addr;
761 addr = atoi(info[SN_ADDRESS]);
762 mask = atoi(info[SN_MASK]);
763 low.s_addr = atoi(info[SN_LOW]);
764 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
766 sprintf(temp_buf, "%ld", low.s_addr);
767 info[SN_LOW] = strdup(temp_buf);
769 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
772 if (atoi(info[SN_HIGH]) == (int)ntohl(inet_addr(S_DEFAULT_HIGH)))
775 unsigned long mask, addr;
777 addr = atoi(info[SN_ADDRESS]);
778 mask = atoi(info[SN_MASK]);
779 high.s_addr = atoi(info[SN_HIGH]);
780 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
782 sprintf(temp_buf, "%ld", high.s_addr);
783 info[SN_HIGH] = strdup(temp_buf);
785 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
788 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
790 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
793 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
794 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
796 if (!strcmp(info[SN_ACE_TYPE], "KERBEROS"))
800 status = mrcl_validate_kerberos_member(info[SN_ACE_NAME], &canon);
801 if (mrcl_get_message())
802 Put_message(mrcl_get_message());
803 if (status == MRCL_REJECT)
805 free(info[SN_ACE_NAME]);
806 info[SN_ACE_NAME] = canon;
808 FreeAndClear(&info[SN_MODTIME], TRUE);
809 FreeAndClear(&info[SN_MODBY], TRUE);
810 FreeAndClear(&info[SN_MODWITH], TRUE);
813 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
816 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
819 FreeAndClear(&info[C_MODTIME], TRUE);
820 FreeAndClear(&info[C_MODBY], TRUE);
821 FreeAndClear(&info[C_MODWITH], TRUE);
824 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
827 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
831 if (GetYesNoValueFromUser("Is this a public container",
832 &info[CON_PUBLIC]) == SUB_ERROR)
834 if (GetValueFromUser("Container's Description:", &info[CON_DESCRIPT]) ==
837 if (GetValueFromUser("Container's Location:", &info[CON_LOCATION]) ==
840 if (GetValueFromUser("Container's Contact:", &info[CON_CONTACT]) ==
843 if (GetTypeFromUser("Container's owner type", "ace_type",
844 &info[CON_OWNER_TYPE]) == SUB_ERROR)
846 if (strcmp(info[CON_OWNER_TYPE], "NONE") &&
847 GetValueFromUser("Owner's Name", &info[CON_OWNER_NAME]) == SUB_ERROR)
849 if (!strcmp(info[CON_OWNER_TYPE], "KERBEROS"))
853 mrcl_validate_kerberos_member(info[CON_OWNER_NAME], &canon);
854 if (mrcl_get_message())
855 Put_message(mrcl_get_message());
856 if (status == MRCL_REJECT)
858 free(info[CON_OWNER_NAME]);
859 info[CON_OWNER_NAME] = canon;
861 if (GetTypeFromUser("Container's Membership ACL", "ace_type",
862 &info[CON_MEMACE_TYPE]) == SUB_ERROR)
864 if (strcmp(info[CON_MEMACE_TYPE], "NONE") &&
865 GetValueFromUser("Membership ACL", &info[CON_MEMACE_NAME])
868 if (!strcmp(info[CON_MEMACE_TYPE], "KERBEROS"))
872 mrcl_validate_kerberos_member(info[CON_MEMACE_NAME], &canon);
873 if (mrcl_get_message())
874 Put_message(mrcl_get_message());
875 if (status == MRCL_REJECT)
877 free(info[CON_MEMACE_NAME]);
878 info[CON_MEMACE_NAME] = canon;
880 FreeAndClear(&info[CON_MODTIME], TRUE);
881 FreeAndClear(&info[CON_MODBY], TRUE);
882 FreeAndClear(&info[CON_MODWITH], TRUE);
887 * Slide the newname into the #2 slot, this screws up all future references
891 SlipInNewName(info, newname);
896 /* ----------- Machine Menu ----------- */
898 /* Function Name: ShowMachineInfo
899 * Description: This function shows the information about a machine.
900 * Arguments: argc, argv - the name of the machine in argv[1].
901 * Returns: DM_NORMAL.
904 int ShowMachineInfo(int argc, char **argv)
909 tmpname = canonicalize_hostname(strdup(argv[1]));
910 top = GetMCInfo(MACHINE, tmpname, NULL);
911 Loop(top, ((void (*)(char **)) PrintMachInfo));
916 /* Function Name: ShowMachineQuery
917 * Description: This function shows the information about a machine.
918 * or group of machines, which may be selected through a
919 * number of criteria.
920 * Arguments: argc, argv - the name of the machine in argv[1],
921 * the address of the machine in argv[2],
922 * the location of the machine in argv[3],
923 * and the contact name in argv[4].
924 * any of these may be wildcards.
925 * Returns: DM_NORMAL.
928 int ShowMachineQuery(int argc, char **argv)
931 struct mqelem *top, *elem = NULL;
934 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
935 !strcmp(argv[3], "") && !strcmp(argv[4], ""))
937 Put_message("You must specify at least one parameter of the query.");
942 args[0] = canonicalize_hostname(strdup(argv[1]));
958 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
960 if (stat == MR_NO_MATCH)
961 Put_message("No machine(s) found matching query in the database.");
963 com_err(program_name, stat, " in get_machine.");
966 top = QueueTop(elem);
967 Loop(top, ((void (*)(char **)) PrintMachInfo));
972 /* Function Name: AddMachine
973 * Description: This function adds a new machine to the database.
974 * Arguments: argc, argv - the name of the network in argv[1].
975 * Returns: DM_NORMAL.
978 int AddMachine(int argc, char **argv)
980 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
982 struct mqelem *elem = NULL;
985 if (!ValidName(argv[1])) /* Checks for wildcards. */
989 * get the network record
992 if (strcasecmp(argv[1], "none") &&
993 (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem)))
995 if (stat == MR_NO_MATCH)
998 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
1001 com_err(program_name, stat, " in get_subnet.");
1006 * Check to see if this machine already exists.
1009 name = strdup(""); /* want to put prefix here */
1010 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
1013 name = canonicalize_hostname(strdup(name));
1016 xargs[1] = xargs[2] = xargs[3] = "*";
1017 if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL)))
1019 sprintf(buf, "The machine '%s' already exists.", name);
1024 else if (stat != MR_NO_MATCH)
1026 com_err(program_name, stat,
1027 " while checking machine '%s' in AddMachine.", name);
1031 rinfo = SetMachineDefaults(info, name);
1032 rinfo[M_SUBNET] = strdup(argv[1]);
1033 if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
1035 Put_message("Aborted.");
1040 * Actually create the new Machine.
1043 if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL)))
1044 com_err(program_name, stat, " in AddMachine.");
1051 /* Function Name: RealUpdateMachine
1052 * Description: Performs the actual update of the machine data.
1053 * Arguments: info - the information on the machine to update.
1054 * junk - an UNUSED Boolean.
1058 static void RealUpdateMachine(char **info, Bool junk)
1061 char **args = AskMCDInfo(info, MACHINE, TRUE);
1064 Put_message("Aborted.");
1067 if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL)))
1068 com_err(program_name, stat, " in UpdateMachine.");
1070 Put_message("Machine successfully updated.");
1073 /* Function Name: UpdateMachine
1074 * Description: This function adds a new machine to the database.
1075 * Arguments: argc, argv - the name of the machine in argv[1].
1076 * Returns: DM_NORMAL.
1079 int UpdateMachine(int argc, char **argv)
1084 tmpname = canonicalize_hostname(strdup(argv[1]));
1085 top = GetMCInfo(MACHINE, tmpname, NULL);
1086 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
1093 /* Function Name: CheckAndRemoveFromCluster
1094 * Description: This func tests to see if a machine is in a cluster.
1095 * and if so then removes it
1096 * Arguments: name - name of the machine (already Canonicalized).
1097 * ask_user- query the user before removing if from clusters?
1098 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
1101 int CheckAndRemoveFromCluster(char *name, Bool ask_user)
1103 int stat, ret_value;
1105 char *args[10], temp_buf[BUFSIZ], *ptr;
1106 struct mqelem *top, *elem = NULL;
1108 ret_value = SUB_NORMAL; /* initialize ret_value. */
1111 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1112 if (stat && stat != MR_NO_MATCH)
1114 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1117 if (stat == MR_SUCCESS)
1119 elem = top = QueueTop(elem);
1122 sprintf(temp_buf, "%s is assigned to the following clusters.", name);
1123 Put_message(temp_buf);
1124 Loop(top, (void (*)(char **)) PrintMCMap);
1125 ptr = "Remove this machine from ** ALL ** these clusters?";
1126 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1130 Put_message("Aborting...");
1142 char **info = elem->q_data;
1143 if ((stat = do_mr_query("delete_machine_from_cluster",
1144 2, info, NULL, NULL)))
1146 ret_value = SUB_ERROR;
1147 com_err(program_name, stat,
1148 " in delete_machine_from_cluster.");
1150 "Machine %s ** NOT ** removed from cluster %s.",
1151 info[MAP_MACHINE], info[MAP_CLUSTER]);
1152 Put_message(temp_buf);
1154 elem = elem->q_forw;
1161 /* Function Name: CheckAndRemoveCnames
1162 * Description: This func tests to see if a machine has cnames,
1163 * and if so then removes them.
1164 * Arguments: name - name of the machine (already Canonicalized).
1165 * ask_user- query the user before removing cnames?
1166 * Returns: MR_ERROR if machine left with a cname, or mr_error.
1169 int CheckAndRemoveCnames(char *name, Bool ask_user)
1171 int stat, ret_value;
1173 char *args[10], temp_buf[BUFSIZ], *ptr;
1174 struct mqelem *top, *elem = NULL;
1176 ret_value = SUB_NORMAL;
1179 stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem);
1180 if (stat && stat != MR_NO_MATCH)
1182 com_err(program_name, stat, " in get_hostalias.");
1185 if (stat == MR_SUCCESS)
1187 elem = top = QueueTop(elem);
1190 sprintf(temp_buf, "%s has the following cnames.", name);
1191 Put_message(temp_buf);
1192 Loop(top, (void (*)(char **)) PrintCname);
1193 ptr = "Remove ** ALL ** these cnames?";
1194 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1198 Put_message("Aborting...");
1210 char **info = elem->q_data;
1211 if ((stat = do_mr_query("delete_hostalias", 2, info,
1214 ret_value = SUB_ERROR;
1215 com_err(program_name, stat, " in delete_hostalias.");
1217 "Cname %s ** NOT ** removed from host %s.",
1219 Put_message(temp_buf);
1221 elem = elem->q_forw;
1228 /* Function Name: RealDeleteMachine
1229 * Description: Actually Deletes the Machine.
1230 * Arguments: info - nescessary information stored as an array of char *'s
1231 * one_machine - a boolean, true if there is only one item in
1236 static void RealDeleteMachine(char **info, Bool one_machine)
1239 char temp_buf[BUFSIZ];
1241 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
1243 if (!one_machine || Confirm(temp_buf))
1245 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
1247 if (CheckAndRemoveCnames(info[M_NAME], TRUE) != SUB_ERROR)
1249 if ((stat = do_mr_query("delete_host", 1,
1250 &info[M_NAME], NULL, NULL)))
1252 com_err(program_name, stat, " in DeleteMachine.");
1253 sprintf(temp_buf, "%s ** NOT ** deleted.",
1255 Put_message(temp_buf);
1259 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
1260 Put_message(temp_buf);
1267 /* Function Name: DeleteMachine
1268 * Description: This function removes a machine from the data base.
1269 * Arguments: argc, argv - the machines name int argv[1].
1270 * Returns: DM_NORMAL.
1273 /* Perhaps we should remove the cluster if it has no machine now. */
1275 int DeleteMachine(int argc, char **argv)
1280 tmpname = canonicalize_hostname(strdup(argv[1]));
1281 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
1282 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
1289 /* Function Name: ShowCname
1290 * Description: This function shows machine aliases
1291 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1292 * Returns: DM_NORMAL.
1295 int ShowCname(int argc, char **argv)
1298 char *tmpalias, *tmpname;
1300 tmpalias = partial_canonicalize_hostname(strdup(argv[1]));
1301 tmpname = canonicalize_hostname(strdup(argv[2]));
1302 top = GetMCInfo(CNAME, tmpalias, tmpname);
1303 Put_message(""); /* blank line on screen */
1304 Loop(top, ((void (*)(char **)) PrintCname));
1310 int AddCname(int argc, char **argv)
1315 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1316 args[1] = canonicalize_hostname(strdup(argv[2]));
1317 stat = do_mr_query("add_hostalias", 2, args, NULL, NULL);
1323 Put_message("That alias name is already in use.");
1326 Put_message("Permission denied. "
1327 "(Regular users can only add two aliases to a host.");
1330 com_err(program_name, stat, " in add_hostalias");
1336 int DeleteCname(int argc, char **argv)
1341 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1342 args[1] = canonicalize_hostname(strdup(argv[2]));
1343 stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL);
1345 com_err(program_name, stat, " in delete_hostalias");
1350 /* Function Name: AddMachineToCluster
1351 * Description: This function adds a machine to a cluster
1352 * Arguments: argc, argv - The machine name is argv[1].
1353 * The cluster name in argv[2].
1354 * Returns: DM_NORMAL.
1357 int AddMachineToCluster(int argc, char **argv)
1360 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1361 Bool add_it, one_machine, one_cluster;
1362 struct mqelem *melem, *mtop, *celem, *ctop;
1364 machine = canonicalize_hostname(strdup(argv[1]));
1365 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1367 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1369 Put_message(temp_buf);
1373 celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1374 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1377 one_machine = (QueueCount(mtop) == 1);
1378 one_cluster = (QueueCount(ctop) == 1);
1380 /* No good way to use QueryLoop() here, sigh */
1384 char **minfo = melem->q_data;
1387 char **cinfo = celem->q_data;
1388 if (one_machine && one_cluster)
1392 sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1393 minfo[M_NAME], cinfo[C_NAME]);
1394 switch (YesNoQuitQuestion(temp_buf, FALSE))
1403 Put_message("Aborting...");
1411 args[0] = minfo[M_NAME];
1412 args[1] = cinfo[C_NAME];
1413 stat = do_mr_query("add_machine_to_cluster", 2, args,
1420 sprintf(temp_buf, "%s is already in cluster %s",
1421 minfo[M_NAME], cinfo[C_NAME]);
1422 Put_message(temp_buf);
1425 com_err(program_name, stat, " in AddMachineToCluster.");
1429 celem = celem->q_forw;
1431 celem = ctop; /* reset cluster element. */
1432 melem = melem->q_forw;
1439 /* Function Name: RealRemoveMachineFromCluster
1440 * Description: This function actually removes the machine from its
1442 * Arguments: info - all information nescessary to perform the removal.
1443 * one_map - True if there is only one case, and we should
1448 static void RealRemoveMachineFromCluster(char **info, Bool one_map)
1450 char temp_buf[BUFSIZ];
1453 sprintf(temp_buf, "Remove %s from the cluster %s",
1454 info[MAP_MACHINE], info[MAP_CLUSTER]);
1455 if (!one_map || Confirm(temp_buf))
1457 if ((stat = do_mr_query("delete_machine_from_cluster", 2,
1459 com_err(program_name, stat, " in delete_machine_from_cluster");
1462 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1463 info[MAP_MACHINE], info[MAP_CLUSTER]);
1464 Put_message(temp_buf);
1468 Put_message("Machine not removed.");
1471 /* Function Name: RemoveMachineFromCluster
1472 * Description: Removes this machine form a specific cluster.
1473 * Arguments: argc, argv - Name of machine in argv[1].
1474 * Name of cluster in argv[2].
1478 int RemoveMachineFromCluster(int argc, char **argv)
1480 struct mqelem *elem = NULL;
1481 char buf[BUFSIZ], *args[10];
1484 args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1]));
1485 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1487 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1488 argv[1], args[MAP_MACHINE]);
1491 args[MAP_CLUSTER] = argv[2];
1492 args[MAP_END] = NULL;
1494 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1496 if (stat == MR_NO_MATCH)
1498 sprintf(buf, "The machine %s is not in the cluster %s.",
1499 args[MAP_MACHINE], args[MAP_CLUSTER]);
1501 free(args[MAP_MACHINE]);
1504 if (stat != MR_SUCCESS)
1505 com_err(program_name, stat, " in delete_machine_from_cluster");
1507 elem = QueueTop(elem);
1508 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1509 "Remove this machine from this cluster");
1512 free(args[MAP_MACHINE]);
1516 /* ---------- Subnet Menu -------- */
1518 /* Function Name: ShowSubnetInfo
1519 * Description: Gets information about a subnet given its name.
1520 * Arguments: argc, argc - the name of the subnet in in argv[1].
1521 * Returns: DM_NORMAL.
1524 int ShowSubnetInfo(int argc, char **argv)
1528 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1529 Loop(top, (void (*)(char **)) PrintSubnetInfo);
1534 /* Function Name: AddSubnet
1535 * Description: Creates a new subnet.
1536 * Arguments: argc, argv - the name of the new subnet is argv[1].
1537 * Returns: DM_NORMAL.
1540 int AddSubnet(int argc, char **argv)
1542 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1546 * Check to see if this subnet already exists.
1548 if (!ValidName(name))
1551 if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS)
1553 Put_message("This subnet already exists.");
1556 else if (stat != MR_NO_MATCH)
1558 com_err(program_name, stat, " in AddSubnet.");
1561 if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1563 Put_message("Aborted.");
1569 * Actually create the new Subnet.
1571 if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL)))
1572 com_err(program_name, stat, " in AddSubnet.");
1578 /* Function Name: RealUpdateSubnet
1579 * Description: This function actually performs the subnet update.
1580 * Arguments: info - all information nesc. for updating the subnet.
1581 * junk - an UNUSED boolean.
1585 static void RealUpdateSubnet(char **info, Bool junk)
1588 char **args = AskMCDInfo(info, SUBNET, TRUE);
1591 Put_message("Aborted.");
1594 if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL)))
1595 com_err(program_name, stat, " in UpdateSubnet.");
1597 Put_message("Subnet successfully updated.");
1600 /* Function Name: UpdateSubnet
1601 * Description: This Function Updates a subnet
1602 * Arguments: name of the subnet in argv[1].
1603 * Returns: DM_NORMAL.
1606 int UpdateSubnet(int argc, char **argv)
1609 top = GetMCInfo(SUBNET, argv[1], NULL);
1610 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1616 /* Function Name: RealDeleteSubnet
1617 * Description: Actually performs the subnet deletion.
1618 * Arguments: info - all information about this subnet.
1619 * one_subnet - If true then there was only one subnet in
1620 * the queue, and we should confirm.
1624 static void RealDeleteSubnet(char **info, Bool one_subnet)
1627 char temp_buf[BUFSIZ];
1630 "Are you sure the you want to delete the subnet %s (y/n) ?",
1632 if (!one_subnet || Confirm(temp_buf))
1634 if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL)))
1636 com_err(program_name, stat, " in delete_subnet.");
1637 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1638 Put_message(temp_buf);
1642 sprintf(temp_buf, "subnet %s successfully deleted.",
1644 Put_message(temp_buf);
1649 /* Function Name: DeleteSubnet
1650 * Description: This function removes a subnet from the database.
1651 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1652 * Returns: DM_NORMAL.
1655 int DeleteSubnet(int argc, char **argv)
1659 top = GetMCInfo(SUBNET, argv[1], NULL);
1660 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1666 /* ---------- Cluster Menu -------- */
1668 /* Function Name: ShowClusterInfo
1669 * Description: Gets information about a cluser given its name.
1670 * Arguments: argc, argc - the name of the cluster in in argv[1].
1671 * Returns: DM_NORMAL.
1674 int ShowClusterInfo(int argc, char **argv)
1678 top = GetMCInfo(CLUSTER, argv[1], NULL);
1679 Loop(top, (void (*)(char **)) PrintClusterInfo);
1684 /* Function Name: AddCluster
1685 * Description: Creates a new cluster.
1686 * Arguments: argc, argv - the name of the new cluster is argv[1].
1687 * Returns: DM_NORMAL.
1690 int AddCluster(int argc, char **argv)
1692 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1696 * Check to see if this cluster already exists.
1698 if (!ValidName(name))
1701 if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS)
1703 Put_message("This cluster already exists.");
1706 else if (stat != MR_NO_MATCH)
1708 com_err(program_name, stat, " in AddCluster.");
1711 if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1713 Put_message("Aborted.");
1719 * Actually create the new Cluster.
1721 if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL)))
1722 com_err(program_name, stat, " in AddCluster.");
1728 /* Function Name: RealUpdateCluster
1729 * Description: This function actually performs the cluster update.
1730 * Arguments: info - all information nesc. for updating the cluster.
1731 * junk - an UNUSED boolean.
1735 static void RealUpdateCluster(char **info, Bool junk)
1738 char **args = AskMCDInfo(info, CLUSTER, TRUE);
1742 Put_message("Aborted.");
1745 if ((stat = do_mr_query("update_cluster", CountArgs(args),
1747 com_err(program_name, stat, " in UpdateCluster.");
1749 Put_message("Cluster successfully updated.");
1752 /* Function Name: UpdateCluster
1753 * Description: This Function Updates a cluster
1754 * Arguments: name of the cluster in argv[1].
1755 * Returns: DM_NORMAL.
1758 int UpdateCluster(int argc, char **argv)
1761 top = GetMCInfo(CLUSTER, argv[1], NULL);
1762 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1768 /* Function Name: CheckAndRemoveMachine
1769 * Description: This function checks and removes all machines from a
1771 * Arguments: name - name of the cluster.
1772 * ask_first - if TRUE, then we will query the user, before
1774 * Returns: SUB_ERROR if all machines not removed.
1777 int CheckAndRemoveMachines(char *name, Bool ask_first)
1779 int stat, ret_value;
1781 char *args[10], temp_buf[BUFSIZ], *ptr;
1782 struct mqelem *top, *elem = NULL;
1784 ret_value = SUB_NORMAL;
1785 args[MAP_MACHINE] = "*";
1786 args[MAP_CLUSTER] = name;
1787 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1788 if (stat && stat != MR_NO_MATCH)
1790 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1793 if (stat == MR_SUCCESS)
1795 elem = top = QueueTop(elem);
1798 sprintf(temp_buf, "The cluster %s has the following machines in it:",
1800 Put_message(temp_buf);
1803 char **info = elem->q_data;
1804 Print(1, &info[MAP_MACHINE], (char *) NULL);
1805 elem = elem->q_forw;
1807 ptr = "Remove ** ALL ** these machines from this cluster?";
1809 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1813 Put_message("Aborting...");
1826 char **info = elem->q_data;
1827 if ((stat = do_mr_query("delete_machine_from_cluster",
1828 2, info, NULL, NULL)))
1830 ret_value = SUB_ERROR;
1831 com_err(program_name, stat,
1832 " in delete_machine_from_cluster.");
1834 "Machine %s ** NOT ** removed from cluster %s.",
1835 info[MAP_MACHINE], info[MAP_CLUSTER]);
1836 Put_message(temp_buf);
1838 elem = elem->q_forw;
1845 /* Function Name: RealDeleteCluster
1846 * Description: Actually performs the cluster deletion.
1847 * Arguments: info - all information about this cluster.
1848 * one_cluster - If true then there was only one cluster in
1849 * the queue, and we should confirm.
1853 static void RealDeleteCluster(char **info, Bool one_cluster)
1856 char temp_buf[BUFSIZ];
1859 "Are you sure the you want to delete the cluster %s (y/n) ?",
1861 if (!one_cluster || Confirm(temp_buf))
1863 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1865 if ((stat = do_mr_query("delete_cluster", 1,
1866 &info[C_NAME], NULL, NULL)))
1868 com_err(program_name, stat, " in delete_cluster.");
1869 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1870 Put_message(temp_buf);
1874 sprintf(temp_buf, "cluster %s successfully deleted.",
1876 Put_message(temp_buf);
1882 /* Function Name: DeleteCluster
1883 * Description: This function removes a cluster from the database.
1884 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1885 * Returns: DM_NORMAL.
1888 int DeleteCluster(int argc, char **argv)
1892 top = GetMCInfo(CLUSTER, argv[1], NULL);
1893 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1899 /* ----------- Cluster Data Menu -------------- */
1901 /* Function Name: ShowClusterData
1902 * Description: This function shows the services for one cluster.
1903 * Arguments: argc, argv - The name of the cluster is argv[1].
1904 * The label of the data in argv[2].
1905 * Returns: DM_NORMAL.
1908 int ShowClusterData(int argc, char **argv)
1910 struct mqelem *elem, *top;
1913 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1916 info = elem->q_data;
1917 PrintClusterData(info);
1918 elem = elem->q_forw;
1924 /* Function Name: AddClusterData
1925 * Description: This function adds some data to the cluster.
1926 * Arguments: argv, argc: argv[1] - the name of the cluster.
1927 * argv[2] - the label of the data.
1928 * argv[3] - the data.
1929 * Returns: DM_NORMAL.
1932 int AddClusterData(int argc, char **argv)
1936 for (i = 1; i < 4; i++)
1938 if (IS_EMPTY(argv[i]))
1940 Put_message("Cluster data cannot be an empty string.");
1944 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
1945 com_err(program_name, stat, " in AddClusterData.");
1949 /* Function Name: RealRemoveClusterData
1950 * Description: actually removes the cluster data.
1951 * Arguments: info - all info necessary to remove the cluster, in an array
1953 * one_item - if true then the queue has only one elem and we
1958 static void RealRemoveClusterData(char **info, Bool one_item)
1964 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1965 PrintClusterData(info);
1966 if (!one_item || Confirm(temp_ptr))
1968 if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
1970 com_err(program_name, stat, " in DeleteClusterData.");
1971 Put_message("Data not removed.");
1974 Put_message("Removal successful.");
1978 /* Function Name: RemoveClusterData
1979 * Description: This function removes data on a given cluster.
1980 * Arguments: argv, argc: argv[1] - the name of the cluster.
1981 * argv[2] - the label of the data.
1982 * argv[3] - the data.
1983 * Returns: DM_NORMAL.
1986 int RemoveClusterData(int argc, char **argv)
1990 top = GetMCInfo(DATA, argv[1], argv[2]);
1991 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1992 "Remove data from cluster");
1998 /* Function Name: MachineToClusterMap
1999 * Description: This Retrieves the mapping between machine and cluster
2000 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
2001 * argv[2] -> cluster name or wildcard.
2005 int MachineToClusterMap(int argc, char **argv)
2007 struct mqelem *elem, *top;
2008 char *tmpname, temp_buf[256];
2010 tmpname = canonicalize_hostname(strdup(argv[1]));
2011 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2013 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2015 Put_message(temp_buf);
2017 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
2019 Put_message(""); /* blank line on screen */
2022 char **info = elem->q_data;
2024 elem = elem->q_forw;
2032 /* Function Name: MachineByOwner
2033 * Description: This function prints all machines which are owned by
2034 * a given user or group.
2036 * Returns: DM_NORMAL.
2039 int MachineByOwner(int argc, char **argv)
2041 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
2044 type = strdup("USER");
2045 if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR)
2048 sprintf(buf, "Name of %s", type);
2049 name = strdup(user);
2050 if (GetValueFromUser(buf, &name) == SUB_ERROR)
2053 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
2056 sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */
2058 type = strdup(temp_buf);
2066 top = GetMachineByOwner(type, name);
2067 Loop(top, PrintMachine);
2073 /* Function Name: GetMachineByOwner
2074 * Description: This function stores information retrieved by
2075 * the get_host_by_owner query
2076 * Arguments: type - an ace_type, argv[0] for the query
2077 * name - name of machine, argv[1] for the query
2078 * Returns: the top element of a queue returning the data, or NULL.
2081 struct mqelem *GetMachineByOwner(char *type, char *name)
2084 struct mqelem *elem = NULL;
2089 if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem)))
2091 com_err(program_name, status, " in get_host_by_owner");
2094 return QueueTop(elem);
2097 int MachineByAcctNumber(int argc, char **argv)
2099 char *args[1], *account_number;
2101 struct mqelem *elem = NULL;
2103 account_number = strdup("");
2104 if (GetValueFromUser("Account Number", &account_number) == SUB_ERROR)
2107 args[0] = account_number;
2108 if (status = do_mr_query("get_host_by_account_number", 1, args, StoreInfo,
2111 com_err(program_name, status, " in get_host_by_account_number");
2114 Loop(QueueTop(elem), (void (*)(char **)) PrintMachInfo);
2120 int ShowContainerInfo(int argc, char **argv)
2124 top = GetMCInfo(CONTAINER, argv[1], NULL);
2125 Loop(top, (void (*)(char **)) PrintContainerInfo);
2130 static char *PrintContainerInfo(char **info)
2132 char buf[BUFSIZ], tbuf[256];
2134 struct mqelem *elem = NULL;
2138 sprintf(buf, "Container: %-16s Public: %s", info[CON_NAME],
2139 atoi(info[CON_PUBLIC]) ? "Yes" : "No");
2141 /* Do a get_container_list to see what the associated list is. */
2142 args[0] = info[CON_NAME];
2143 if (stat = do_mr_query("get_container_list", 1, args, StoreInfo, &elem))
2145 if (stat != MR_NO_MATCH)
2146 com_err(program_name, stat, " looking up container list");
2150 sprintf(buf, "Container's associated list is: LIST %s",
2151 ((char **)elem->q_data)[1]);
2155 sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]);
2157 sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION],
2160 sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE],
2161 strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : "");
2162 sprintf(buf, "Owner: %-16s", tbuf);
2164 sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE],
2165 strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : "");
2166 sprintf(buf, "Membership ACL: %-16s", tbuf);
2169 sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME],
2172 return(info[CON_NAME]);
2175 static char *PrintContainer(char **info)
2179 sprintf(buf, "Container: %s", info[CON_NAME]);
2184 static char *PrintMContMap(char **info)
2187 sprintf(buf, "Container: %-30s Machine: %-20s",
2193 int AddContainer(int argc, char **argv)
2195 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
2198 /* Can't use ValidName() because spaces are allowed in container names */
2201 Put_message("Please use a non-empty name.");
2205 if (strchr(name, '*') || strchr(name, '?'))
2207 Put_message("Wildcards not accepted here.");
2211 /* Check if this cluster already exists. */
2212 if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL))
2215 Put_message("This container already exists.");
2218 else if (stat != MR_NO_MATCH)
2220 com_err(program_name, stat, " in AddContainer.");
2223 if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE)))
2225 Put_message("Aborted.");
2230 /* Create the new container. */
2231 if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL)))
2232 com_err(program_name, stat, " in AddContainer.");
2238 int UpdateContainer(int argc, char **argv)
2241 top = GetMCInfo(CONTAINER, argv[1], NULL);
2242 QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container");
2248 static void RealUpdateContainer(char **info, Bool junk)
2251 char **args = AskMCDInfo(info, CONTAINER, TRUE);
2255 Put_message("Aborted.");
2258 if ((stat = do_mr_query("update_container", CountArgs(args), args,
2260 com_err(program_name, stat, " in UpdateContainer.");
2262 Put_message("Container successfully updated.");
2265 int DeleteContainer(int argc, char **argv)
2269 top = GetMCInfo(CONTAINER, argv[1], NULL);
2270 QueryLoop(top, PrintClusterInfo, RealDeleteContainer,
2271 "Delete the container");
2277 static void RealDeleteContainer(char **info, Bool one_container)
2280 char temp_buf[BUFSIZ];
2283 "Are you sure you want to delete the container %s (y/n) ?",
2285 if (!one_container || Confirm(temp_buf))
2287 if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE)
2290 if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME],
2293 com_err(program_name, stat, " in delete_container.");
2294 sprintf(temp_buf, "Container %s ** NOT ** deleted.",
2296 Put_message(temp_buf);
2300 sprintf(temp_buf, "Container %s successfully deleted.",
2302 Put_message(temp_buf);
2308 int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first)
2310 int stat, ret_value;
2312 char *args[10], temp_buf[BUFSIZ], *ptr;
2313 struct mqelem *top, *elem = NULL;
2315 ret_value = SUB_NORMAL;
2318 stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo,
2320 if (stat && stat != MR_NO_MATCH)
2322 com_err(program_name, stat, " in get_machines_of_container");
2325 if (stat == MR_SUCCESS)
2327 elem = top = QueueTop(elem);
2331 "The container %s has the following machines in it:", name);
2332 Put_message(temp_buf);
2335 char **info = elem->q_data;
2336 Print(1, &info[0], (char *) NULL);
2337 elem = elem->q_forw;
2339 ptr = "Remove ** ALL ** these machines from this container?";
2341 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
2345 Put_message("Aborting...");
2358 char **info = elem->q_data;
2359 if ((stat = do_mr_query("delete_machine_from_container",
2360 2, info, NULL, NULL)))
2362 ret_value = SUB_ERROR;
2363 com_err(program_name, stat,
2364 " in delete_machine_from_container.");
2366 "Machine %s ** NOT ** removed from container %s.",
2368 Put_message(temp_buf);
2370 elem = elem->q_forw;
2377 int GetSubContainers(int argc, char **argv)
2380 struct mqelem *elem = NULL, *top = NULL;
2385 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2390 if (stat = do_mr_query("get_subcontainers_of_container", 2, args,
2392 com_err(program_name, stat, " in get_subcontainers_of_container");
2394 top = QueueTop(elem);
2395 Loop(top, ((void (*)(char **)) PrintContainer));
2400 int MachineToContainerMap(int argc, char **argv)
2402 struct mqelem *elem, *top;
2403 char *tmpname, temp_buf[256];
2405 tmpname = canonicalize_hostname(strdup(argv[1]));
2406 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2408 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2410 Put_message(temp_buf);
2412 top = elem = GetMCInfo(CONTMAP, tmpname, NULL);
2417 char **info = elem->q_data;
2418 PrintMContMap(info);
2419 elem = elem->q_forw;
2427 int AddMachineToContainer(int argc, char **argv)
2430 char *machine, *container, temp_buf[BUFSIZ], *args[10];
2431 Bool add_it, one_machine, one_container;
2432 struct mqelem *melem, *mtop, *celem, *ctop;
2434 machine = canonicalize_hostname(strdup(argv[1]));
2435 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
2437 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2439 Put_message(temp_buf);
2441 container = argv[2];
2443 celem = ctop = GetMCInfo(CONTAINER, container, NULL);
2444 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
2447 one_machine = (QueueCount(mtop) == 1);
2448 one_container = (QueueCount(ctop) == 1);
2452 char **minfo = melem->q_data;
2455 char **cinfo = celem->q_data;
2456 if (one_machine && one_container)
2460 sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?",
2461 minfo[M_NAME], cinfo[CON_NAME]);
2462 switch (YesNoQuestion(temp_buf, FALSE))
2471 Put_message("Aborting...");
2479 args[0] = minfo[M_NAME];
2480 args[1] = cinfo[CON_NAME];
2481 stat = do_mr_query("add_machine_to_container", 2, args, NULL,
2488 sprintf(temp_buf, "%s is already in container %s",
2489 minfo[M_NAME], cinfo[CON_NAME]);
2490 Put_message(temp_buf);
2493 com_err(program_name, stat, " in AddMachineToContainer.");
2497 celem = celem->q_forw;
2500 melem = melem->q_forw;
2507 int RemoveMachineFromContainer(int argc, char **argv)
2509 struct mqelem *elem = NULL;
2510 char buf[BUFSIZ], *args[10];
2513 args[0] = canonicalize_hostname(strdup(argv[1]));
2514 if (strcasecmp(args[0], argv[1]) && *argv[1] != '"')
2516 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
2523 stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo,
2525 if (stat == MR_NO_MATCH)
2527 sprintf(buf, "The machine %s is not in the container %s.",
2533 if (stat != MR_SUCCESS)
2534 com_err(program_name, stat, " in deleter_machine_from_container");
2536 elem = QueueTop(elem);
2537 QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer,
2538 "Remove this machine from this container");
2545 static void RealRemoveMachineFromContainer(char **info, Bool one_contmap)
2547 char temp_buf[BUFSIZ];
2550 sprintf(temp_buf, "Remove %s from the container %s",
2552 if (!one_contmap || Confirm(temp_buf))
2554 if ((stat = do_mr_query("delete_machine_from_container", 2,
2556 com_err(program_name, stat, " in delete_machine_from_container");
2559 sprintf(temp_buf, "%s has been removed from the container %s.",
2561 Put_message(temp_buf);
2565 Put_message("Machine not removed.");
2568 int GetMachinesOfContainer(int argc, char **argv)
2571 struct mqelem *elem = NULL, *top = NULL;
2576 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2581 if (stat = do_mr_query("get_machines_of_container", 2, args,
2583 com_err(program_name, stat, " in get_machines_of_container");
2585 top = QueueTop(elem);
2586 Loop(top, ((void (*)(char **)) PrintMContMap));
2591 int GetTopLevelCont(int argc, char **argv)
2594 struct mqelem *elem = NULL;
2595 if (status = do_mr_query("get_toplevel_containers", 0, NULL, StoreInfo,
2598 com_err(program_name, status, " in get_toplevel_containers");
2601 Loop(QueueTop(elem), (void(*)(char **)) PrintContainer);