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[16] = info[17] = 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 sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0")));
195 info[SN_ADDRESS] = strdup(buf);
196 sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0")));
197 info[SN_MASK] = strdup(buf);
198 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW)));
199 info[SN_LOW] = strdup(buf);
200 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH)));
201 info[SN_HIGH] = strdup(buf);
202 info[SN_PREFIX] = strdup("");
203 info[SN_ACE_TYPE] = strdup("LIST");
204 info[SN_ACE_NAME] = strdup("network");
205 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
209 /* -------------------- General Functions -------------------- */
211 static char aliasbuf[256];
213 void PrintAliases(char **info)
215 if (strlen(aliasbuf) == 0)
216 sprintf(aliasbuf, "Aliases: %s", info[0]);
219 strcat(aliasbuf, ", ");
220 strcat(aliasbuf, info[0]);
225 /* Function Name: PrintMachInfo
226 * Description: This function Prints out the Machine info in
228 * Arguments: info - array of information about a machine.
229 * Returns: The name of the Machine
232 static char *PrintMachInfo(char **info)
234 char buf[BUFSIZ], tbuf[256];
236 struct mqelem *elem = NULL;
240 sprintf(buf, "Machine: %s", info[M_NAME]);
243 args[1] = info[M_NAME];
244 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
246 if (stat != MR_NO_MATCH)
247 com_err(program_name, stat, " looking up aliases");
252 Loop(QueueTop(elem), (void (*)(char **)) PrintAliases);
254 Put_message(aliasbuf);
256 sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
257 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
258 sprintf(buf, "Address: %-16s Network: %-16s",
259 info[M_ADDR], info[M_SUBNET]);
261 sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]);
263 sprintf(buf, "Status: %-16s Changed: %s",
264 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
267 sprintf(buf, "Vendor: %-16s Location: %s", info[M_VENDOR],
270 sprintf(buf, "Model: %-16s Contact: %s", info[M_MODEL],
273 sprintf(buf, "OS: %-16s Billing Contact: %s", info[M_OS],
274 info[M_BILL_CONTACT]);
276 sprintf(buf, "Opt: %-16s Account Number: %s", info[M_USE],
277 info[M_ACCT_NUMBER]);
280 sprintf(buf, "Adm cmt: %s", info[M_ACOMMENT]);
282 sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]);
285 sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]);
287 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
292 /* Function Name: PrintMachine
293 * Description: Prints the name of a machine record
294 * Arguments: info - array of information about the machine.
298 static void PrintMachine(char **info)
302 sprintf(buf, "Machine: %s", info[M_NAME]);
306 /* Function Name: PrintCname
307 * Description: Prints the Data on a host alias
308 * Arguments: info a pointer to the data array.
309 * Returns: The name of the alias.
312 static char *PrintCname(char **info)
316 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
321 /* Function Name: PrintClusterInfo
322 * Description: This function Prints out the cluster info
323 * in a coherent form.
324 * Arguments: info - array of information about a cluster.
325 * Returns: The name of the cluster.
328 static char *PrintClusterInfo(char **info)
333 sprintf(buf, "Cluster: %s", info[C_NAME]);
335 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
337 sprintf(buf, "Location: %s", info[C_LOCATION]);
339 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
344 /* Function Name: PrintClusterData
345 * Description: Prints the Data on a cluster
346 * Arguments: info a pointer to the data array.
347 * Returns: The name of the cluster.
350 static char *PrintClusterData(char **info)
355 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
356 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
358 return info[CD_NAME];
361 /* Function Name: PrintMCMap
362 * Description: Prints the data about a machine to cluster mapping.
363 * Arguments: info a pointer to the data array.
367 static char *PrintMCMap(char **info)
370 sprintf(buf, "Cluster: %-30s Machine: %-20s",
371 info[MAP_CLUSTER], info[MAP_MACHINE]);
373 return ""; /* Used by QueryLoop(). */
376 /* Function Name: PrintSubnetInfo
377 * Description: This function Prints out the subnet info
378 * in a coherent form.
379 * Arguments: info - array of information about a subnet.
380 * Returns: The name of the subnet.
383 static char *PrintSubnetInfo(char **info)
386 struct in_addr addr, mask, low, high;
389 sprintf(buf, " Network: %s", info[SN_NAME]);
391 sprintf(buf, " Description: %s", info[SN_DESC]);
393 sprintf(buf, " Status: %s", SubnetState(atoi(info[SN_STATUS])));
395 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
396 mask.s_addr = htonl(atoi(info[SN_MASK]));
397 low.s_addr = htonl(atoi(info[SN_LOW]));
398 high.s_addr = htonl(atoi(info[SN_HIGH]));
399 /* screwy sequence is here because inet_ntoa returns a pointer to
400 a static buf. If it were all one sprintf, the last value would
402 sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr));
403 strcat(buf, inet_ntoa(mask));
404 strcat(buf, "\n High: ");
405 strcat(buf, inet_ntoa(high));
406 strcat(buf, " Low: ");
407 strcat(buf, inet_ntoa(low));
409 sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
411 sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE],
412 strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : "");
414 sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]);
416 return info[SN_NAME];
419 /* Function Name: GetMCInfo.
420 * Description: This function stores info about a machine.
421 * type - type of data we are trying to retrieve.
422 * name1 - the name of argv[0] for the call.
423 * name2 - the name of argv[1] for the call.
424 * Returns: the top element of a queue containing the data or NULL.
427 struct mqelem *GetMCInfo(int type, char *name1, char *name2)
430 struct mqelem *elem = NULL;
437 args[1] = args[2] = args[3] = "*";
438 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
440 if (stat == MR_NO_MATCH)
443 sprintf(buf, "Machine '%s' is not in the database.", name1);
447 com_err(program_name, stat, " in get_machine.");
454 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
456 com_err(program_name, stat, " in get_hostalias.");
461 if ((stat = do_mr_query("get_subnet", 1, &name1, StoreInfo, &elem)))
463 if (stat == MR_NO_MATCH)
466 sprintf(buf, "Network '%s' is not in the database.", name1);
470 com_err(program_name, stat, " in get_subnet.");
475 if ((stat = do_mr_query("get_cluster", 1, &name1, StoreInfo, &elem)))
477 com_err(program_name, stat, " in get_cluster.");
482 args[MAP_MACHINE] = name1;
483 args[MAP_CLUSTER] = name2;
484 if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args,
487 com_err(program_name, stat, " in get_machine_to_cluster_map.");
492 args[CD_NAME] = name1;
493 args[CD_LABEL] = name2;
494 if ((stat = do_mr_query("get_cluster_data", 2, args, StoreInfo, &elem)))
496 com_err(program_name, stat, " in get_cluster_data.");
501 args[CON_NAME] = name1;
502 if ((stat = do_mr_query("get_container", 1, &name1, StoreInfo, &elem)))
504 com_err(program_name, stat, " in get_container.");
510 if ((stat = do_mr_query("get_machine_to_container_map", 1, &name1,
513 com_err(program_name, stat, " in get_machine_to_container_map.");
517 return QueueTop(elem);
520 /* Function Name: AskMCDInfo.
521 * Description: This function askes the user for information about a
522 * machine and saves it into a structure.
523 * Arguments: info - a pointer the information to ask about
524 * type - type of information - MACHINE
528 * name - T/F : change the name of this type.
532 char **AskMCDInfo(char **info, int type, Bool name)
534 char temp_buf[BUFSIZ], *newname, *oldnewname;
539 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
543 sprintf(temp_buf, "Setting the information for the Network %s...",
547 sprintf(temp_buf, "Setting the information for the Cluster %s...",
551 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
555 sprintf(temp_buf, "Setting the Data for the Container %s...",
559 Put_message(temp_buf);
566 newname = strdup(info[M_NAME]);
567 if (GetValueFromUser("The new name for this machine? ", &newname) ==
570 oldnewname = strdup(newname);
571 newname = canonicalize_hostname(newname);
572 if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
574 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
575 oldnewname, newname);
576 Put_message(temp_buf);
581 newname = strdup(info[SN_NAME]);
582 if (GetValueFromUser("The new name for this network? ", &newname) ==
587 newname = strdup(info[C_NAME]);
588 if (GetValueFromUser("The new name for this cluster? ", &newname) ==
593 newname = strdup(info[CON_NAME]);
594 if (GetValueFromUser("The new name for this container? ", &newname)
599 Put_message("Unknown type in AskMCDInfo, programmer botch");
607 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
609 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
611 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
614 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
616 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
619 if (GetValueFromUser("Machine's billing contact",
620 &info[M_BILL_CONTACT]) == SUB_ERROR)
622 if (GetValueFromUser("Machine's billing account number",
623 &info[M_ACCT_NUMBER]) == SUB_ERROR)
628 if (GetValueFromUser("Machine's status (? for help)",
629 &info[M_STAT]) == SUB_ERROR)
631 if (isdigit(info[M_STAT][0]))
633 Put_message("Valid status numbers:");
634 for (i = 0; i < 4; i++)
635 Put_message(states[i]);
638 /* there appears to be some argument mismatch between the client
639 * and the server.. so here is this argument shuffler.
640 * I have since modified this to always shuffle the arguments..
641 * not just do so when performing a modify all fields request.
642 * The SetMachinedefaults() has been changed to reflect this.
643 * pray for us and may we attain enlightenment through structures.
648 /* info did not come from SetMachineDefaults(), which does not
649 * initialize entry 10 (M_STAT_CHNG), therefore we can
652 /* This is an update of an existing machine and the structure
653 * was filled in thru a query to the db which does fill in this
659 info[10] = info[M_SUBNET];
660 info[11] = info[M_ADDR];
661 info[12] = info[M_OWNER_TYPE];
662 info[13] = info[M_OWNER_NAME];
663 info[14] = info[M_ACOMMENT];
664 info[15] = info[M_OCOMMENT];
668 if (GetValueFromUser("Machine's network (or 'none')", &info[10])
672 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
673 &info[11]) == SUB_ERROR)
675 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[12]) ==
678 if (strcmp(info[12], "NONE") &&
679 GetValueFromUser("Owner's Name", &info[13]) == SUB_ERROR)
681 if (!strcmp(info[12], "KERBEROS"))
685 mrcl_validate_kerberos_member(info[13], &canon);
686 if (mrcl_get_message())
687 Put_message(mrcl_get_message());
691 if (GetValueFromUser("Administrative comment", &info[14]) == SUB_ERROR)
693 if (GetValueFromUser("Operational comment", &info[15]) == SUB_ERROR)
696 FreeAndClear(&info[17], TRUE);
697 FreeAndClear(&info[18], TRUE);
700 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
705 if (GetValueFromUser("Network's status (? for help)",
706 &info[SN_STATUS]) == SUB_ERROR)
708 if (isdigit(info[SN_STATUS][0]))
710 Put_message("Valid status numbers:");
711 for (i = 0; i < 5; i++)
712 Put_message(subnet_states[i]);
714 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
716 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
718 if (atoi(info[SN_LOW]) == (int)ntohl(inet_addr(S_DEFAULT_LOW)))
721 unsigned long mask, addr;
723 addr = atoi(info[SN_ADDRESS]);
724 mask = atoi(info[SN_MASK]);
725 low.s_addr = atoi(info[SN_LOW]);
726 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
728 sprintf(temp_buf, "%ld", low.s_addr);
729 info[SN_LOW] = strdup(temp_buf);
731 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
734 if (atoi(info[SN_HIGH]) == (int)ntohl(inet_addr(S_DEFAULT_HIGH)))
737 unsigned long mask, addr;
739 addr = atoi(info[SN_ADDRESS]);
740 mask = atoi(info[SN_MASK]);
741 high.s_addr = atoi(info[SN_HIGH]);
742 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
744 sprintf(temp_buf, "%ld", high.s_addr);
745 info[SN_HIGH] = strdup(temp_buf);
747 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
750 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
752 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
755 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
756 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
758 if (!strcmp(info[SN_ACE_TYPE], "KERBEROS"))
762 mrcl_validate_kerberos_member(info[SN_ACE_NAME], &canon);
763 if (mrcl_get_message())
764 Put_message(mrcl_get_message());
765 free(info[SN_ACE_NAME]);
766 info[SN_ACE_NAME] = canon;
768 FreeAndClear(&info[SN_MODTIME], TRUE);
769 FreeAndClear(&info[SN_MODBY], TRUE);
770 FreeAndClear(&info[SN_MODWITH], TRUE);
773 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
776 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
779 FreeAndClear(&info[C_MODTIME], TRUE);
780 FreeAndClear(&info[C_MODBY], TRUE);
781 FreeAndClear(&info[C_MODWITH], TRUE);
784 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
787 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
791 if (GetValueFromUser("Container's Description:", &info[CON_DESCRIPT]) ==
794 if (GetValueFromUser("Container's Location:", &info[CON_LOCATION]) ==
797 if (GetValueFromUser("Container's Contact:", &info[CON_CONTACT]) ==
800 if (GetTypeFromUser("Container's owner type", "ace_type",
801 &info[CON_OWNER_TYPE]) == SUB_ERROR)
803 if (strcmp(info[CON_OWNER_TYPE], "NONE") &&
804 GetValueFromUser("Owner's Name", &info[CON_OWNER_NAME]) == SUB_ERROR)
806 if (!strcmp(info[CON_OWNER_TYPE], "KERBEROS"))
810 mrcl_validate_kerberos_member(info[CON_OWNER_NAME], &canon);
811 if (mrcl_get_message())
812 Put_message(mrcl_get_message());
813 free(info[CON_OWNER_NAME]);
814 info[CON_OWNER_NAME] = canon;
816 if (GetTypeFromUser("Container's Membership ACL", "ace_type",
817 &info[CON_MEMACE_TYPE]) == SUB_ERROR)
819 if (strcmp(info[CON_MEMACE_TYPE], "NONE") &&
820 GetValueFromUser("Membership ACL", &info[CON_MEMACE_NAME])
823 if (!strcmp(info[CON_MEMACE_TYPE], "KERBEROS"))
827 mrcl_validate_kerberos_member(info[CON_MEMACE_NAME], &canon);
828 if (mrcl_get_message())
829 Put_message(mrcl_get_message());
830 free(info[CON_MEMACE_NAME]);
831 info[CON_MEMACE_NAME] = canon;
833 FreeAndClear(&info[CON_MODTIME], TRUE);
834 FreeAndClear(&info[CON_MODBY], TRUE);
835 FreeAndClear(&info[CON_MODWITH], TRUE);
840 * Slide the newname into the #2 slot, this screws up all future references
844 SlipInNewName(info, newname);
849 /* ----------- Machine Menu ----------- */
851 /* Function Name: ShowMachineInfo
852 * Description: This function shows the information about a machine.
853 * Arguments: argc, argv - the name of the machine in argv[1].
854 * Returns: DM_NORMAL.
857 int ShowMachineInfo(int argc, char **argv)
862 tmpname = canonicalize_hostname(strdup(argv[1]));
863 top = GetMCInfo(MACHINE, tmpname, NULL);
864 Loop(top, ((void (*)(char **)) PrintMachInfo));
869 /* Function Name: ShowMachineQuery
870 * Description: This function shows the information about a machine.
871 * or group of machines, which may be selected through a
872 * number of criteria.
873 * Arguments: argc, argv - the name of the machine in argv[1],
874 * the address of the machine in argv[2],
875 * the location of the machine in argv[3],
876 * and the contact name in argv[4].
877 * any of these may be wildcards.
878 * Returns: DM_NORMAL.
881 int ShowMachineQuery(int argc, char **argv)
884 struct mqelem *top, *elem = NULL;
887 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
888 !strcmp(argv[3], "") && !strcmp(argv[4], ""))
890 Put_message("You must specify at least one parameter of the query.");
895 args[0] = canonicalize_hostname(strdup(argv[1]));
911 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
913 if (stat == MR_NO_MATCH)
914 Put_message("No machine(s) found matching query in the database.");
916 com_err(program_name, stat, " in get_machine.");
919 top = QueueTop(elem);
920 Loop(top, ((void (*)(char **)) PrintMachInfo));
925 /* Function Name: AddMachine
926 * Description: This function adds a new machine to the database.
927 * Arguments: argc, argv - the name of the network in argv[1].
928 * Returns: DM_NORMAL.
931 int AddMachine(int argc, char **argv)
933 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
935 struct mqelem *elem = NULL;
938 if (!ValidName(argv[1])) /* Checks for wildcards. */
942 * get the network record
945 if (strcasecmp(argv[1], "none") &&
946 (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem)))
948 if (stat == MR_NO_MATCH)
951 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
954 com_err(program_name, stat, " in get_subnet.");
959 * Check to see if this machine already exists.
962 name = strdup(""); /* want to put prefix here */
963 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
966 name = canonicalize_hostname(strdup(name));
969 xargs[1] = xargs[2] = xargs[3] = "*";
970 if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL)))
972 sprintf(buf, "The machine '%s' already exists.", name);
977 else if (stat != MR_NO_MATCH)
979 com_err(program_name, stat,
980 " while checking machine '%s' in AddMachine.", name);
984 rinfo = SetMachineDefaults(info, name);
985 rinfo[M_SUBNET] = strdup(argv[1]);
986 if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
988 Put_message("Aborted.");
993 * Actually create the new Machine.
996 if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL)))
997 com_err(program_name, stat, " in AddMachine.");
1004 /* Function Name: RealUpdateMachine
1005 * Description: Performs the actual update of the machine data.
1006 * Arguments: info - the information on the machine to update.
1007 * junk - an UNUSED Boolean.
1011 static void RealUpdateMachine(char **info, Bool junk)
1014 char **args = AskMCDInfo(info, MACHINE, TRUE);
1017 Put_message("Aborted.");
1020 if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL)))
1021 com_err(program_name, stat, " in UpdateMachine.");
1023 Put_message("Machine successfully updated.");
1026 /* Function Name: UpdateMachine
1027 * Description: This function adds a new machine to the database.
1028 * Arguments: argc, argv - the name of the machine in argv[1].
1029 * Returns: DM_NORMAL.
1032 int UpdateMachine(int argc, char **argv)
1037 tmpname = canonicalize_hostname(strdup(argv[1]));
1038 top = GetMCInfo(MACHINE, tmpname, NULL);
1039 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
1046 /* Function Name: CheckAndRemoveFromCluster
1047 * Description: This func tests to see if a machine is in a cluster.
1048 * and if so then removes it
1049 * Arguments: name - name of the machine (already Canonicalized).
1050 * ask_user- query the user before removing if from clusters?
1051 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
1054 int CheckAndRemoveFromCluster(char *name, Bool ask_user)
1056 int stat, ret_value;
1058 char *args[10], temp_buf[BUFSIZ], *ptr;
1059 struct mqelem *top, *elem = NULL;
1061 ret_value = SUB_NORMAL; /* initialize ret_value. */
1064 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1065 if (stat && stat != MR_NO_MATCH)
1067 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1070 if (stat == MR_SUCCESS)
1072 elem = top = QueueTop(elem);
1075 sprintf(temp_buf, "%s is assigned to the following clusters.", name);
1076 Put_message(temp_buf);
1077 Loop(top, (void (*)(char **)) PrintMCMap);
1078 ptr = "Remove this machine from ** ALL ** these clusters?";
1079 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1083 Put_message("Aborting...");
1095 char **info = elem->q_data;
1096 if ((stat = do_mr_query("delete_machine_from_cluster",
1097 2, info, NULL, NULL)))
1099 ret_value = SUB_ERROR;
1100 com_err(program_name, stat,
1101 " in delete_machine_from_cluster.");
1103 "Machine %s ** NOT ** removed from cluster %s.",
1104 info[MAP_MACHINE], info[MAP_CLUSTER]);
1105 Put_message(temp_buf);
1107 elem = elem->q_forw;
1114 /* Function Name: CheckAndRemoveCnames
1115 * Description: This func tests to see if a machine has cnames,
1116 * and if so then removes them.
1117 * Arguments: name - name of the machine (already Canonicalized).
1118 * ask_user- query the user before removing cnames?
1119 * Returns: MR_ERROR if machine left with a cname, or mr_error.
1122 int CheckAndRemoveCnames(char *name, Bool ask_user)
1124 int stat, ret_value;
1126 char *args[10], temp_buf[BUFSIZ], *ptr;
1127 struct mqelem *top, *elem = NULL;
1129 ret_value = SUB_NORMAL;
1132 stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem);
1133 if (stat && stat != MR_NO_MATCH)
1135 com_err(program_name, stat, " in get_hostalias.");
1138 if (stat == MR_SUCCESS)
1140 elem = top = QueueTop(elem);
1143 sprintf(temp_buf, "%s has the following cnames.", name);
1144 Put_message(temp_buf);
1145 Loop(top, (void (*)(char **)) PrintCname);
1146 ptr = "Remove ** ALL ** these cnames?";
1147 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1151 Put_message("Aborting...");
1163 char **info = elem->q_data;
1164 if ((stat = do_mr_query("delete_hostalias", 2, info,
1167 ret_value = SUB_ERROR;
1168 com_err(program_name, stat, " in delete_hostalias.");
1170 "Cname %s ** NOT ** removed from host %s.",
1172 Put_message(temp_buf);
1174 elem = elem->q_forw;
1181 /* Function Name: RealDeleteMachine
1182 * Description: Actually Deletes the Machine.
1183 * Arguments: info - nescessary information stored as an array of char *'s
1184 * one_machine - a boolean, true if there is only one item in
1189 static void RealDeleteMachine(char **info, Bool one_machine)
1192 char temp_buf[BUFSIZ];
1194 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
1196 if (!one_machine || Confirm(temp_buf))
1198 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
1200 if (CheckAndRemoveCnames(info[M_NAME], TRUE) != SUB_ERROR)
1202 if ((stat = do_mr_query("delete_host", 1,
1203 &info[M_NAME], NULL, NULL)))
1205 com_err(program_name, stat, " in DeleteMachine.");
1206 sprintf(temp_buf, "%s ** NOT ** deleted.",
1208 Put_message(temp_buf);
1212 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
1213 Put_message(temp_buf);
1220 /* Function Name: DeleteMachine
1221 * Description: This function removes a machine from the data base.
1222 * Arguments: argc, argv - the machines name int argv[1].
1223 * Returns: DM_NORMAL.
1226 /* Perhaps we should remove the cluster if it has no machine now. */
1228 int DeleteMachine(int argc, char **argv)
1233 tmpname = canonicalize_hostname(strdup(argv[1]));
1234 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
1235 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
1242 /* Function Name: ShowCname
1243 * Description: This function shows machine aliases
1244 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1245 * Returns: DM_NORMAL.
1248 int ShowCname(int argc, char **argv)
1251 char *tmpalias, *tmpname;
1253 tmpalias = partial_canonicalize_hostname(strdup(argv[1]));
1254 tmpname = canonicalize_hostname(strdup(argv[2]));
1255 top = GetMCInfo(CNAME, tmpalias, tmpname);
1256 Put_message(""); /* blank line on screen */
1257 Loop(top, ((void (*)(char **)) PrintCname));
1263 int AddCname(int argc, char **argv)
1268 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1269 args[1] = canonicalize_hostname(strdup(argv[2]));
1270 stat = do_mr_query("add_hostalias", 2, args, NULL, NULL);
1276 Put_message("That alias name is already in use.");
1279 Put_message("Permission denied. "
1280 "(Regular users can only add two aliases to a host.");
1283 com_err(program_name, stat, " in add_hostalias");
1289 int DeleteCname(int argc, char **argv)
1294 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1295 args[1] = canonicalize_hostname(strdup(argv[2]));
1296 stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL);
1298 com_err(program_name, stat, " in delete_hostalias");
1303 /* Function Name: AddMachineToCluster
1304 * Description: This function adds a machine to a cluster
1305 * Arguments: argc, argv - The machine name is argv[1].
1306 * The cluster name in argv[2].
1307 * Returns: DM_NORMAL.
1310 int AddMachineToCluster(int argc, char **argv)
1313 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1314 Bool add_it, one_machine, one_cluster;
1315 struct mqelem *melem, *mtop, *celem, *ctop;
1317 machine = canonicalize_hostname(strdup(argv[1]));
1318 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1320 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1322 Put_message(temp_buf);
1326 celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1327 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1330 one_machine = (QueueCount(mtop) == 1);
1331 one_cluster = (QueueCount(ctop) == 1);
1333 /* No good way to use QueryLoop() here, sigh */
1337 char **minfo = melem->q_data;
1340 char **cinfo = celem->q_data;
1341 if (one_machine && one_cluster)
1345 sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1346 minfo[M_NAME], cinfo[C_NAME]);
1347 switch (YesNoQuitQuestion(temp_buf, FALSE))
1356 Put_message("Aborting...");
1364 args[0] = minfo[M_NAME];
1365 args[1] = cinfo[C_NAME];
1366 stat = do_mr_query("add_machine_to_cluster", 2, args,
1373 sprintf(temp_buf, "%s is already in cluster %s",
1374 minfo[M_NAME], cinfo[C_NAME]);
1375 Put_message(temp_buf);
1378 com_err(program_name, stat, " in AddMachineToCluster.");
1382 celem = celem->q_forw;
1384 celem = ctop; /* reset cluster element. */
1385 melem = melem->q_forw;
1392 /* Function Name: RealRemoveMachineFromCluster
1393 * Description: This function actually removes the machine from its
1395 * Arguments: info - all information nescessary to perform the removal.
1396 * one_map - True if there is only one case, and we should
1401 static void RealRemoveMachineFromCluster(char **info, Bool one_map)
1403 char temp_buf[BUFSIZ];
1406 sprintf(temp_buf, "Remove %s from the cluster %s",
1407 info[MAP_MACHINE], info[MAP_CLUSTER]);
1408 if (!one_map || Confirm(temp_buf))
1410 if ((stat = do_mr_query("delete_machine_from_cluster", 2,
1412 com_err(program_name, stat, " in delete_machine_from_cluster");
1415 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1416 info[MAP_MACHINE], info[MAP_CLUSTER]);
1417 Put_message(temp_buf);
1421 Put_message("Machine not removed.");
1424 /* Function Name: RemoveMachineFromCluster
1425 * Description: Removes this machine form a specific cluster.
1426 * Arguments: argc, argv - Name of machine in argv[1].
1427 * Name of cluster in argv[2].
1431 int RemoveMachineFromCluster(int argc, char **argv)
1433 struct mqelem *elem = NULL;
1434 char buf[BUFSIZ], *args[10];
1437 args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1]));
1438 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1440 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1441 argv[1], args[MAP_MACHINE]);
1444 args[MAP_CLUSTER] = argv[2];
1445 args[MAP_END] = NULL;
1447 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1449 if (stat == MR_NO_MATCH)
1451 sprintf(buf, "The machine %s is not in the cluster %s.",
1452 args[MAP_MACHINE], args[MAP_CLUSTER]);
1454 free(args[MAP_MACHINE]);
1457 if (stat != MR_SUCCESS)
1458 com_err(program_name, stat, " in delete_machine_from_cluster");
1460 elem = QueueTop(elem);
1461 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1462 "Remove this machine from this cluster");
1465 free(args[MAP_MACHINE]);
1469 /* ---------- Subnet Menu -------- */
1471 /* Function Name: ShowSubnetInfo
1472 * Description: Gets information about a subnet given its name.
1473 * Arguments: argc, argc - the name of the subnet in in argv[1].
1474 * Returns: DM_NORMAL.
1477 int ShowSubnetInfo(int argc, char **argv)
1481 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1482 Loop(top, (void (*)(char **)) PrintSubnetInfo);
1487 /* Function Name: AddSubnet
1488 * Description: Creates a new subnet.
1489 * Arguments: argc, argv - the name of the new subnet is argv[1].
1490 * Returns: DM_NORMAL.
1493 int AddSubnet(int argc, char **argv)
1495 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1499 * Check to see if this subnet already exists.
1501 if (!ValidName(name))
1504 if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS)
1506 Put_message("This subnet already exists.");
1509 else if (stat != MR_NO_MATCH)
1511 com_err(program_name, stat, " in AddSubnet.");
1514 if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1516 Put_message("Aborted.");
1522 * Actually create the new Subnet.
1524 if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL)))
1525 com_err(program_name, stat, " in AddSubnet.");
1531 /* Function Name: RealUpdateSubnet
1532 * Description: This function actually performs the subnet update.
1533 * Arguments: info - all information nesc. for updating the subnet.
1534 * junk - an UNUSED boolean.
1538 static void RealUpdateSubnet(char **info, Bool junk)
1541 char **args = AskMCDInfo(info, SUBNET, TRUE);
1544 Put_message("Aborted.");
1547 if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL)))
1548 com_err(program_name, stat, " in UpdateSubnet.");
1550 Put_message("Subnet successfully updated.");
1553 /* Function Name: UpdateSubnet
1554 * Description: This Function Updates a subnet
1555 * Arguments: name of the subnet in argv[1].
1556 * Returns: DM_NORMAL.
1559 int UpdateSubnet(int argc, char **argv)
1562 top = GetMCInfo(SUBNET, argv[1], NULL);
1563 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1569 /* Function Name: RealDeleteSubnet
1570 * Description: Actually performs the subnet deletion.
1571 * Arguments: info - all information about this subnet.
1572 * one_subnet - If true then there was only one subnet in
1573 * the queue, and we should confirm.
1577 static void RealDeleteSubnet(char **info, Bool one_subnet)
1580 char temp_buf[BUFSIZ];
1583 "Are you sure the you want to delete the subnet %s (y/n) ?",
1585 if (!one_subnet || Confirm(temp_buf))
1587 if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL)))
1589 com_err(program_name, stat, " in delete_subnet.");
1590 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1591 Put_message(temp_buf);
1595 sprintf(temp_buf, "subnet %s successfully deleted.",
1597 Put_message(temp_buf);
1602 /* Function Name: DeleteSubnet
1603 * Description: This function removes a subnet from the database.
1604 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1605 * Returns: DM_NORMAL.
1608 int DeleteSubnet(int argc, char **argv)
1612 top = GetMCInfo(SUBNET, argv[1], NULL);
1613 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1619 /* ---------- Cluster Menu -------- */
1621 /* Function Name: ShowClusterInfo
1622 * Description: Gets information about a cluser given its name.
1623 * Arguments: argc, argc - the name of the cluster in in argv[1].
1624 * Returns: DM_NORMAL.
1627 int ShowClusterInfo(int argc, char **argv)
1631 top = GetMCInfo(CLUSTER, argv[1], NULL);
1632 Loop(top, (void (*)(char **)) PrintClusterInfo);
1637 /* Function Name: AddCluster
1638 * Description: Creates a new cluster.
1639 * Arguments: argc, argv - the name of the new cluster is argv[1].
1640 * Returns: DM_NORMAL.
1643 int AddCluster(int argc, char **argv)
1645 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1649 * Check to see if this cluster already exists.
1651 if (!ValidName(name))
1654 if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS)
1656 Put_message("This cluster already exists.");
1659 else if (stat != MR_NO_MATCH)
1661 com_err(program_name, stat, " in AddCluster.");
1664 if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1666 Put_message("Aborted.");
1672 * Actually create the new Cluster.
1674 if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL)))
1675 com_err(program_name, stat, " in AddCluster.");
1681 /* Function Name: RealUpdateCluster
1682 * Description: This function actually performs the cluster update.
1683 * Arguments: info - all information nesc. for updating the cluster.
1684 * junk - an UNUSED boolean.
1688 static void RealUpdateCluster(char **info, Bool junk)
1691 char **args = AskMCDInfo(info, CLUSTER, TRUE);
1695 Put_message("Aborted.");
1698 if ((stat = do_mr_query("update_cluster", CountArgs(args),
1700 com_err(program_name, stat, " in UpdateCluster.");
1702 Put_message("Cluster successfully updated.");
1705 /* Function Name: UpdateCluster
1706 * Description: This Function Updates a cluster
1707 * Arguments: name of the cluster in argv[1].
1708 * Returns: DM_NORMAL.
1711 int UpdateCluster(int argc, char **argv)
1714 top = GetMCInfo(CLUSTER, argv[1], NULL);
1715 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1721 /* Function Name: CheckAndRemoveMachine
1722 * Description: This function checks and removes all machines from a
1724 * Arguments: name - name of the cluster.
1725 * ask_first - if TRUE, then we will query the user, before
1727 * Returns: SUB_ERROR if all machines not removed.
1730 int CheckAndRemoveMachines(char *name, Bool ask_first)
1732 int stat, ret_value;
1734 char *args[10], temp_buf[BUFSIZ], *ptr;
1735 struct mqelem *top, *elem = NULL;
1737 ret_value = SUB_NORMAL;
1738 args[MAP_MACHINE] = "*";
1739 args[MAP_CLUSTER] = name;
1740 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1741 if (stat && stat != MR_NO_MATCH)
1743 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1746 if (stat == MR_SUCCESS)
1748 elem = top = QueueTop(elem);
1751 sprintf(temp_buf, "The cluster %s has the following machines in it:",
1753 Put_message(temp_buf);
1756 char **info = elem->q_data;
1757 Print(1, &info[MAP_MACHINE], (char *) NULL);
1758 elem = elem->q_forw;
1760 ptr = "Remove ** ALL ** these machines from this cluster?";
1762 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1766 Put_message("Aborting...");
1779 char **info = elem->q_data;
1780 if ((stat = do_mr_query("delete_machine_from_cluster",
1781 2, info, NULL, NULL)))
1783 ret_value = SUB_ERROR;
1784 com_err(program_name, stat,
1785 " in delete_machine_from_cluster.");
1787 "Machine %s ** NOT ** removed from cluster %s.",
1788 info[MAP_MACHINE], info[MAP_CLUSTER]);
1789 Put_message(temp_buf);
1791 elem = elem->q_forw;
1798 /* Function Name: RealDeleteCluster
1799 * Description: Actually performs the cluster deletion.
1800 * Arguments: info - all information about this cluster.
1801 * one_cluster - If true then there was only one cluster in
1802 * the queue, and we should confirm.
1806 static void RealDeleteCluster(char **info, Bool one_cluster)
1809 char temp_buf[BUFSIZ];
1812 "Are you sure the you want to delete the cluster %s (y/n) ?",
1814 if (!one_cluster || Confirm(temp_buf))
1816 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1818 if ((stat = do_mr_query("delete_cluster", 1,
1819 &info[C_NAME], NULL, NULL)))
1821 com_err(program_name, stat, " in delete_cluster.");
1822 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1823 Put_message(temp_buf);
1827 sprintf(temp_buf, "cluster %s successfully deleted.",
1829 Put_message(temp_buf);
1835 /* Function Name: DeleteCluster
1836 * Description: This function removes a cluster from the database.
1837 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1838 * Returns: DM_NORMAL.
1841 int DeleteCluster(int argc, char **argv)
1845 top = GetMCInfo(CLUSTER, argv[1], NULL);
1846 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1852 /* ----------- Cluster Data Menu -------------- */
1854 /* Function Name: ShowClusterData
1855 * Description: This function shows the services for one cluster.
1856 * Arguments: argc, argv - The name of the cluster is argv[1].
1857 * The label of the data in argv[2].
1858 * Returns: DM_NORMAL.
1861 int ShowClusterData(int argc, char **argv)
1863 struct mqelem *elem, *top;
1866 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1869 info = elem->q_data;
1870 PrintClusterData(info);
1871 elem = elem->q_forw;
1877 /* Function Name: AddClusterData
1878 * Description: This function adds some data to the cluster.
1879 * Arguments: argv, argc: argv[1] - the name of the cluster.
1880 * argv[2] - the label of the data.
1881 * argv[3] - the data.
1882 * Returns: DM_NORMAL.
1885 int AddClusterData(int argc, char **argv)
1889 for (i = 1; i < 4; i++)
1891 if (IS_EMPTY(argv[i]))
1893 Put_message("Cluster data cannot be an empty string.");
1897 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
1898 com_err(program_name, stat, " in AddClusterData.");
1902 /* Function Name: RealRemoveClusterData
1903 * Description: actually removes the cluster data.
1904 * Arguments: info - all info necessary to remove the cluster, in an array
1906 * one_item - if true then the queue has only one elem and we
1911 static void RealRemoveClusterData(char **info, Bool one_item)
1917 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1918 PrintClusterData(info);
1919 if (!one_item || Confirm(temp_ptr))
1921 if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
1923 com_err(program_name, stat, " in DeleteClusterData.");
1924 Put_message("Data not removed.");
1927 Put_message("Removal successful.");
1931 /* Function Name: RemoveClusterData
1932 * Description: This function removes data on a given cluster.
1933 * Arguments: argv, argc: argv[1] - the name of the cluster.
1934 * argv[2] - the label of the data.
1935 * argv[3] - the data.
1936 * Returns: DM_NORMAL.
1939 int RemoveClusterData(int argc, char **argv)
1943 top = GetMCInfo(DATA, argv[1], argv[2]);
1944 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1945 "Remove data from cluster");
1951 /* Function Name: MachineToClusterMap
1952 * Description: This Retrieves the mapping between machine and cluster
1953 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1954 * argv[2] -> cluster name or wildcard.
1958 int MachineToClusterMap(int argc, char **argv)
1960 struct mqelem *elem, *top;
1961 char *tmpname, temp_buf[256];
1963 tmpname = canonicalize_hostname(strdup(argv[1]));
1964 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
1966 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1968 Put_message(temp_buf);
1970 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1972 Put_message(""); /* blank line on screen */
1975 char **info = elem->q_data;
1977 elem = elem->q_forw;
1985 /* Function Name: MachineByOwner
1986 * Description: This function prints all machines which are owned by
1987 * a given user or group.
1989 * Returns: DM_NORMAL.
1992 int MachineByOwner(int argc, char **argv)
1994 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
1997 type = strdup("USER");
1998 if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR)
2001 sprintf(buf, "Name of %s", type);
2002 name = strdup(user);
2003 if (GetValueFromUser(buf, &name) == SUB_ERROR)
2006 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
2009 sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */
2011 type = strdup(temp_buf);
2019 top = GetMachineByOwner(type, name);
2020 Loop(top, PrintMachine);
2026 /* Function Name: GetMachineByOwner
2027 * Description: This function stores information retrieved by
2028 * the get_host_by_owner query
2029 * Arguments: type - an ace_type, argv[0] for the query
2030 * name - name of machine, argv[1] for the query
2031 * Returns: the top element of a queue returning the data, or NULL.
2034 struct mqelem *GetMachineByOwner(char *type, char *name)
2037 struct mqelem *elem = NULL;
2042 if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem)))
2044 com_err(program_name, status, " in get_host_by_owner");
2047 return QueueTop(elem);
2050 int ShowContainerInfo(int argc, char **argv)
2054 top = GetMCInfo(CONTAINER, argv[1], NULL);
2055 Loop(top, (void (*)(char **)) PrintContainerInfo);
2060 static char *PrintContainerInfo(char **info)
2062 char buf[BUFSIZ], tbuf[256];
2065 sprintf(buf, "Container: %-16s", info[CON_NAME]);
2067 sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]);
2069 sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION],
2072 sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE],
2073 strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : "");
2074 sprintf(buf, "Owner: %-16s", tbuf);
2076 sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE],
2077 strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : "");
2078 sprintf(buf, "Membership ACL: %-16s", tbuf);
2081 sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME],
2084 return info[CON_NAME];
2087 static char *PrintContainer(char **info)
2091 sprintf(buf, "Container: %s", info[CON_NAME]);
2095 static char *PrintMContMap(char **info)
2098 sprintf(buf, "Container: %-30s Machine: %-20s",
2104 int AddContainer(int argc, char **argv)
2106 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
2109 /* Can't use ValidName() because spaces are allowed in container names */
2112 Put_message("Please use a non-empty name.");
2116 if (strchr(name, '*') || strchr(name, '?'))
2118 Put_message("Wildcards not accepted here.");
2122 /* Check if this cluster already exists. */
2123 if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL))
2126 Put_message("This container already exists.");
2129 else if (stat != MR_NO_MATCH)
2131 com_err(program_name, stat, " in AddContainer.");
2134 if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE)))
2136 Put_message("Aborted.");
2141 /* Create the new container. */
2142 if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL)))
2143 com_err(program_name, stat, " in AddContainer.");
2149 int UpdateContainer(int argc, char **argv)
2152 top = GetMCInfo(CONTAINER, argv[1], NULL);
2153 QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container");
2159 static void RealUpdateContainer(char **info, Bool junk)
2162 char **args = AskMCDInfo(info, CONTAINER, TRUE);
2166 Put_message("Aborted.");
2169 if ((stat = do_mr_query("update_container", CountArgs(args), args,
2171 com_err(program_name, stat, " in UpdateContainer.");
2173 Put_message("Container successfully updated.");
2176 int DeleteContainer(int argc, char **argv)
2180 top = GetMCInfo(CONTAINER, argv[1], NULL);
2181 QueryLoop(top, PrintClusterInfo, RealDeleteContainer,
2182 "Delete the container");
2188 static void RealDeleteContainer(char **info, Bool one_container)
2191 char temp_buf[BUFSIZ];
2194 "Are you sure you want to delete the container %s (y/n) ?",
2196 if (!one_container || Confirm(temp_buf))
2198 if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE)
2201 if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME],
2204 com_err(program_name, stat, " in delete_container.");
2205 sprintf(temp_buf, "Container %s ** NOT ** deleted.",
2207 Put_message(temp_buf);
2211 sprintf(temp_buf, "Container %s successfully deleted.",
2213 Put_message(temp_buf);
2219 int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first)
2221 int stat, ret_value;
2223 char *args[10], temp_buf[BUFSIZ], *ptr;
2224 struct mqelem *top, *elem = NULL;
2226 ret_value = SUB_NORMAL;
2229 stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo,
2231 if (stat && stat != MR_NO_MATCH)
2233 com_err(program_name, stat, " in get_machines_of_container");
2236 if (stat == MR_SUCCESS)
2238 elem = top = QueueTop(elem);
2242 "The container %s has the following machines in it:", name);
2243 Put_message(temp_buf);
2246 char **info = elem->q_data;
2247 Print(1, &info[0], (char *) NULL);
2248 elem = elem->q_forw;
2250 ptr = "Remove ** ALL ** these machines from this container?";
2252 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
2256 Put_message("Aborting...");
2269 char **info = elem->q_data;
2270 if ((stat = do_mr_query("delete_machine_from_container",
2271 2, info, NULL, NULL)))
2273 ret_value = SUB_ERROR;
2274 com_err(program_name, stat,
2275 " in delete_machine_from_container.");
2277 "Machine %s ** NOT ** removed from container %s.",
2279 Put_message(temp_buf);
2281 elem = elem->q_forw;
2288 int GetSubContainers(int argc, char **argv)
2291 struct mqelem *elem = NULL, *top = NULL;
2296 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2301 if (stat = do_mr_query("get_subcontainers_of_container", 2, args,
2303 com_err(program_name, stat, " in get_subcontainers_of_container");
2305 top = QueueTop(elem);
2306 Loop(top, ((void (*)(char **)) PrintContainer));
2311 int MachineToContainerMap(int argc, char **argv)
2313 struct mqelem *elem, *top;
2314 char *tmpname, temp_buf[256];
2316 tmpname = canonicalize_hostname(strdup(argv[1]));
2317 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2319 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2321 Put_message(temp_buf);
2323 top = elem = GetMCInfo(CONTMAP, tmpname, NULL);
2328 char **info = elem->q_data;
2329 PrintMContMap(info);
2330 elem = elem->q_forw;
2338 int AddMachineToContainer(int argc, char **argv)
2341 char *machine, *container, temp_buf[BUFSIZ], *args[10];
2342 Bool add_it, one_machine, one_container;
2343 struct mqelem *melem, *mtop, *celem, *ctop;
2345 machine = canonicalize_hostname(strdup(argv[1]));
2346 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
2348 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2350 Put_message(temp_buf);
2352 container = argv[2];
2354 celem = ctop = GetMCInfo(CONTAINER, container, NULL);
2355 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
2358 one_machine = (QueueCount(mtop) == 1);
2359 one_container = (QueueCount(ctop) == 1);
2363 char **minfo = melem->q_data;
2366 char **cinfo = celem->q_data;
2367 if (one_machine && one_container)
2371 sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?",
2372 minfo[M_NAME], cinfo[CON_NAME]);
2373 switch (YesNoQuestion(temp_buf, FALSE))
2382 Put_message("Aborting...");
2390 args[0] = minfo[M_NAME];
2391 args[1] = cinfo[CON_NAME];
2392 stat = do_mr_query("add_machine_to_container", 2, args, NULL,
2399 sprintf(temp_buf, "%s is already in container %s",
2400 minfo[M_NAME], cinfo[CON_NAME]);
2401 Put_message(temp_buf);
2404 com_err(program_name, stat, " in AddMachineToContainer.");
2408 celem = celem->q_forw;
2411 melem = melem->q_forw;
2418 int RemoveMachineFromContainer(int argc, char **argv)
2420 struct mqelem *elem = NULL;
2421 char buf[BUFSIZ], *args[10];
2424 args[0] = canonicalize_hostname(strdup(argv[1]));
2425 if (strcasecmp(args[0], argv[1]) && *argv[1] != '"')
2427 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
2434 stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo,
2436 if (stat == MR_NO_MATCH)
2438 sprintf(buf, "The machine %s is not in the container %s.",
2444 if (stat != MR_SUCCESS)
2445 com_err(program_name, stat, " in deleter_machine_from_container");
2447 elem = QueueTop(elem);
2448 QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer,
2449 "Remove this machine from this container");
2456 static void RealRemoveMachineFromContainer(char **info, Bool one_contmap)
2458 char temp_buf[BUFSIZ];
2461 sprintf(temp_buf, "Remove %s from the container %s",
2463 if (!one_contmap || Confirm(temp_buf))
2465 if ((stat = do_mr_query("delete_machine_from_container", 2,
2467 com_err(program_name, stat, " in delete_machine_from_container");
2470 sprintf(temp_buf, "%s has been removed from the container %s.",
2472 Put_message(temp_buf);
2476 Put_message("Machine not removed.");
2479 int GetMachinesOfContainer(int argc, char **argv)
2482 struct mqelem *elem = NULL, *top = NULL;
2487 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2492 if (stat = do_mr_query("get_machines_of_container", 2, args,
2494 com_err(program_name, stat, " in get_machines_of_container");
2496 top = QueueTop(elem);
2497 Loop(top, ((void (*)(char **)) PrintMContMap));