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[] = {
94 static char *MacState(int state)
96 static char buf[BUFSIZ];
98 if (state < 0 || state > 3)
100 sprintf(buf, "Unknown (%d)", state);
103 return states[state];
106 static char *SubnetState(int state)
108 static char buf[BUFSIZ];
110 if (state < 0 || state > 4)
112 sprintf(buf, "Unknown (%d)", state);
115 return subnet_states[state];
118 /* -------------------- Set Defaults -------------------- */
120 /* Function Name: SetMachineDefaults
121 * Description: sets machine defaults.
122 * Arguments: info - an array to put the defaults into.
123 * name - Canonacalized name of the machine.
124 * Returns: info - the array.
127 static char **SetMachineDefaults(char **info, char *name)
129 info[M_NAME] = strdup(name);
130 info[M_VENDOR] = strdup(M_DEFAULT_TYPE);
131 info[M_MODEL] = strdup(M_DEFAULT_TYPE);
132 info[M_OS] = strdup(M_DEFAULT_TYPE);
133 info[M_LOC] = strdup(M_DEFAULT_TYPE);
134 info[M_CONTACT] = strdup(M_DEFAULT_TYPE);
135 info[M_BILL_CONTACT] = strdup(M_DEFAULT_TYPE);
136 info[M_ACCT_NUMBER] = strdup("");
137 info[M_USE] = strdup("0");
138 info[M_STAT] = strdup("1");
139 info[M_SUBNET] = strdup("NONE");
140 info[M_ADDR] = strdup("unique");
141 info[M_OWNER_TYPE] = strdup("NONE");
142 info[M_OWNER_NAME] = strdup("NONE");
143 info[M_ACOMMENT] = strdup("");
144 info[M_OCOMMENT] = strdup("");
145 info[17] = info[18] = NULL;
149 /* Function Name: SetClusterDefaults
150 * Description: sets Cluster defaults.
151 * Arguments: info - an array to put the defaults into.
152 * name - name of the Cluster.
153 * Returns: info - the array.
156 static char **SetClusterDefaults(char **info, char *name)
158 info[C_NAME] = strdup(name);
159 info[C_DESCRIPT] = strdup(C_DEFAULT_DESCRIPT);
160 info[C_LOCATION] = strdup(C_DEFAULT_LOCATION);
161 info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
165 static char **SetContainerDefaults(char **info, char *name)
167 info[CON_NAME] = strdup(name);
168 info[CON_DESCRIPT] = strdup(CON_DEFAULT_TYPE);
169 info[CON_LOCATION] = strdup(CON_DEFAULT_TYPE);
170 info[CON_CONTACT] = strdup(CON_DEFAULT_TYPE);
171 info[CON_OWNER_TYPE] = strdup("NONE");
172 info[CON_OWNER_NAME] = strdup("NONE");
173 info[CON_MEMACE_TYPE] = strdup("NONE");
174 info[CON_MEMACE_NAME] = strdup("NONE");
175 info[CON_MODBY] = info[CON_MODTIME] = info[CON_MODWITH] = NULL;
176 info[CON_END] = NULL;
180 /* Function Name: SetSubnetDefaults
181 * Description: sets Subnet defaults.
182 * Arguments: info - an array to put the defaults into.
183 * name - name of the Subnet.
184 * Returns: info - the array.
187 static char **SetSubnetDefaults(char **info, char *name)
191 info[SN_NAME] = strdup(name);
192 info[SN_DESC] = strdup("");
193 info[SN_STATUS] = strdup("1");
194 info[SN_CONTACT] = strdup(DEFAULT_NONE);
195 info[SN_ACCT_NUMBER] = strdup("");
196 sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0")));
197 info[SN_ADDRESS] = strdup(buf);
198 sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0")));
199 info[SN_MASK] = strdup(buf);
200 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW)));
201 info[SN_LOW] = strdup(buf);
202 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH)));
203 info[SN_HIGH] = strdup(buf);
204 info[SN_PREFIX] = strdup("");
205 info[SN_ACE_TYPE] = strdup("LIST");
206 info[SN_ACE_NAME] = strdup("network");
207 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
211 /* -------------------- General Functions -------------------- */
213 static char aliasbuf[256];
215 void PrintAliases(char **info)
217 if (strlen(aliasbuf) == 0)
218 sprintf(aliasbuf, "Aliases: %s", info[0]);
221 strcat(aliasbuf, ", ");
222 strcat(aliasbuf, info[0]);
227 /* Function Name: PrintMachInfo
228 * Description: This function Prints out the Machine info in
230 * Arguments: info - array of information about a machine.
231 * Returns: The name of the Machine
234 static char *PrintMachInfo(char **info)
236 char buf[BUFSIZ], tbuf[256];
238 struct mqelem *elem = NULL, *elem2 = NULL;
242 sprintf(buf, "Machine: %s", info[M_NAME]);
245 args[1] = info[M_NAME];
246 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
248 if (stat != MR_NO_MATCH)
249 com_err(program_name, stat, " looking up aliases");
254 Loop(QueueTop(elem), (void (*)(char **)) PrintAliases);
256 Put_message(aliasbuf);
258 sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
259 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
260 sprintf(buf, "Address: %-16s Network: %-16s",
261 info[M_ADDR], info[M_SUBNET]);
263 sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]);
265 sprintf(buf, "Status: %-16s Changed: %s",
266 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
269 sprintf(buf, "Vendor: %-16s Location: %s", info[M_VENDOR],
272 sprintf(buf, "Model: %-16s Contact: %s", info[M_MODEL],
275 sprintf(buf, "OS: %-16s Billing Contact: %s", info[M_OS],
276 info[M_BILL_CONTACT]);
278 sprintf(buf, "Opt: %-16s Account Number: %s", info[M_USE],
279 info[M_ACCT_NUMBER]);
282 sprintf(buf, "Adm cmt: %s", info[M_ACOMMENT]);
284 sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]);
287 sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]);
289 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
291 /* Do a get_subnet for the machine's subnet. We need to know if it's
294 args[0] = info[M_SUBNET];
295 stat = do_mr_query("get_subnet", 1, args, StoreInfo, &elem2);
297 com_err(program_name, stat, " looking up subnet info");
298 else if (atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_10MBPS ||
299 atoi(((char **)elem2->q_data)[2]) == SNET_STATUS_PRIVATE_100MBPS)
302 sprintf(buf, "Warning: This host is on a private subnet.");
304 sprintf(buf, "Billing information shown is superceded by billing information for the subnet.");
312 /* Function Name: PrintMachine
313 * Description: Prints the name of a machine record
314 * Arguments: info - array of information about the machine.
318 static void PrintMachine(char **info)
322 sprintf(buf, "Machine: %s", info[M_NAME]);
326 /* Function Name: PrintCname
327 * Description: Prints the Data on a host alias
328 * Arguments: info a pointer to the data array.
329 * Returns: The name of the alias.
332 static char *PrintCname(char **info)
336 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
341 /* Function Name: PrintClusterInfo
342 * Description: This function Prints out the cluster info
343 * in a coherent form.
344 * Arguments: info - array of information about a cluster.
345 * Returns: The name of the cluster.
348 static char *PrintClusterInfo(char **info)
353 sprintf(buf, "Cluster: %s", info[C_NAME]);
355 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
357 sprintf(buf, "Location: %s", info[C_LOCATION]);
359 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
364 /* Function Name: PrintClusterData
365 * Description: Prints the Data on a cluster
366 * Arguments: info a pointer to the data array.
367 * Returns: The name of the cluster.
370 static char *PrintClusterData(char **info)
375 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
376 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
378 return info[CD_NAME];
381 /* Function Name: PrintMCMap
382 * Description: Prints the data about a machine to cluster mapping.
383 * Arguments: info a pointer to the data array.
387 static char *PrintMCMap(char **info)
390 sprintf(buf, "Cluster: %-30s Machine: %-20s",
391 info[MAP_CLUSTER], info[MAP_MACHINE]);
393 return ""; /* Used by QueryLoop(). */
396 /* Function Name: PrintSubnetInfo
397 * Description: This function Prints out the subnet info
398 * in a coherent form.
399 * Arguments: info - array of information about a subnet.
400 * Returns: The name of the subnet.
403 static char *PrintSubnetInfo(char **info)
406 struct in_addr addr, mask, low, high;
409 sprintf(buf, " Network: %s", info[SN_NAME]);
411 sprintf(buf, " Description: %s", info[SN_DESC]);
413 sprintf(buf, " Status: %s", SubnetState(atoi(info[SN_STATUS])));
415 sprintf(buf, " Contact: %s", info[SN_CONTACT]);
417 sprintf(buf, " Account Number: %s", info[SN_ACCT_NUMBER]);
419 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
420 mask.s_addr = htonl(atoi(info[SN_MASK]));
421 low.s_addr = htonl(atoi(info[SN_LOW]));
422 high.s_addr = htonl(atoi(info[SN_HIGH]));
423 /* screwy sequence is here because inet_ntoa returns a pointer to
424 a static buf. If it were all one sprintf, the last value would
426 sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr));
427 strcat(buf, inet_ntoa(mask));
428 strcat(buf, "\n High: ");
429 strcat(buf, inet_ntoa(high));
430 strcat(buf, " Low: ");
431 strcat(buf, inet_ntoa(low));
433 sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
435 sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE],
436 strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : "");
438 sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]);
440 return info[SN_NAME];
443 /* Function Name: GetMCInfo.
444 * Description: This function stores info about a machine.
445 * type - type of data we are trying to retrieve.
446 * name1 - the name of argv[0] for the call.
447 * name2 - the name of argv[1] for the call.
448 * Returns: the top element of a queue containing the data or NULL.
451 struct mqelem *GetMCInfo(int type, char *name1, char *name2)
454 struct mqelem *elem = NULL;
461 args[1] = args[2] = args[3] = "*";
462 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
464 if (stat == MR_NO_MATCH)
467 sprintf(buf, "Machine '%s' is not in the database.", name1);
471 com_err(program_name, stat, " in get_machine.");
478 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
480 com_err(program_name, stat, " in get_hostalias.");
485 if ((stat = do_mr_query("get_subnet", 1, &name1, StoreInfo, &elem)))
487 if (stat == MR_NO_MATCH)
490 sprintf(buf, "Network '%s' is not in the database.", name1);
494 com_err(program_name, stat, " in get_subnet.");
499 if ((stat = do_mr_query("get_cluster", 1, &name1, StoreInfo, &elem)))
501 com_err(program_name, stat, " in get_cluster.");
506 args[MAP_MACHINE] = name1;
507 args[MAP_CLUSTER] = name2;
508 if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args,
511 com_err(program_name, stat, " in get_machine_to_cluster_map.");
516 args[CD_NAME] = name1;
517 args[CD_LABEL] = name2;
518 if ((stat = do_mr_query("get_cluster_data", 2, args, StoreInfo, &elem)))
520 com_err(program_name, stat, " in get_cluster_data.");
525 args[CON_NAME] = name1;
526 if ((stat = do_mr_query("get_container", 1, &name1, StoreInfo, &elem)))
528 com_err(program_name, stat, " in get_container.");
534 if ((stat = do_mr_query("get_machine_to_container_map", 1, &name1,
537 com_err(program_name, stat, " in get_machine_to_container_map.");
541 return QueueTop(elem);
544 /* Function Name: AskMCDInfo.
545 * Description: This function askes the user for information about a
546 * machine and saves it into a structure.
547 * Arguments: info - a pointer the information to ask about
548 * type - type of information - MACHINE
552 * name - T/F : change the name of this type.
556 char **AskMCDInfo(char **info, int type, Bool name)
558 char temp_buf[BUFSIZ], *newname, *oldnewname;
563 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
567 sprintf(temp_buf, "Setting the information for the Network %s...",
571 sprintf(temp_buf, "Setting the information for the Cluster %s...",
575 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
579 sprintf(temp_buf, "Setting the Data for the Container %s...",
583 Put_message(temp_buf);
590 newname = strdup(info[M_NAME]);
591 if (GetValueFromUser("The new name for this machine? ", &newname) ==
594 oldnewname = strdup(newname);
595 newname = canonicalize_hostname(newname);
596 if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
598 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
599 oldnewname, newname);
600 Put_message(temp_buf);
605 newname = strdup(info[SN_NAME]);
606 if (GetValueFromUser("The new name for this network? ", &newname) ==
611 newname = strdup(info[C_NAME]);
612 if (GetValueFromUser("The new name for this cluster? ", &newname) ==
617 newname = strdup(info[CON_NAME]);
618 if (GetValueFromUser("The new name for this container? ", &newname)
623 Put_message("Unknown type in AskMCDInfo, programmer botch");
631 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
633 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
635 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
638 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
640 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
643 if (GetValueFromUser("Machine's billing contact",
644 &info[M_BILL_CONTACT]) == SUB_ERROR)
646 if (GetValueFromUser("Machine's billing account number",
647 &info[M_ACCT_NUMBER]) == SUB_ERROR)
652 if (GetValueFromUser("Machine's status (? for help)",
653 &info[M_STAT]) == SUB_ERROR)
655 if (isdigit(info[M_STAT][0]))
657 Put_message("Valid status numbers:");
658 for (i = 0; i < 4; i++)
659 Put_message(states[i]);
662 /* there appears to be some argument mismatch between the client
663 * and the server.. so here is this argument shuffler.
664 * I have since modified this to always shuffle the arguments..
665 * not just do so when performing a modify all fields request.
666 * The SetMachinedefaults() has been changed to reflect this.
667 * pray for us and may we attain enlightenment through structures.
672 /* info did not come from SetMachineDefaults(), which does not
673 * initialize entry 10 (M_STAT_CHNG), therefore we can
676 /* This is an update of an existing machine and the structure
677 * was filled in thru a query to the db which does fill in this
683 info[10] = info[M_SUBNET];
684 info[11] = info[M_ADDR];
685 info[12] = info[M_OWNER_TYPE];
686 info[13] = info[M_OWNER_NAME];
687 info[14] = info[M_ACOMMENT];
688 info[15] = info[M_OCOMMENT];
692 if (GetValueFromUser("Machine's network (or 'none')", &info[10])
696 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
697 &info[11]) == SUB_ERROR)
699 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[12]) ==
702 if (strcmp(info[12], "NONE") &&
703 GetValueFromUser("Owner's Name", &info[13]) == SUB_ERROR)
705 if (!strcmp(info[12], "KERBEROS"))
709 mrcl_validate_kerberos_member(info[13], &canon);
710 if (mrcl_get_message())
711 Put_message(mrcl_get_message());
715 if (GetValueFromUser("Administrative comment", &info[14]) == SUB_ERROR)
717 if (GetValueFromUser("Operational comment", &info[15]) == SUB_ERROR)
720 FreeAndClear(&info[17], TRUE);
721 FreeAndClear(&info[18], TRUE);
724 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
729 if (GetValueFromUser("Network's status (? for help)",
730 &info[SN_STATUS]) == SUB_ERROR)
732 if (isdigit(info[SN_STATUS][0]))
734 Put_message("Valid status numbers:");
735 for (i = 0; i < 5; i++)
736 Put_message(subnet_states[i]);
738 if (GetValueFromUser("Network's contact", &info[SN_CONTACT]) == SUB_ERROR)
740 if (GetValueFromUser("Network's billing account number",
741 &info[SN_ACCT_NUMBER]) == SUB_ERROR)
743 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
745 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
747 if (atoi(info[SN_LOW]) == (int)ntohl(inet_addr(S_DEFAULT_LOW)))
750 unsigned long mask, addr;
752 addr = atoi(info[SN_ADDRESS]);
753 mask = atoi(info[SN_MASK]);
754 low.s_addr = atoi(info[SN_LOW]);
755 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
757 sprintf(temp_buf, "%ld", low.s_addr);
758 info[SN_LOW] = strdup(temp_buf);
760 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
763 if (atoi(info[SN_HIGH]) == (int)ntohl(inet_addr(S_DEFAULT_HIGH)))
766 unsigned long mask, addr;
768 addr = atoi(info[SN_ADDRESS]);
769 mask = atoi(info[SN_MASK]);
770 high.s_addr = atoi(info[SN_HIGH]);
771 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
773 sprintf(temp_buf, "%ld", high.s_addr);
774 info[SN_HIGH] = strdup(temp_buf);
776 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
779 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
781 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
784 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
785 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
787 if (!strcmp(info[SN_ACE_TYPE], "KERBEROS"))
791 mrcl_validate_kerberos_member(info[SN_ACE_NAME], &canon);
792 if (mrcl_get_message())
793 Put_message(mrcl_get_message());
794 free(info[SN_ACE_NAME]);
795 info[SN_ACE_NAME] = canon;
797 FreeAndClear(&info[SN_MODTIME], TRUE);
798 FreeAndClear(&info[SN_MODBY], TRUE);
799 FreeAndClear(&info[SN_MODWITH], TRUE);
802 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
805 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
808 FreeAndClear(&info[C_MODTIME], TRUE);
809 FreeAndClear(&info[C_MODBY], TRUE);
810 FreeAndClear(&info[C_MODWITH], TRUE);
813 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
816 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
820 if (GetValueFromUser("Container's Description:", &info[CON_DESCRIPT]) ==
823 if (GetValueFromUser("Container's Location:", &info[CON_LOCATION]) ==
826 if (GetValueFromUser("Container's Contact:", &info[CON_CONTACT]) ==
829 if (GetTypeFromUser("Container's owner type", "ace_type",
830 &info[CON_OWNER_TYPE]) == SUB_ERROR)
832 if (strcmp(info[CON_OWNER_TYPE], "NONE") &&
833 GetValueFromUser("Owner's Name", &info[CON_OWNER_NAME]) == SUB_ERROR)
835 if (!strcmp(info[CON_OWNER_TYPE], "KERBEROS"))
839 mrcl_validate_kerberos_member(info[CON_OWNER_NAME], &canon);
840 if (mrcl_get_message())
841 Put_message(mrcl_get_message());
842 free(info[CON_OWNER_NAME]);
843 info[CON_OWNER_NAME] = canon;
845 if (GetTypeFromUser("Container's Membership ACL", "ace_type",
846 &info[CON_MEMACE_TYPE]) == SUB_ERROR)
848 if (strcmp(info[CON_MEMACE_TYPE], "NONE") &&
849 GetValueFromUser("Membership ACL", &info[CON_MEMACE_NAME])
852 if (!strcmp(info[CON_MEMACE_TYPE], "KERBEROS"))
856 mrcl_validate_kerberos_member(info[CON_MEMACE_NAME], &canon);
857 if (mrcl_get_message())
858 Put_message(mrcl_get_message());
859 free(info[CON_MEMACE_NAME]);
860 info[CON_MEMACE_NAME] = canon;
862 FreeAndClear(&info[CON_MODTIME], TRUE);
863 FreeAndClear(&info[CON_MODBY], TRUE);
864 FreeAndClear(&info[CON_MODWITH], TRUE);
869 * Slide the newname into the #2 slot, this screws up all future references
873 SlipInNewName(info, newname);
878 /* ----------- Machine Menu ----------- */
880 /* Function Name: ShowMachineInfo
881 * Description: This function shows the information about a machine.
882 * Arguments: argc, argv - the name of the machine in argv[1].
883 * Returns: DM_NORMAL.
886 int ShowMachineInfo(int argc, char **argv)
891 tmpname = canonicalize_hostname(strdup(argv[1]));
892 top = GetMCInfo(MACHINE, tmpname, NULL);
893 Loop(top, ((void (*)(char **)) PrintMachInfo));
898 /* Function Name: ShowMachineQuery
899 * Description: This function shows the information about a machine.
900 * or group of machines, which may be selected through a
901 * number of criteria.
902 * Arguments: argc, argv - the name of the machine in argv[1],
903 * the address of the machine in argv[2],
904 * the location of the machine in argv[3],
905 * and the contact name in argv[4].
906 * any of these may be wildcards.
907 * Returns: DM_NORMAL.
910 int ShowMachineQuery(int argc, char **argv)
913 struct mqelem *top, *elem = NULL;
916 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
917 !strcmp(argv[3], "") && !strcmp(argv[4], ""))
919 Put_message("You must specify at least one parameter of the query.");
924 args[0] = canonicalize_hostname(strdup(argv[1]));
940 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
942 if (stat == MR_NO_MATCH)
943 Put_message("No machine(s) found matching query in the database.");
945 com_err(program_name, stat, " in get_machine.");
948 top = QueueTop(elem);
949 Loop(top, ((void (*)(char **)) PrintMachInfo));
954 /* Function Name: AddMachine
955 * Description: This function adds a new machine to the database.
956 * Arguments: argc, argv - the name of the network in argv[1].
957 * Returns: DM_NORMAL.
960 int AddMachine(int argc, char **argv)
962 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
964 struct mqelem *elem = NULL;
967 if (!ValidName(argv[1])) /* Checks for wildcards. */
971 * get the network record
974 if (strcasecmp(argv[1], "none") &&
975 (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem)))
977 if (stat == MR_NO_MATCH)
980 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
983 com_err(program_name, stat, " in get_subnet.");
988 * Check to see if this machine already exists.
991 name = strdup(""); /* want to put prefix here */
992 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
995 name = canonicalize_hostname(strdup(name));
998 xargs[1] = xargs[2] = xargs[3] = "*";
999 if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL)))
1001 sprintf(buf, "The machine '%s' already exists.", name);
1006 else if (stat != MR_NO_MATCH)
1008 com_err(program_name, stat,
1009 " while checking machine '%s' in AddMachine.", name);
1013 rinfo = SetMachineDefaults(info, name);
1014 rinfo[M_SUBNET] = strdup(argv[1]);
1015 if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
1017 Put_message("Aborted.");
1022 * Actually create the new Machine.
1025 if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL)))
1026 com_err(program_name, stat, " in AddMachine.");
1033 /* Function Name: RealUpdateMachine
1034 * Description: Performs the actual update of the machine data.
1035 * Arguments: info - the information on the machine to update.
1036 * junk - an UNUSED Boolean.
1040 static void RealUpdateMachine(char **info, Bool junk)
1043 char **args = AskMCDInfo(info, MACHINE, TRUE);
1046 Put_message("Aborted.");
1049 if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL)))
1050 com_err(program_name, stat, " in UpdateMachine.");
1052 Put_message("Machine successfully updated.");
1055 /* Function Name: UpdateMachine
1056 * Description: This function adds a new machine to the database.
1057 * Arguments: argc, argv - the name of the machine in argv[1].
1058 * Returns: DM_NORMAL.
1061 int UpdateMachine(int argc, char **argv)
1066 tmpname = canonicalize_hostname(strdup(argv[1]));
1067 top = GetMCInfo(MACHINE, tmpname, NULL);
1068 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
1075 /* Function Name: CheckAndRemoveFromCluster
1076 * Description: This func tests to see if a machine is in a cluster.
1077 * and if so then removes it
1078 * Arguments: name - name of the machine (already Canonicalized).
1079 * ask_user- query the user before removing if from clusters?
1080 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
1083 int CheckAndRemoveFromCluster(char *name, Bool ask_user)
1085 int stat, ret_value;
1087 char *args[10], temp_buf[BUFSIZ], *ptr;
1088 struct mqelem *top, *elem = NULL;
1090 ret_value = SUB_NORMAL; /* initialize ret_value. */
1093 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1094 if (stat && stat != MR_NO_MATCH)
1096 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1099 if (stat == MR_SUCCESS)
1101 elem = top = QueueTop(elem);
1104 sprintf(temp_buf, "%s is assigned to the following clusters.", name);
1105 Put_message(temp_buf);
1106 Loop(top, (void (*)(char **)) PrintMCMap);
1107 ptr = "Remove this machine from ** ALL ** these clusters?";
1108 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1112 Put_message("Aborting...");
1124 char **info = elem->q_data;
1125 if ((stat = do_mr_query("delete_machine_from_cluster",
1126 2, info, NULL, NULL)))
1128 ret_value = SUB_ERROR;
1129 com_err(program_name, stat,
1130 " in delete_machine_from_cluster.");
1132 "Machine %s ** NOT ** removed from cluster %s.",
1133 info[MAP_MACHINE], info[MAP_CLUSTER]);
1134 Put_message(temp_buf);
1136 elem = elem->q_forw;
1143 /* Function Name: CheckAndRemoveCnames
1144 * Description: This func tests to see if a machine has cnames,
1145 * and if so then removes them.
1146 * Arguments: name - name of the machine (already Canonicalized).
1147 * ask_user- query the user before removing cnames?
1148 * Returns: MR_ERROR if machine left with a cname, or mr_error.
1151 int CheckAndRemoveCnames(char *name, Bool ask_user)
1153 int stat, ret_value;
1155 char *args[10], temp_buf[BUFSIZ], *ptr;
1156 struct mqelem *top, *elem = NULL;
1158 ret_value = SUB_NORMAL;
1161 stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem);
1162 if (stat && stat != MR_NO_MATCH)
1164 com_err(program_name, stat, " in get_hostalias.");
1167 if (stat == MR_SUCCESS)
1169 elem = top = QueueTop(elem);
1172 sprintf(temp_buf, "%s has the following cnames.", name);
1173 Put_message(temp_buf);
1174 Loop(top, (void (*)(char **)) PrintCname);
1175 ptr = "Remove ** ALL ** these cnames?";
1176 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1180 Put_message("Aborting...");
1192 char **info = elem->q_data;
1193 if ((stat = do_mr_query("delete_hostalias", 2, info,
1196 ret_value = SUB_ERROR;
1197 com_err(program_name, stat, " in delete_hostalias.");
1199 "Cname %s ** NOT ** removed from host %s.",
1201 Put_message(temp_buf);
1203 elem = elem->q_forw;
1210 /* Function Name: RealDeleteMachine
1211 * Description: Actually Deletes the Machine.
1212 * Arguments: info - nescessary information stored as an array of char *'s
1213 * one_machine - a boolean, true if there is only one item in
1218 static void RealDeleteMachine(char **info, Bool one_machine)
1221 char temp_buf[BUFSIZ];
1223 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
1225 if (!one_machine || Confirm(temp_buf))
1227 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
1229 if (CheckAndRemoveCnames(info[M_NAME], TRUE) != SUB_ERROR)
1231 if ((stat = do_mr_query("delete_host", 1,
1232 &info[M_NAME], NULL, NULL)))
1234 com_err(program_name, stat, " in DeleteMachine.");
1235 sprintf(temp_buf, "%s ** NOT ** deleted.",
1237 Put_message(temp_buf);
1241 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
1242 Put_message(temp_buf);
1249 /* Function Name: DeleteMachine
1250 * Description: This function removes a machine from the data base.
1251 * Arguments: argc, argv - the machines name int argv[1].
1252 * Returns: DM_NORMAL.
1255 /* Perhaps we should remove the cluster if it has no machine now. */
1257 int DeleteMachine(int argc, char **argv)
1262 tmpname = canonicalize_hostname(strdup(argv[1]));
1263 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
1264 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
1271 /* Function Name: ShowCname
1272 * Description: This function shows machine aliases
1273 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1274 * Returns: DM_NORMAL.
1277 int ShowCname(int argc, char **argv)
1280 char *tmpalias, *tmpname;
1282 tmpalias = partial_canonicalize_hostname(strdup(argv[1]));
1283 tmpname = canonicalize_hostname(strdup(argv[2]));
1284 top = GetMCInfo(CNAME, tmpalias, tmpname);
1285 Put_message(""); /* blank line on screen */
1286 Loop(top, ((void (*)(char **)) PrintCname));
1292 int AddCname(int argc, char **argv)
1297 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1298 args[1] = canonicalize_hostname(strdup(argv[2]));
1299 stat = do_mr_query("add_hostalias", 2, args, NULL, NULL);
1305 Put_message("That alias name is already in use.");
1308 Put_message("Permission denied. "
1309 "(Regular users can only add two aliases to a host.");
1312 com_err(program_name, stat, " in add_hostalias");
1318 int DeleteCname(int argc, char **argv)
1323 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1324 args[1] = canonicalize_hostname(strdup(argv[2]));
1325 stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL);
1327 com_err(program_name, stat, " in delete_hostalias");
1332 /* Function Name: AddMachineToCluster
1333 * Description: This function adds a machine to a cluster
1334 * Arguments: argc, argv - The machine name is argv[1].
1335 * The cluster name in argv[2].
1336 * Returns: DM_NORMAL.
1339 int AddMachineToCluster(int argc, char **argv)
1342 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1343 Bool add_it, one_machine, one_cluster;
1344 struct mqelem *melem, *mtop, *celem, *ctop;
1346 machine = canonicalize_hostname(strdup(argv[1]));
1347 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1349 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1351 Put_message(temp_buf);
1355 celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1356 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1359 one_machine = (QueueCount(mtop) == 1);
1360 one_cluster = (QueueCount(ctop) == 1);
1362 /* No good way to use QueryLoop() here, sigh */
1366 char **minfo = melem->q_data;
1369 char **cinfo = celem->q_data;
1370 if (one_machine && one_cluster)
1374 sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1375 minfo[M_NAME], cinfo[C_NAME]);
1376 switch (YesNoQuitQuestion(temp_buf, FALSE))
1385 Put_message("Aborting...");
1393 args[0] = minfo[M_NAME];
1394 args[1] = cinfo[C_NAME];
1395 stat = do_mr_query("add_machine_to_cluster", 2, args,
1402 sprintf(temp_buf, "%s is already in cluster %s",
1403 minfo[M_NAME], cinfo[C_NAME]);
1404 Put_message(temp_buf);
1407 com_err(program_name, stat, " in AddMachineToCluster.");
1411 celem = celem->q_forw;
1413 celem = ctop; /* reset cluster element. */
1414 melem = melem->q_forw;
1421 /* Function Name: RealRemoveMachineFromCluster
1422 * Description: This function actually removes the machine from its
1424 * Arguments: info - all information nescessary to perform the removal.
1425 * one_map - True if there is only one case, and we should
1430 static void RealRemoveMachineFromCluster(char **info, Bool one_map)
1432 char temp_buf[BUFSIZ];
1435 sprintf(temp_buf, "Remove %s from the cluster %s",
1436 info[MAP_MACHINE], info[MAP_CLUSTER]);
1437 if (!one_map || Confirm(temp_buf))
1439 if ((stat = do_mr_query("delete_machine_from_cluster", 2,
1441 com_err(program_name, stat, " in delete_machine_from_cluster");
1444 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1445 info[MAP_MACHINE], info[MAP_CLUSTER]);
1446 Put_message(temp_buf);
1450 Put_message("Machine not removed.");
1453 /* Function Name: RemoveMachineFromCluster
1454 * Description: Removes this machine form a specific cluster.
1455 * Arguments: argc, argv - Name of machine in argv[1].
1456 * Name of cluster in argv[2].
1460 int RemoveMachineFromCluster(int argc, char **argv)
1462 struct mqelem *elem = NULL;
1463 char buf[BUFSIZ], *args[10];
1466 args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1]));
1467 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1469 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1470 argv[1], args[MAP_MACHINE]);
1473 args[MAP_CLUSTER] = argv[2];
1474 args[MAP_END] = NULL;
1476 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1478 if (stat == MR_NO_MATCH)
1480 sprintf(buf, "The machine %s is not in the cluster %s.",
1481 args[MAP_MACHINE], args[MAP_CLUSTER]);
1483 free(args[MAP_MACHINE]);
1486 if (stat != MR_SUCCESS)
1487 com_err(program_name, stat, " in delete_machine_from_cluster");
1489 elem = QueueTop(elem);
1490 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1491 "Remove this machine from this cluster");
1494 free(args[MAP_MACHINE]);
1498 /* ---------- Subnet Menu -------- */
1500 /* Function Name: ShowSubnetInfo
1501 * Description: Gets information about a subnet given its name.
1502 * Arguments: argc, argc - the name of the subnet in in argv[1].
1503 * Returns: DM_NORMAL.
1506 int ShowSubnetInfo(int argc, char **argv)
1510 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1511 Loop(top, (void (*)(char **)) PrintSubnetInfo);
1516 /* Function Name: AddSubnet
1517 * Description: Creates a new subnet.
1518 * Arguments: argc, argv - the name of the new subnet is argv[1].
1519 * Returns: DM_NORMAL.
1522 int AddSubnet(int argc, char **argv)
1524 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1528 * Check to see if this subnet already exists.
1530 if (!ValidName(name))
1533 if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS)
1535 Put_message("This subnet already exists.");
1538 else if (stat != MR_NO_MATCH)
1540 com_err(program_name, stat, " in AddSubnet.");
1543 if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1545 Put_message("Aborted.");
1551 * Actually create the new Subnet.
1553 if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL)))
1554 com_err(program_name, stat, " in AddSubnet.");
1560 /* Function Name: RealUpdateSubnet
1561 * Description: This function actually performs the subnet update.
1562 * Arguments: info - all information nesc. for updating the subnet.
1563 * junk - an UNUSED boolean.
1567 static void RealUpdateSubnet(char **info, Bool junk)
1570 char **args = AskMCDInfo(info, SUBNET, TRUE);
1573 Put_message("Aborted.");
1576 if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL)))
1577 com_err(program_name, stat, " in UpdateSubnet.");
1579 Put_message("Subnet successfully updated.");
1582 /* Function Name: UpdateSubnet
1583 * Description: This Function Updates a subnet
1584 * Arguments: name of the subnet in argv[1].
1585 * Returns: DM_NORMAL.
1588 int UpdateSubnet(int argc, char **argv)
1591 top = GetMCInfo(SUBNET, argv[1], NULL);
1592 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1598 /* Function Name: RealDeleteSubnet
1599 * Description: Actually performs the subnet deletion.
1600 * Arguments: info - all information about this subnet.
1601 * one_subnet - If true then there was only one subnet in
1602 * the queue, and we should confirm.
1606 static void RealDeleteSubnet(char **info, Bool one_subnet)
1609 char temp_buf[BUFSIZ];
1612 "Are you sure the you want to delete the subnet %s (y/n) ?",
1614 if (!one_subnet || Confirm(temp_buf))
1616 if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL)))
1618 com_err(program_name, stat, " in delete_subnet.");
1619 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1620 Put_message(temp_buf);
1624 sprintf(temp_buf, "subnet %s successfully deleted.",
1626 Put_message(temp_buf);
1631 /* Function Name: DeleteSubnet
1632 * Description: This function removes a subnet from the database.
1633 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1634 * Returns: DM_NORMAL.
1637 int DeleteSubnet(int argc, char **argv)
1641 top = GetMCInfo(SUBNET, argv[1], NULL);
1642 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1648 /* ---------- Cluster Menu -------- */
1650 /* Function Name: ShowClusterInfo
1651 * Description: Gets information about a cluser given its name.
1652 * Arguments: argc, argc - the name of the cluster in in argv[1].
1653 * Returns: DM_NORMAL.
1656 int ShowClusterInfo(int argc, char **argv)
1660 top = GetMCInfo(CLUSTER, argv[1], NULL);
1661 Loop(top, (void (*)(char **)) PrintClusterInfo);
1666 /* Function Name: AddCluster
1667 * Description: Creates a new cluster.
1668 * Arguments: argc, argv - the name of the new cluster is argv[1].
1669 * Returns: DM_NORMAL.
1672 int AddCluster(int argc, char **argv)
1674 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1678 * Check to see if this cluster already exists.
1680 if (!ValidName(name))
1683 if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS)
1685 Put_message("This cluster already exists.");
1688 else if (stat != MR_NO_MATCH)
1690 com_err(program_name, stat, " in AddCluster.");
1693 if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1695 Put_message("Aborted.");
1701 * Actually create the new Cluster.
1703 if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL)))
1704 com_err(program_name, stat, " in AddCluster.");
1710 /* Function Name: RealUpdateCluster
1711 * Description: This function actually performs the cluster update.
1712 * Arguments: info - all information nesc. for updating the cluster.
1713 * junk - an UNUSED boolean.
1717 static void RealUpdateCluster(char **info, Bool junk)
1720 char **args = AskMCDInfo(info, CLUSTER, TRUE);
1724 Put_message("Aborted.");
1727 if ((stat = do_mr_query("update_cluster", CountArgs(args),
1729 com_err(program_name, stat, " in UpdateCluster.");
1731 Put_message("Cluster successfully updated.");
1734 /* Function Name: UpdateCluster
1735 * Description: This Function Updates a cluster
1736 * Arguments: name of the cluster in argv[1].
1737 * Returns: DM_NORMAL.
1740 int UpdateCluster(int argc, char **argv)
1743 top = GetMCInfo(CLUSTER, argv[1], NULL);
1744 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1750 /* Function Name: CheckAndRemoveMachine
1751 * Description: This function checks and removes all machines from a
1753 * Arguments: name - name of the cluster.
1754 * ask_first - if TRUE, then we will query the user, before
1756 * Returns: SUB_ERROR if all machines not removed.
1759 int CheckAndRemoveMachines(char *name, Bool ask_first)
1761 int stat, ret_value;
1763 char *args[10], temp_buf[BUFSIZ], *ptr;
1764 struct mqelem *top, *elem = NULL;
1766 ret_value = SUB_NORMAL;
1767 args[MAP_MACHINE] = "*";
1768 args[MAP_CLUSTER] = name;
1769 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1770 if (stat && stat != MR_NO_MATCH)
1772 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1775 if (stat == MR_SUCCESS)
1777 elem = top = QueueTop(elem);
1780 sprintf(temp_buf, "The cluster %s has the following machines in it:",
1782 Put_message(temp_buf);
1785 char **info = elem->q_data;
1786 Print(1, &info[MAP_MACHINE], (char *) NULL);
1787 elem = elem->q_forw;
1789 ptr = "Remove ** ALL ** these machines from this cluster?";
1791 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1795 Put_message("Aborting...");
1808 char **info = elem->q_data;
1809 if ((stat = do_mr_query("delete_machine_from_cluster",
1810 2, info, NULL, NULL)))
1812 ret_value = SUB_ERROR;
1813 com_err(program_name, stat,
1814 " in delete_machine_from_cluster.");
1816 "Machine %s ** NOT ** removed from cluster %s.",
1817 info[MAP_MACHINE], info[MAP_CLUSTER]);
1818 Put_message(temp_buf);
1820 elem = elem->q_forw;
1827 /* Function Name: RealDeleteCluster
1828 * Description: Actually performs the cluster deletion.
1829 * Arguments: info - all information about this cluster.
1830 * one_cluster - If true then there was only one cluster in
1831 * the queue, and we should confirm.
1835 static void RealDeleteCluster(char **info, Bool one_cluster)
1838 char temp_buf[BUFSIZ];
1841 "Are you sure the you want to delete the cluster %s (y/n) ?",
1843 if (!one_cluster || Confirm(temp_buf))
1845 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1847 if ((stat = do_mr_query("delete_cluster", 1,
1848 &info[C_NAME], NULL, NULL)))
1850 com_err(program_name, stat, " in delete_cluster.");
1851 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1852 Put_message(temp_buf);
1856 sprintf(temp_buf, "cluster %s successfully deleted.",
1858 Put_message(temp_buf);
1864 /* Function Name: DeleteCluster
1865 * Description: This function removes a cluster from the database.
1866 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1867 * Returns: DM_NORMAL.
1870 int DeleteCluster(int argc, char **argv)
1874 top = GetMCInfo(CLUSTER, argv[1], NULL);
1875 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1881 /* ----------- Cluster Data Menu -------------- */
1883 /* Function Name: ShowClusterData
1884 * Description: This function shows the services for one cluster.
1885 * Arguments: argc, argv - The name of the cluster is argv[1].
1886 * The label of the data in argv[2].
1887 * Returns: DM_NORMAL.
1890 int ShowClusterData(int argc, char **argv)
1892 struct mqelem *elem, *top;
1895 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1898 info = elem->q_data;
1899 PrintClusterData(info);
1900 elem = elem->q_forw;
1906 /* Function Name: AddClusterData
1907 * Description: This function adds some data to the cluster.
1908 * Arguments: argv, argc: argv[1] - the name of the cluster.
1909 * argv[2] - the label of the data.
1910 * argv[3] - the data.
1911 * Returns: DM_NORMAL.
1914 int AddClusterData(int argc, char **argv)
1918 for (i = 1; i < 4; i++)
1920 if (IS_EMPTY(argv[i]))
1922 Put_message("Cluster data cannot be an empty string.");
1926 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
1927 com_err(program_name, stat, " in AddClusterData.");
1931 /* Function Name: RealRemoveClusterData
1932 * Description: actually removes the cluster data.
1933 * Arguments: info - all info necessary to remove the cluster, in an array
1935 * one_item - if true then the queue has only one elem and we
1940 static void RealRemoveClusterData(char **info, Bool one_item)
1946 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1947 PrintClusterData(info);
1948 if (!one_item || Confirm(temp_ptr))
1950 if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
1952 com_err(program_name, stat, " in DeleteClusterData.");
1953 Put_message("Data not removed.");
1956 Put_message("Removal successful.");
1960 /* Function Name: RemoveClusterData
1961 * Description: This function removes data on a given cluster.
1962 * Arguments: argv, argc: argv[1] - the name of the cluster.
1963 * argv[2] - the label of the data.
1964 * argv[3] - the data.
1965 * Returns: DM_NORMAL.
1968 int RemoveClusterData(int argc, char **argv)
1972 top = GetMCInfo(DATA, argv[1], argv[2]);
1973 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1974 "Remove data from cluster");
1980 /* Function Name: MachineToClusterMap
1981 * Description: This Retrieves the mapping between machine and cluster
1982 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1983 * argv[2] -> cluster name or wildcard.
1987 int MachineToClusterMap(int argc, char **argv)
1989 struct mqelem *elem, *top;
1990 char *tmpname, temp_buf[256];
1992 tmpname = canonicalize_hostname(strdup(argv[1]));
1993 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
1995 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1997 Put_message(temp_buf);
1999 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
2001 Put_message(""); /* blank line on screen */
2004 char **info = elem->q_data;
2006 elem = elem->q_forw;
2014 /* Function Name: MachineByOwner
2015 * Description: This function prints all machines which are owned by
2016 * a given user or group.
2018 * Returns: DM_NORMAL.
2021 int MachineByOwner(int argc, char **argv)
2023 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
2026 type = strdup("USER");
2027 if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR)
2030 sprintf(buf, "Name of %s", type);
2031 name = strdup(user);
2032 if (GetValueFromUser(buf, &name) == SUB_ERROR)
2035 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
2038 sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */
2040 type = strdup(temp_buf);
2048 top = GetMachineByOwner(type, name);
2049 Loop(top, PrintMachine);
2055 /* Function Name: GetMachineByOwner
2056 * Description: This function stores information retrieved by
2057 * the get_host_by_owner query
2058 * Arguments: type - an ace_type, argv[0] for the query
2059 * name - name of machine, argv[1] for the query
2060 * Returns: the top element of a queue returning the data, or NULL.
2063 struct mqelem *GetMachineByOwner(char *type, char *name)
2066 struct mqelem *elem = NULL;
2071 if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem)))
2073 com_err(program_name, status, " in get_host_by_owner");
2076 return QueueTop(elem);
2079 int MachineByAcctNumber(int argc, char **argv)
2081 char *args[1], *account_number;
2083 struct mqelem *elem = NULL;
2085 account_number = strdup("");
2086 if (GetValueFromUser("Account Number", &account_number) == SUB_ERROR)
2089 args[0] = account_number;
2090 if (status = do_mr_query("get_host_by_account_number", 1, args, StoreInfo,
2093 com_err(program_name, status, " in get_host_by_account_number");
2096 Loop(QueueTop(elem), (void (*)(char **)) PrintMachInfo);
2102 int ShowContainerInfo(int argc, char **argv)
2106 top = GetMCInfo(CONTAINER, argv[1], NULL);
2107 Loop(top, (void (*)(char **)) PrintContainerInfo);
2112 static char *PrintContainerInfo(char **info)
2114 char buf[BUFSIZ], tbuf[256];
2117 sprintf(buf, "Container: %-16s", info[CON_NAME]);
2119 sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]);
2121 sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION],
2124 sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE],
2125 strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : "");
2126 sprintf(buf, "Owner: %-16s", tbuf);
2128 sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE],
2129 strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : "");
2130 sprintf(buf, "Membership ACL: %-16s", tbuf);
2133 sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME],
2136 return info[CON_NAME];
2139 static char *PrintContainer(char **info)
2143 sprintf(buf, "Container: %s", info[CON_NAME]);
2148 static char *PrintMContMap(char **info)
2151 sprintf(buf, "Container: %-30s Machine: %-20s",
2157 int AddContainer(int argc, char **argv)
2159 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
2162 /* Can't use ValidName() because spaces are allowed in container names */
2165 Put_message("Please use a non-empty name.");
2169 if (strchr(name, '*') || strchr(name, '?'))
2171 Put_message("Wildcards not accepted here.");
2175 /* Check if this cluster already exists. */
2176 if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL))
2179 Put_message("This container already exists.");
2182 else if (stat != MR_NO_MATCH)
2184 com_err(program_name, stat, " in AddContainer.");
2187 if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE)))
2189 Put_message("Aborted.");
2194 /* Create the new container. */
2195 if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL)))
2196 com_err(program_name, stat, " in AddContainer.");
2202 int UpdateContainer(int argc, char **argv)
2205 top = GetMCInfo(CONTAINER, argv[1], NULL);
2206 QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container");
2212 static void RealUpdateContainer(char **info, Bool junk)
2215 char **args = AskMCDInfo(info, CONTAINER, TRUE);
2219 Put_message("Aborted.");
2222 if ((stat = do_mr_query("update_container", CountArgs(args), args,
2224 com_err(program_name, stat, " in UpdateContainer.");
2226 Put_message("Container successfully updated.");
2229 int DeleteContainer(int argc, char **argv)
2233 top = GetMCInfo(CONTAINER, argv[1], NULL);
2234 QueryLoop(top, PrintClusterInfo, RealDeleteContainer,
2235 "Delete the container");
2241 static void RealDeleteContainer(char **info, Bool one_container)
2244 char temp_buf[BUFSIZ];
2247 "Are you sure you want to delete the container %s (y/n) ?",
2249 if (!one_container || Confirm(temp_buf))
2251 if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE)
2254 if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME],
2257 com_err(program_name, stat, " in delete_container.");
2258 sprintf(temp_buf, "Container %s ** NOT ** deleted.",
2260 Put_message(temp_buf);
2264 sprintf(temp_buf, "Container %s successfully deleted.",
2266 Put_message(temp_buf);
2272 int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first)
2274 int stat, ret_value;
2276 char *args[10], temp_buf[BUFSIZ], *ptr;
2277 struct mqelem *top, *elem = NULL;
2279 ret_value = SUB_NORMAL;
2282 stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo,
2284 if (stat && stat != MR_NO_MATCH)
2286 com_err(program_name, stat, " in get_machines_of_container");
2289 if (stat == MR_SUCCESS)
2291 elem = top = QueueTop(elem);
2295 "The container %s has the following machines in it:", name);
2296 Put_message(temp_buf);
2299 char **info = elem->q_data;
2300 Print(1, &info[0], (char *) NULL);
2301 elem = elem->q_forw;
2303 ptr = "Remove ** ALL ** these machines from this container?";
2305 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
2309 Put_message("Aborting...");
2322 char **info = elem->q_data;
2323 if ((stat = do_mr_query("delete_machine_from_container",
2324 2, info, NULL, NULL)))
2326 ret_value = SUB_ERROR;
2327 com_err(program_name, stat,
2328 " in delete_machine_from_container.");
2330 "Machine %s ** NOT ** removed from container %s.",
2332 Put_message(temp_buf);
2334 elem = elem->q_forw;
2341 int GetSubContainers(int argc, char **argv)
2344 struct mqelem *elem = NULL, *top = NULL;
2349 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2354 if (stat = do_mr_query("get_subcontainers_of_container", 2, args,
2356 com_err(program_name, stat, " in get_subcontainers_of_container");
2358 top = QueueTop(elem);
2359 Loop(top, ((void (*)(char **)) PrintContainer));
2364 int MachineToContainerMap(int argc, char **argv)
2366 struct mqelem *elem, *top;
2367 char *tmpname, temp_buf[256];
2369 tmpname = canonicalize_hostname(strdup(argv[1]));
2370 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2372 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2374 Put_message(temp_buf);
2376 top = elem = GetMCInfo(CONTMAP, tmpname, NULL);
2381 char **info = elem->q_data;
2382 PrintMContMap(info);
2383 elem = elem->q_forw;
2391 int AddMachineToContainer(int argc, char **argv)
2394 char *machine, *container, temp_buf[BUFSIZ], *args[10];
2395 Bool add_it, one_machine, one_container;
2396 struct mqelem *melem, *mtop, *celem, *ctop;
2398 machine = canonicalize_hostname(strdup(argv[1]));
2399 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
2401 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2403 Put_message(temp_buf);
2405 container = argv[2];
2407 celem = ctop = GetMCInfo(CONTAINER, container, NULL);
2408 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
2411 one_machine = (QueueCount(mtop) == 1);
2412 one_container = (QueueCount(ctop) == 1);
2416 char **minfo = melem->q_data;
2419 char **cinfo = celem->q_data;
2420 if (one_machine && one_container)
2424 sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?",
2425 minfo[M_NAME], cinfo[CON_NAME]);
2426 switch (YesNoQuestion(temp_buf, FALSE))
2435 Put_message("Aborting...");
2443 args[0] = minfo[M_NAME];
2444 args[1] = cinfo[CON_NAME];
2445 stat = do_mr_query("add_machine_to_container", 2, args, NULL,
2452 sprintf(temp_buf, "%s is already in container %s",
2453 minfo[M_NAME], cinfo[CON_NAME]);
2454 Put_message(temp_buf);
2457 com_err(program_name, stat, " in AddMachineToContainer.");
2461 celem = celem->q_forw;
2464 melem = melem->q_forw;
2471 int RemoveMachineFromContainer(int argc, char **argv)
2473 struct mqelem *elem = NULL;
2474 char buf[BUFSIZ], *args[10];
2477 args[0] = canonicalize_hostname(strdup(argv[1]));
2478 if (strcasecmp(args[0], argv[1]) && *argv[1] != '"')
2480 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
2487 stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo,
2489 if (stat == MR_NO_MATCH)
2491 sprintf(buf, "The machine %s is not in the container %s.",
2497 if (stat != MR_SUCCESS)
2498 com_err(program_name, stat, " in deleter_machine_from_container");
2500 elem = QueueTop(elem);
2501 QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer,
2502 "Remove this machine from this container");
2509 static void RealRemoveMachineFromContainer(char **info, Bool one_contmap)
2511 char temp_buf[BUFSIZ];
2514 sprintf(temp_buf, "Remove %s from the container %s",
2516 if (!one_contmap || Confirm(temp_buf))
2518 if ((stat = do_mr_query("delete_machine_from_container", 2,
2520 com_err(program_name, stat, " in delete_machine_from_container");
2523 sprintf(temp_buf, "%s has been removed from the container %s.",
2525 Put_message(temp_buf);
2529 Put_message("Machine not removed.");
2532 int GetMachinesOfContainer(int argc, char **argv)
2535 struct mqelem *elem = NULL, *top = NULL;
2540 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2545 if (stat = do_mr_query("get_machines_of_container", 2, args,
2547 com_err(program_name, stat, " in get_machines_of_container");
2549 top = QueueTop(elem);
2550 Loop(top, ((void (*)(char **)) PrintMContMap));
2555 int GetTopLevelCont(int argc, char **argv)
2558 struct mqelem *elem = NULL;
2559 if (status = do_mr_query("get_toplevel_containers", 0, NULL, StoreInfo,
2562 com_err(program_name, status, " in get_toplevel_containers");
2565 Loop(QueueTop(elem), (void(*)(char **)) PrintContainer);