]> andersk Git - moira.git/blob - clients/moira/cluster.c
second code style cleanup: void/void * usage, proper #includes. try to
[moira.git] / clients / moira / cluster.c
1 /* $Id $
2  *
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.
5  *      It Contains:
6  *
7  *      Created:        4/22/88
8  *      By:             Chris D. Peterson
9  *
10  * Copyright (C) 1988-1998 by the Massachusetts Institute of Technology.
11  * For copying and distribution information, please see the file
12  * <mit-copyright.h>.
13  */
14
15 /* BTW: for anyone who cares MCD is short for Machine, Cluster, Data. */
16
17 #include <mit-copyright.h>
18 #include <moira.h>
19 #include <moira_site.h>
20
21 #include "defs.h"
22 #include "f_defs.h"
23 #include "globals.h"
24
25 #include <sys/utsname.h>
26
27 #include <netinet/in.h>
28 #include <arpa/inet.h>
29 #include <netdb.h>
30
31 #include <ctype.h>
32 #include <stdio.h>
33 #include <stdlib.h>
34 #include <string.h>
35
36 void PrintAliases(char **info);
37 struct qelem *GetMCInfo(int type, char *name1, char *name2);
38 char **AskMCDInfo(char **info, int type, Bool name);
39 int CheckAndRemoveFromCluster(char *name, Bool ask_user);
40 int CheckAndRemoveMachines(char *name, Bool ask_first);
41 char *partial_canonicalize_hostname(char *s);
42
43 #define MACHINE  0
44 #define CLUSTER  1
45 #define DATA     2
46 #define MAP      3
47 #define SUBNET   4
48 #define CNAME    5
49
50 #define M_DEFAULT_TYPE     DEFAULT_NONE
51
52 #define C_DEFAULT_DESCRIPT DEFAULT_NONE
53 #define C_DEFAULT_LOCATION DEFAULT_NONE
54
55 #define CD_DEFAULT_LABEL   DEFAULT_NONE
56 #define CD_DEFAULT_DATA    DEFAULT_NONE
57
58 #define S_DEFAULT_LOW   "18.0.0.20"
59 #define S_DEFAULT_HIGH  "18.0.2.249"
60
61 static char *states[] = {
62   "Reserved (0)",
63   "Active (1)",
64   "None (2)",
65   "Deleted (3)"
66 };
67
68 static char *MacState(int state)
69 {
70   static char buf[BUFSIZ];
71
72   if (state < 0 || state > 3)
73     {
74       sprintf(buf, "Unknown (%d)", state);
75       return buf;
76     }
77   return states[state];
78 }
79
80
81
82 /* -------------------- Set Defaults -------------------- */
83
84 /*      Function Name: SetMachineDefaults
85  *      Description: sets machine defaults.
86  *      Arguments: info - an array to put the defaults into.
87  *                 name - Canonacalized name of the machine.
88  *      Returns: info - the array.
89  */
90
91 static char **SetMachineDefaults(char **info, char *name)
92 {
93   info[M_NAME] = strdup(name);
94   info[M_VENDOR] = strdup(M_DEFAULT_TYPE);
95   info[M_MODEL] = strdup(M_DEFAULT_TYPE);
96   info[M_OS] = strdup(M_DEFAULT_TYPE);
97   info[M_LOC] = strdup(M_DEFAULT_TYPE);
98   info[M_CONTACT] = strdup(M_DEFAULT_TYPE);
99   info[M_USE] = strdup("0");
100   info[M_STAT] = strdup("1");
101   info[M_SUBNET] = strdup("NONE");
102   info[M_ADDR] = strdup("unique");
103   info[M_OWNER_TYPE] = strdup("NONE");
104   info[M_OWNER_NAME] = strdup("NONE");
105   info[M_ACOMMENT] = strdup("");
106   info[M_OCOMMENT] = strdup("");
107   info[15] = info[16] = NULL;
108   return info;
109 }
110
111 /*      Function Name: SetClusterDefaults
112  *      Description: sets Cluster defaults.
113  *      Arguments: info - an array to put the defaults into.
114  *                 name - name of the Cluster.
115  *      Returns: info - the array.
116  */
117
118 static char **SetClusterDefaults(char **info, char *name)
119 {
120   info[C_NAME] = strdup(name);
121   info[C_DESCRIPT] = strdup(C_DEFAULT_DESCRIPT);
122   info[C_LOCATION] = strdup(C_DEFAULT_LOCATION);
123   info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
124   return info;
125 }
126
127 /*      Function Name: SetSubnetDefaults
128  *      Description: sets Subnet defaults.
129  *      Arguments: info - an array to put the defaults into.
130  *                 name - name of the Subnet.
131  *      Returns: info - the array.
132  */
133
134 static char **SetSubnetDefaults(char **info, char *name)
135 {
136   char buf[256];
137
138   info[C_NAME] = strdup(name);
139   info[SN_DESC] = strdup("");
140   sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0")));
141   info[SN_ADDRESS] = strdup(buf);
142   sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0")));
143   info[SN_MASK] = strdup(buf);
144   sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW)));
145   info[SN_LOW] = strdup(buf);
146   sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH)));
147   info[SN_HIGH] = strdup(buf);
148   info[SN_PREFIX] = strdup("");
149   info[SN_ACE_TYPE] = strdup("LIST");
150   info[SN_ACE_NAME] = strdup("network");
151   info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
152   return info;
153 }
154
155 /* -------------------- General Functions -------------------- */
156
157 static char aliasbuf[256];
158
159 void PrintAliases(char **info)
160 {
161   if (strlen(aliasbuf) == 0)
162     sprintf(aliasbuf, "Aliases:  %s", info[0]);
163   else
164     {
165       strcat(aliasbuf, ", ");
166       strcat(aliasbuf, info[0]);
167     }
168 }
169
170
171 /*      Function Name: PrintMachInfo
172  *      Description: This function Prints out the Machine info in
173  *                   a coherent form.
174  *      Arguments: info - array of information about a machine.
175  *      Returns: The name of the Machine
176  */
177
178 static char *PrintMachInfo(char **info)
179 {
180   char buf[BUFSIZ], tbuf[256];
181   char *args[3];
182   struct qelem *elem = NULL;
183   int stat;
184
185   Put_message("");
186   sprintf(buf, "Machine:  %s", info[M_NAME]);
187   Put_message(buf);
188   args[0] = "*";
189   args[1] = info[M_NAME];
190   if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
191     {
192       if (stat != MR_NO_MATCH)
193         com_err(program_name, stat, " looking up aliases");
194     }
195   else
196     {
197       aliasbuf[0] = 0;
198       Loop(QueueTop(elem), (void *) PrintAliases);
199       FreeQueue(elem);
200       Put_message(aliasbuf);
201     }
202   sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
203           strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
204   sprintf(buf, "Address:  %-16s    Network:    %-16s",
205           info[M_ADDR], info[M_SUBNET]);
206   Put_message(buf);
207   sprintf(buf, "Owner:    %-16s    Use data:   %s", tbuf, info[M_INUSE]);
208   Put_message(buf);
209   sprintf(buf, "Status:   %-16s    Changed:    %s",
210           MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
211   Put_message(buf);
212   Put_message("");
213
214   sprintf(buf, "Vendor:   %-16s    Model:      %-20s  OS:  %s",
215           info[M_VENDOR], info[M_MODEL], info[M_OS]);
216   Put_message(buf);
217   sprintf(buf, "Location: %-16s    Contact:    %-20s  Opt: %s",
218           info[M_LOC], info[M_CONTACT], info[M_USE]);
219   Put_message(buf);
220   sprintf(buf, "\nAdm cmt: %s", info[M_ACOMMENT]);
221   Put_message(buf);
222   sprintf(buf, "Op cmt:  %s", info[M_OCOMMENT]);
223   Put_message(buf);
224   Put_message("");
225   sprintf(buf, "Created  by %s on %s", info[M_CREATOR], info[M_CREATED]);
226   Put_message(buf);
227   sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
228   Put_message(buf);
229   return info[M_NAME];
230 }
231
232 /*      Function Name: PrintCname
233  *      Description: Prints the Data on a host alias
234  *      Arguments: info a pointer to the data array.
235  *      Returns: The name of the alias.
236  */
237
238 static char *PrintCname(char **info)
239 {
240   char buf[BUFSIZ];
241
242   sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
243   Put_message(buf);
244   return info[0];
245 }
246
247 /*      Function Name: PrintClusterInfo
248  *      Description: This function Prints out the cluster info
249  *                   in a coherent form.
250  *      Arguments: info - array of information about a cluster.
251  *      Returns: The name of the cluster.
252  */
253
254 static char *PrintClusterInfo(char **info)
255 {
256   char buf[BUFSIZ];
257
258   Put_message("");
259   sprintf(buf, "Cluster:     %s", info[C_NAME]);
260   Put_message(buf);
261   sprintf(buf, "Description: %s", info[C_DESCRIPT]);
262   Put_message(buf);
263   sprintf(buf, "Location:    %s", info[C_LOCATION]);
264   Put_message(buf);
265   sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
266   Put_message(buf);
267   return info[C_NAME];
268 }
269
270 /*      Function Name: PrintClusterData
271  *      Description: Prints the Data on a cluster
272  *      Arguments: info a pointer to the data array.
273  *      Returns: The name of the cluster.
274  */
275
276 static char *PrintClusterData(char **info)
277 {
278   char buf[BUFSIZ];
279
280   Put_message("");
281   sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
282           info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
283   Put_message(buf);
284   return info[CD_NAME];
285 }
286
287 /*      Function Name: PrintMCMap
288  *      Description: Prints the data about a machine to cluster mapping.
289  *      Arguments: info a pointer to the data array.
290  *      Returns: none
291  */
292
293 static char *PrintMCMap(char **info)
294 {
295   char buf[BUFSIZ];
296   sprintf(buf, "Cluster: %-30s Machine: %-20s",
297           info[MAP_CLUSTER], info[MAP_MACHINE]);
298   Put_message(buf);
299   return "";                    /* Used by QueryLoop(). */
300 }
301
302 /*      Function Name: PrintSubnetInfo
303  *      Description: This function Prints out the subnet info
304  *                   in a coherent form.
305  *      Arguments: info - array of information about a subnet.
306  *      Returns: The name of the subnet.
307  */
308
309 static char *PrintSubnetInfo(char **info)
310 {
311   char buf[BUFSIZ];
312   struct in_addr addr, mask, low, high;
313
314   Put_message("");
315   sprintf(buf, "        Network:  %s", info[SN_NAME]);
316   Put_message(buf);
317   sprintf(buf, "    Description:  %s", info[SN_DESC]);
318   Put_message(buf);
319   addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
320   mask.s_addr = htonl(atoi(info[SN_MASK]));
321   low.s_addr = htonl(atoi(info[SN_LOW]));
322   high.s_addr = htonl(atoi(info[SN_HIGH]));
323   /* screwy sequence is here because inet_ntoa returns a pointer to
324      a static buf.  If it were all one sprintf, the last value would
325      appear 4 times. */
326   sprintf(buf, "        Address:  %s        Mask:  ", inet_ntoa(addr));
327   strcat(buf, inet_ntoa(mask));
328   strcat(buf, "\n           High:  ");
329   strcat(buf, inet_ntoa(high));
330   strcat(buf, "       Low:  ");
331   strcat(buf, inet_ntoa(low));
332   Put_message(buf);
333   sprintf(buf, "Hostname prefix:  %s", info[SN_PREFIX]);
334   Put_message(buf);
335   sprintf(buf, "          Owner:  %s %s\n", info[SN_ACE_TYPE],
336           strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : "");
337   Put_message(buf);
338   sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]);
339   Put_message(buf);
340   return info[SN_NAME];
341 }
342
343 /*      Function Name: GetMCInfo.
344  *      Description: This function stores info about a machine.
345  *                   type - type of data we are trying to retrieve.
346  *                   name1 - the name of argv[0] for the call.
347  *                   name2 - the name of argv[1] for the call.
348  *      Returns: the top element of a queue containing the data or NULL.
349  */
350
351 struct qelem *GetMCInfo(int type, char *name1, char *name2)
352 {
353   int stat;
354   struct qelem *elem = NULL;
355   char *args[5];
356
357   switch (type)
358     {
359     case MACHINE:
360       args[0] = name1;
361       args[1] = args[2] = args[3] = "*";
362       if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
363         {
364           if (stat == MR_NO_MATCH)
365             {
366               char buf[128];
367               sprintf(buf, "Machine '%s' is not in the database.", name1);
368               Put_message(buf);
369             }
370           else
371             com_err(program_name, stat, " in get_machine.");
372           return NULL;
373         }
374       break;
375     case CNAME:
376       args[0] = name1;
377       args[1] = name2;
378       if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
379         {
380           com_err(program_name, stat, " in get_hostalias.");
381           return NULL;
382         }
383       break;
384     case SUBNET:
385       if ((stat = do_mr_query("get_subnet", 1, &name1, StoreInfo, &elem)))
386         {
387           if (stat == MR_NO_MATCH)
388             {
389               char buf[128];
390               sprintf(buf, "Network '%s' is not in the database.", name1);
391               Put_message(buf);
392             }
393           else
394             com_err(program_name, stat, " in get_subnet.");
395           return NULL;
396         }
397       break;
398     case CLUSTER:
399       if ((stat = do_mr_query("get_cluster", 1, &name1, StoreInfo, &elem)))
400         {
401           com_err(program_name, stat, " in get_cluster.");
402           return NULL;
403         }
404       break;
405     case MAP:
406       args[MAP_MACHINE] = name1;
407       args[MAP_CLUSTER] = name2;
408       if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args,
409                               StoreInfo, &elem)))
410         {
411           com_err(program_name, stat, " in get_machine_to_cluster_map.");
412           return NULL;
413         }
414       break;
415     case DATA:
416       args[CD_NAME] = name1;
417       args[CD_LABEL] = name2;
418       if ((stat = do_mr_query("get_cluster_data", 2, args, StoreInfo, &elem)))
419         {
420           com_err(program_name, stat, " in get_cluster_data.");
421           return NULL;
422         }
423     }
424   return QueueTop(elem);
425 }
426
427 /*      Function Name: AskMCDInfo.
428  *      Description: This function askes the user for information about a
429  *                   machine and saves it into a structure.
430  *      Arguments: info - a pointer the information to ask about
431  *                 type - type of information - MACHINE
432  *                                              CLUSTER
433  *                                              DATA
434  *                 name - T/F : change the name of this type.
435  *      Returns: none.
436  */
437
438 char **AskMCDInfo(char **info, int type, Bool name)
439 {
440   char temp_buf[BUFSIZ], *newname, *oldnewname;
441
442   switch (type)
443     {
444     case MACHINE:
445       sprintf(temp_buf, "\nSetting the information for the Machine %s...",
446               info[M_NAME]);
447       break;
448     case SUBNET:
449       sprintf(temp_buf, "Setting the information for the Network %s...",
450               info[SN_NAME]);
451       break;
452     case CLUSTER:
453       sprintf(temp_buf, "Setting the information for the Cluster %s...",
454               info[C_NAME]);
455       break;
456     case DATA:
457       sprintf(temp_buf, "Setting the Data for the Cluster %s...",
458               info[CD_NAME]);
459       break;
460     }
461   Put_message(temp_buf);
462
463   if (name)
464     {
465       switch (type)
466         {
467         case MACHINE:
468           newname = strdup(info[M_NAME]);
469           if (GetValueFromUser("The new name for this machine? ", &newname) ==
470               SUB_ERROR)
471             return NULL;
472           oldnewname = strdup(newname);
473           newname = canonicalize_hostname(newname);
474           if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
475             {
476               sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
477                       oldnewname, newname);
478               Put_message(temp_buf);
479             }
480           free(oldnewname);
481           break;
482         case SUBNET:
483           newname = strdup(info[SN_NAME]);
484           if (GetValueFromUser("The new name for this network? ", &newname) ==
485               SUB_ERROR)
486             return NULL;
487           break;
488         case CLUSTER:
489           newname = strdup(info[C_NAME]);
490           if (GetValueFromUser("The new name for this cluster? ", &newname) ==
491               SUB_ERROR)
492             return NULL;
493           break;
494         default:
495           Put_message("Unknown type in AskMCDInfo, programmer botch");
496           return NULL;
497         }
498     }
499
500   switch (type)
501     {
502     case MACHINE:
503       if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
504         return NULL;
505       if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
506         return NULL;
507       if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
508           SUB_ERROR)
509         return NULL;
510       if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
511         return NULL;
512       if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
513           SUB_ERROR)
514         return NULL;
515       while (1)
516         {
517           int i;
518           if (GetValueFromUser("Machine's status (? for help)",
519                                  &info[M_STAT]) == SUB_ERROR)
520             return NULL;
521           if (isdigit(info[M_STAT][0]))
522             break;
523           Put_message("Valid status numbers:");
524           for (i = 0; i < 4; i++)
525             Put_message(states[i]);
526         }
527
528       /* there appears to be some argument mismatch between the client
529        * and the server.. so here is this argument shuffler.
530        * I have since modified this to always shuffle the arguments..
531        * not just do so when performing a modify all fields request.
532        * The SetMachinedefaults() has been changed to reflect this.
533        * pray for us and may we attain enlightenment through structures.
534        */
535
536       if (name)
537         {
538           /* info did not come from SetMachineDefaults(), which does not
539            * initialize entry 8 (M_STAT_CHNG), therefore we can
540            * free it.
541            */
542           /* This is an update of an existing machine and the structure
543            * was filled in thru a query to the db which does fill in this
544            * field.
545            */
546           free(info[8]);
547         }
548
549       info[8] = info[M_SUBNET];
550       info[9] = info[M_ADDR];
551       info[10] = info[M_OWNER_TYPE];
552       info[11] = info[M_OWNER_NAME];
553       info[12] = info[M_ACOMMENT];
554       info[13] = info[M_OCOMMENT];
555
556       if (name)
557         {
558           if (GetValueFromUser("Machine's network (or 'none')", &info[8])
559               == SUB_ERROR)
560             return NULL;
561         }
562       if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
563                            &info[9]) == SUB_ERROR)
564         return NULL;
565       if (GetTypeFromUser("Machine's owner type", "ace_type", &info[10]) ==
566           SUB_ERROR)
567         return NULL;
568       if (strcmp(info[10], "NONE") &&
569           GetValueFromUser("Owner's Name", &info[11]) == SUB_ERROR)
570         return NULL;
571       if (GetValueFromUser("Administrative comment", &info[12]) == SUB_ERROR)
572         return NULL;
573       if (GetValueFromUser("Operational comment", &info[13]) == SUB_ERROR)
574         return NULL;
575       info[14] = NULL;
576       FreeAndClear(&info[15], TRUE);
577       FreeAndClear(&info[16], TRUE);
578       break;
579     case SUBNET:
580       if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
581         return NULL;
582       if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
583         return NULL;
584       if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
585         return NULL;
586       if (atoi(info[SN_LOW]) == ntohl(inet_addr(S_DEFAULT_LOW)))
587         {
588           struct in_addr low;
589           unsigned long mask, addr;
590
591           addr = atoi(info[SN_ADDRESS]);
592           mask = atoi(info[SN_MASK]);
593           low.s_addr = atoi(info[SN_LOW]);
594           low.s_addr = (low.s_addr & ~mask) | (addr & mask);
595           free(info[SN_LOW]);
596           sprintf(temp_buf, "%ld", low.s_addr);
597           info[SN_LOW] = strdup(temp_buf);
598         }
599       if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
600           SUB_ERROR)
601         return NULL;
602       if (atoi(info[SN_HIGH]) == ntohl(inet_addr(S_DEFAULT_HIGH)))
603         {
604           struct in_addr high;
605           unsigned long mask, addr;
606
607           addr = atoi(info[SN_ADDRESS]);
608           mask = atoi(info[SN_MASK]);
609           high.s_addr = atoi(info[SN_HIGH]);
610           high.s_addr = (high.s_addr & ~mask) | (addr & mask);
611           free(info[SN_HIGH]);
612           sprintf(temp_buf, "%ld", high.s_addr);
613           info[SN_HIGH] = strdup(temp_buf);
614         }
615       if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
616           SUB_ERROR)
617         return NULL;
618       if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
619         return NULL;
620       if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
621           SUB_ERROR)
622         return NULL;
623       if (strcmp(info[SN_ACE_TYPE], "NONE") &&
624           GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
625         return NULL;
626       FreeAndClear(&info[SN_MODTIME], TRUE);
627       FreeAndClear(&info[SN_MODBY], TRUE);
628       FreeAndClear(&info[SN_MODWITH], TRUE);
629       break;
630     case CLUSTER:
631       if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
632           SUB_ERROR)
633         return NULL;
634       if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
635           SUB_ERROR)
636         return NULL;
637       FreeAndClear(&info[C_MODTIME], TRUE);
638       FreeAndClear(&info[C_MODBY], TRUE);
639       FreeAndClear(&info[C_MODWITH], TRUE);
640       break;
641     case DATA:
642       if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
643           SUB_ERROR)
644         return NULL;
645       if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
646         return NULL;
647       break;
648     }
649
650   /*
651    * Slide the newname into the #2 slot, this screws up all future references
652    * to this list.
653    */
654   if (name)
655     SlipInNewName(info, newname);
656
657   return info;
658 }
659
660 /* -----------  Machine Menu ----------- */
661
662 /*      Function Name: ShowMachineInfo
663  *      Description: This function shows the information about a machine.
664  *      Arguments: argc, argv - the name of the machine in argv[1].
665  *      Returns: DM_NORMAL.
666  */
667
668 int ShowMachineInfo(int argc, char **argv)
669 {
670   struct qelem *top;
671   char *tmpname;
672
673   tmpname = canonicalize_hostname(strdup(argv[1]));
674   top = GetMCInfo(MACHINE, tmpname, NULL);
675   Loop(top, ((void *) PrintMachInfo));
676   FreeQueue(top);
677   return DM_NORMAL;
678 }
679
680 /*      Function Name: ShowMachineQuery
681  *      Description: This function shows the information about a machine.
682  *              or group of machines, which may be selected through a
683  *              number of criteria.
684  *      Arguments: argc, argv - the name of the machine in argv[1],
685  *              the address of the machine in argv[2],
686  *              the location of the machine in argv[3],
687  *              and the contact name in argv[4].
688  *           any of these may be wildcards.
689  *      Returns: DM_NORMAL.
690  */
691
692 int ShowMachineQuery(int argc, char **argv)
693 {
694   int stat;
695   struct qelem *top, *elem = NULL;
696   char *args[5];
697
698   if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
699       !strcmp(argv[3], "") && !strcmp(argv[4], ""))
700     {
701       Put_message("You must specify at least one parameter of the query.");
702       return DM_NORMAL;
703     }
704
705   if (*argv[1])
706     args[0] = canonicalize_hostname(strdup(argv[1]));
707   else
708     args[0] = "*";
709   if (*argv[2])
710     args[1] = argv[2];
711   else
712     args[1] = "*";
713   if (*argv[3])
714     args[2] = argv[3];
715   else
716     args[2] = "*";
717   if (*argv[4])
718     args[3] = argv[4];
719   else
720     args[3] = "*";
721
722   if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
723     {
724       if (stat == MR_NO_MATCH)
725         Put_message("No machine(s) found matching query in the database.");
726       else
727         com_err(program_name, stat, " in get_machine.");
728       return DM_NORMAL;
729     }
730   top = QueueTop(elem);
731   Loop(top, ((void *) PrintMachInfo));
732   FreeQueue(top);
733   return DM_NORMAL;
734 }
735
736 /*      Function Name: AddMachine
737  *      Description: This function adds a new machine to the database.
738  *      Arguments: argc, argv - the name of the network in argv[1].
739  *      Returns: DM_NORMAL.
740  */
741
742 int AddMachine(int argc, char **argv)
743 {
744   char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
745   char **rinfo;
746   struct qelem *elem = NULL;
747   int stat;
748
749   if (!ValidName(argv[1]))      /* Checks for wildcards. */
750     return DM_NORMAL;
751
752   /*
753    * get the network record
754    */
755
756   if (strcasecmp(argv[1], "none") &&
757       (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem)))
758     {
759       if (stat == MR_NO_MATCH)
760         {
761           char buf[128];
762           sprintf(buf, "Network '%s' is not in the database.", argv[1]);
763           Put_message(buf);
764         } else
765           com_err(program_name, stat, " in get_subnet.");
766       return DM_NORMAL;
767     }
768
769   /*
770    * Check to see if this machine already exists.
771    */
772
773   name = strdup(""); /* want to put prefix here */
774   if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
775     return 0;
776
777   name = canonicalize_hostname(strdup(name));
778
779   xargs[0] = name;
780   xargs[1] = xargs[2] = xargs[3] = "*";
781   if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL)))
782     {
783       sprintf(buf, "The machine '%s' already exists.", name);
784       Put_message(buf);
785       free(name);
786       return DM_NORMAL;
787     }
788   else if (stat != MR_NO_MATCH)
789     {
790       com_err(program_name, stat,
791               " while checking machine '%s' in AddMachine.", name);
792       free(name);
793       return DM_NORMAL;
794     }
795   rinfo = SetMachineDefaults(info, name);
796   rinfo[M_SUBNET] = strdup(argv[1]);
797   if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
798     {
799       Put_message("Aborted.");
800       return DM_NORMAL;
801     }
802
803   /*
804    * Actually create the new Machine.
805    */
806
807   if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL)))
808     com_err(program_name, stat, " in AddMachine.");
809
810   FreeInfo(info);
811   free(name);
812   return DM_NORMAL;
813 }
814
815 /*      Function Name: RealUpdateMachine
816  *      Description: Performs the actual update of the machine data.
817  *      Arguments: info - the information on the machine to update.
818  *                 junk - an UNUSED Boolean.
819  *      Returns: none.
820  */
821
822 static void RealUpdateMachine(char **info, Bool junk)
823 {
824   int stat;
825   char **args = AskMCDInfo(info, MACHINE, TRUE);
826   if (!args)
827     {
828       Put_message("Aborted.");
829       return;
830     }
831   if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL)))
832     com_err(program_name, stat, " in UpdateMachine.");
833   else
834     Put_message("Machine successfully updated.");
835 }
836
837 /*      Function Name: UpdateMachine
838  *      Description: This function adds a new machine to the database.
839  *      Arguments: argc, argv - the name of the machine in argv[1].
840  *      Returns: DM_NORMAL.
841  */
842
843 int UpdateMachine(int argc, char **argv)
844 {
845   struct qelem *top;
846   char *tmpname;
847
848   tmpname = canonicalize_hostname(strdup(argv[1]));
849   top = GetMCInfo(MACHINE, tmpname, NULL);
850   QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
851
852   FreeQueue(top);
853   free(tmpname);
854   return DM_NORMAL;
855 }
856
857 /*      Function Name: CheckAndRemoveFromCluster
858  *      Description: This func tests to see if a machine is in a cluster.
859  *                   and if so then removes it
860  *      Arguments: name - name of the machine (already Canonocalized).
861  *                 ask_user- query the user before removing if from clusters?
862  *      Returns: MR_ERROR if machine left in a cluster, or mr_error.
863  */
864
865 int CheckAndRemoveFromCluster(char *name, Bool ask_user)
866 {
867   int stat, ret_value;
868   Bool delete_it;
869   char *args[10], temp_buf[BUFSIZ], *ptr;
870   struct qelem *top, *elem = NULL;
871
872   ret_value = SUB_NORMAL;       /* initialize ret_value. */
873   args[0] = name;
874   args[1] = "*";
875   stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
876   if (stat && stat != MR_NO_MATCH)
877     {
878       com_err(program_name, stat, " in get_machine_to_cluster_map.");
879       return DM_NORMAL;
880     }
881   if (stat == MR_SUCCESS)
882     {
883       elem = top = QueueTop(elem);
884       if (ask_user)
885         {
886           sprintf(temp_buf, "%s is assigned to the following clusters.", name);
887           Put_message(temp_buf);
888           Loop(top, (void *) PrintMCMap);
889           ptr = "Remove this machine from ** ALL ** these clusters?";
890           if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
891             delete_it = TRUE;
892           else
893             {
894               Put_message("Aborting...");
895               FreeQueue(top);
896               return SUB_ERROR;
897             }
898         }
899       else
900         delete_it = TRUE;
901
902       if (delete_it)
903         {
904           while (elem)
905             {
906               char **info = elem->q_data;
907               if ((stat = do_mr_query("delete_machine_from_cluster",
908                                        2, info, NULL, NULL)))
909                 {
910                   ret_value = SUB_ERROR;
911                   com_err(program_name, stat,
912                           " in delete_machine_from_cluster.");
913                   sprintf(temp_buf,
914                           "Machine %s ** NOT ** removed from cluster %s.",
915                           info[MAP_MACHINE], info[MAP_CLUSTER]);
916                   Put_message(temp_buf);
917                 }
918               elem = elem->q_forw;
919             }
920         }
921     }
922   return ret_value;
923 }
924
925 /*      Function Name: RealDeleteMachine
926  *      Description: Actually Deletes the Machine.
927  *      Arguments: info - nescessary information stored as an array of char *'s
928  *                 one_machine - a boolean, true if there is only one item in
929  *                               the query.
930  *      Returns: none.
931  */
932
933 static void RealDeleteMachine(char **info, Bool one_machine)
934 {
935   int stat;
936   char temp_buf[BUFSIZ];
937
938   sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
939           info[M_NAME]);
940   if (!one_machine || Confirm(temp_buf))
941     {
942       if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
943         {
944           if ((stat = do_mr_query("delete_host", 1,
945                                   &info[M_NAME], NULL, NULL)))
946             {
947               com_err(program_name, stat, " in DeleteMachine.");
948               sprintf(temp_buf, "%s ** NOT ** deleted.",
949                       info[M_NAME]);
950               Put_message(temp_buf);
951             }
952           else
953             {
954               sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
955               Put_message(temp_buf);
956             }
957         }
958     }
959 }
960
961 /*      Function Name: DeleteMachine
962  *      Description: This function removes a machine from the data base.
963  *      Arguments: argc, argv - the machines name int argv[1].
964  *      Returns: DM_NORMAL.
965  */
966
967 /* Perhaps we should remove the cluster if it has no machine now. */
968
969 int DeleteMachine(int argc, char **argv)
970 {
971   struct qelem *top;
972   char *tmpname;
973
974   tmpname = canonicalize_hostname(strdup(argv[1]));
975   top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
976   QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
977   FreeQueue(top);
978   free(tmpname);
979   return DM_NORMAL;
980 }
981
982
983 char *partial_canonicalize_hostname(char *s)
984 {
985   char buf[256], *cp;
986   static char *def_domain = NULL;
987   struct hostent *hp;
988   struct utsname name;
989
990   if (!def_domain)
991     {
992       uname(&name);
993       hp = gethostbyname(name.nodename);
994       cp = strchr(hp->h_name, '.');
995       if (cp)
996         def_domain = strdup(++cp);
997       else
998         def_domain = "";
999     }
1000
1001   if (strchr(s, '.') || strchr(s, '*'))
1002     return s;
1003   sprintf(buf, "%s.%s", s, def_domain);
1004   free(s);
1005   return strdup(buf);
1006 }
1007
1008
1009 /*      Function Name: ShowCname
1010  *      Description: This function shows machine aliases
1011  *      Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1012  *      Returns: DM_NORMAL.
1013  */
1014
1015 int ShowCname(int argc, char **argv)
1016 {
1017   struct qelem *top;
1018   char *tmpalias, *tmpname;
1019
1020   tmpalias = partial_canonicalize_hostname(strdup(argv[1]));
1021   tmpname = canonicalize_hostname(strdup(argv[2]));
1022   top = GetMCInfo(CNAME, tmpalias, tmpname);
1023   Put_message("");              /* blank line on screen */
1024   Loop(top, ((void *) PrintCname));
1025   FreeQueue(top);
1026   return DM_NORMAL;
1027 }
1028
1029
1030 int AddCname(int argc, char **argv)
1031 {
1032   int stat;
1033   char *args[10];
1034
1035   args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1036   args[1] = canonicalize_hostname(strdup(argv[2]));
1037   stat = do_mr_query("add_hostalias", 2, args, NULL, NULL);
1038   switch (stat)
1039     {
1040     case MR_SUCCESS:
1041       break;
1042     case MR_EXISTS:
1043       Put_message("That alias name is already in use.");
1044       break;
1045     case MR_PERM:
1046       Put_message("Permission denied.  "
1047                   "(Regular users can only add two aliases to a host.");
1048       break;
1049     default:
1050       com_err(program_name, stat, " in add_hostalias");
1051     }
1052   return DM_NORMAL;
1053 }
1054
1055
1056 int DeleteCname(int argc, char **argv)
1057 {
1058   int stat;
1059   char *args[10];
1060
1061   args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1062   args[1] = canonicalize_hostname(strdup(argv[2]));
1063   stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL);
1064   if (stat)
1065     com_err(program_name, stat, " in delete_hostalias");
1066   return DM_NORMAL;
1067 }
1068
1069
1070 /*      Function Name: AddMachineToCluster
1071  *      Description: This function adds a machine to a cluster
1072  *      Arguments: argc, argv - The machine name is argv[1].
1073  *                              The cluster name in argv[2].
1074  *      Returns: DM_NORMAL.
1075  */
1076
1077 int AddMachineToCluster(int argc, char **argv)
1078 {
1079   int stat;
1080   char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1081   Bool add_it, one_machine, one_cluster;
1082   struct qelem *melem, *mtop, *celem, *ctop;
1083
1084   machine = canonicalize_hostname(strdup(argv[1]));
1085   if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1086     {
1087       sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1088               argv[1], machine);
1089       Put_message(temp_buf);
1090     }
1091   cluster = argv[2];
1092
1093   celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1094   melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1095   free(machine);
1096
1097   one_machine = (QueueCount(mtop) == 1);
1098   one_cluster = (QueueCount(ctop) == 1);
1099
1100   /* No good way to use QueryLoop() here, sigh */
1101
1102   while (melem)
1103     {
1104       char **minfo = melem->q_data;
1105       while (celem)
1106         {
1107           char **cinfo = celem->q_data;
1108           if (one_machine && one_cluster)
1109             add_it = TRUE;
1110           else
1111             {
1112               sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1113                       minfo[M_NAME], cinfo[C_NAME]);
1114               switch (YesNoQuitQuestion(temp_buf, FALSE))
1115                 {
1116                 case TRUE:
1117                   add_it = TRUE;
1118                   break;
1119                 case FALSE:
1120                   add_it = FALSE;
1121                   break;
1122                 default:
1123                   Put_message("Aborting...");
1124                   FreeQueue(ctop);
1125                   FreeQueue(mtop);
1126                   return DM_NORMAL;
1127                 }
1128             }
1129           if (add_it)
1130             {
1131               args[0] = minfo[M_NAME];
1132               args[1] = cinfo[C_NAME];
1133               stat = do_mr_query("add_machine_to_cluster", 2, args,
1134                                  NULL, NULL);
1135               switch (stat)
1136                 {
1137                 case MR_SUCCESS:
1138                   break;
1139                 case MR_EXISTS:
1140                   sprintf(temp_buf, "%s is already in cluster %s",
1141                           minfo[M_NAME], cinfo[C_NAME]);
1142                   Put_message(temp_buf);
1143                   break;
1144                 default:
1145                   com_err(program_name, stat, " in AddMachineToCluster.");
1146                   break;
1147                 }
1148             }
1149           celem = celem->q_forw;
1150         }
1151       celem = ctop;             /* reset cluster element. */
1152       melem = melem->q_forw;
1153     }
1154   FreeQueue(ctop);
1155   FreeQueue(mtop);
1156   return DM_NORMAL;
1157 }
1158
1159 /*      Function Name: RealRemoveMachineFromCluster
1160  *      Description: This function actually removes the machine from its
1161  *                   cluster.
1162  *      Arguments: info - all information nescessary to perform the removal.
1163  *                 one_map - True if there is only one case, and we should
1164  *                           confirm.
1165  *      Returns: none.
1166  */
1167
1168 static void RealRemoveMachineFromCluster(char **info, Bool one_map)
1169 {
1170   char temp_buf[BUFSIZ];
1171   int stat;
1172
1173   sprintf(temp_buf, "Remove %s from the cluster %s",
1174           info[MAP_MACHINE], info[MAP_CLUSTER]);
1175   if (!one_map || Confirm(temp_buf))
1176     {
1177       if ((stat = do_mr_query("delete_machine_from_cluster", 2,
1178                               info, NULL, NULL)))
1179         com_err(program_name, stat, " in delete_machine_from_cluster");
1180       else
1181         {
1182           sprintf(temp_buf, "%s has been removed from the cluster %s.",
1183                   info[MAP_MACHINE], info[MAP_CLUSTER]);
1184           Put_message(temp_buf);
1185         }
1186     }
1187   else
1188     Put_message("Machine not removed.");
1189 }
1190
1191 /*      Function Name: RemoveMachineFromCluster
1192  *      Description: Removes this machine form a specific cluster.
1193  *      Arguments: argc, argv - Name of machine in argv[1].
1194  *                              Name of cluster in argv[2].
1195  *      Returns: none.
1196  */
1197
1198 int RemoveMachineFromCluster(int argc, char **argv)
1199 {
1200   struct qelem *elem = NULL;
1201   char buf[BUFSIZ], * args[10];
1202   int stat;
1203
1204   args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1]));
1205   if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1206     {
1207       sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1208               argv[1], args[MAP_MACHINE]);
1209       Put_message(buf);
1210     }
1211   args[MAP_CLUSTER] = argv[2];
1212   args[MAP_END] = NULL;
1213
1214   stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
1215                      StoreInfo, &elem);
1216   if (stat == MR_NO_MATCH)
1217     {
1218       sprintf(buf, "The machine %s is not is the cluster %s.",
1219               args[MAP_MACHINE], args[MAP_CLUSTER]);
1220       Put_message(buf);
1221       free(args[MAP_MACHINE]);
1222       return DM_NORMAL;
1223     }
1224   if (stat != MR_SUCCESS)
1225     com_err(program_name, stat, " in delete_machine_from_cluster");
1226
1227   elem = QueueTop(elem);
1228   QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1229             "Remove this machine from this cluster");
1230
1231   FreeQueue(elem);
1232   free(args[MAP_MACHINE]);
1233   return DM_NORMAL;
1234 }
1235
1236 /* ---------- Subnet Menu -------- */
1237
1238 /*      Function Name: ShowSubnetInfo
1239  *      Description: Gets information about a subnet given its name.
1240  *      Arguments: argc, argc - the name of the subnet in in argv[1].
1241  *      Returns: DM_NORMAL.
1242  */
1243
1244 int ShowSubnetInfo(int argc, char **argv)
1245 {
1246   struct qelem *top;
1247
1248   top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
1249   Loop(top, (void *) PrintSubnetInfo);
1250   FreeQueue(top);
1251   return DM_NORMAL;
1252 }
1253
1254 /*      Function Name: AddSubnet
1255  *      Description: Creates a new subnet.
1256  *      Arguments: argc, argv - the name of the new subnet is argv[1].
1257  *      Returns: DM_NORMAL.
1258  */
1259
1260 int AddSubnet(int argc, char **argv)
1261 {
1262   char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1263   int stat;
1264
1265   /*
1266    * Check to see if this subnet already exists.
1267    */
1268   if (!ValidName(name))
1269     return DM_NORMAL;
1270
1271   if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS)
1272     {
1273       Put_message("This subnet already exists.");
1274       return DM_NORMAL;
1275     }
1276   else if (stat != MR_NO_MATCH)
1277     {
1278       com_err(program_name, stat, " in AddSubnet.");
1279       return DM_NORMAL;
1280     }
1281   if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1282     {
1283       Put_message("Aborted.");
1284       FreeInfo(info);
1285       return DM_NORMAL;
1286     }
1287
1288   /*
1289    * Actually create the new Subnet.
1290    */
1291   if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL)))
1292     com_err(program_name, stat, " in AddSubnet.");
1293
1294   FreeInfo(info);
1295   return DM_NORMAL;
1296 }
1297
1298 /*      Function Name: RealUpdateSubnet
1299  *      Description: This function actually performs the subnet update.
1300  *      Arguments: info - all information nesc. for updating the subnet.
1301  *                 junk - an UNUSED boolean.
1302  *      Returns: none.
1303  */
1304
1305 static void RealUpdateSubnet(char **info, Bool junk)
1306 {
1307   int stat;
1308   char **args = AskMCDInfo(info, SUBNET, TRUE);
1309   if (!args)
1310     {
1311       Put_message("Aborted.");
1312       return;
1313     }
1314   if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL)))
1315     com_err(program_name, stat, " in UpdateSubnet.");
1316   else
1317     Put_message("Subnet successfully updated.");
1318 }
1319
1320 /*      Function Name: UpdateSubnet
1321  *      Description: This Function Updates a subnet
1322  *      Arguments: name of the subnet in argv[1].
1323  *      Returns: DM_NORMAL.
1324  */
1325
1326 int UpdateSubnet(int argc, char **argv)
1327 {
1328   struct qelem *top;
1329   top = GetMCInfo(SUBNET, argv[1], NULL);
1330   QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
1331
1332   FreeQueue(top);
1333   return DM_NORMAL;
1334 }
1335
1336 /*      Function Name: RealDeleteSubnet
1337  *      Description: Actually performs the subnet deletion.
1338  *      Arguments: info - all information about this subnet.
1339  *                 one_subnet - If true then there was only one subnet in
1340  *                               the queue, and we should confirm.
1341  *      Returns: none.
1342  */
1343
1344 static void RealDeleteSubnet(char **info, Bool one_subnet)
1345 {
1346   int stat;
1347   char temp_buf[BUFSIZ];
1348
1349   sprintf(temp_buf,
1350           "Are you sure the you want to delete the subnet %s (y/n) ?",
1351           info[C_NAME]);
1352   if (!one_subnet || Confirm(temp_buf))
1353     {
1354       if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL)))
1355         {
1356           com_err(program_name, stat, " in delete_subnet.");
1357           sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1358           Put_message(temp_buf);
1359         }
1360       else
1361         {
1362           sprintf(temp_buf, "subnet %s successfully deleted.",
1363                   info[C_NAME]);
1364           Put_message(temp_buf);
1365         }
1366     }
1367 }
1368
1369 /*      Function Name: DeleteSubnet
1370  *      Description: This function removes a subnet from the database.
1371  *      Arguments: argc, argv - the name of the subnet is stored in argv[1].
1372  *      Returns: DM_NORMAL.
1373  */
1374
1375 int DeleteSubnet(int argc, char **argv)
1376 {
1377   struct qelem *top;
1378
1379   top = GetMCInfo(SUBNET, argv[1], NULL);
1380   QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
1381
1382   FreeQueue(top);
1383   return DM_NORMAL;
1384 }
1385
1386 /* ---------- Cluster Menu -------- */
1387
1388 /*      Function Name: ShowClusterInfo
1389  *      Description: Gets information about a cluser given its name.
1390  *      Arguments: argc, argc - the name of the cluster in in argv[1].
1391  *      Returns: DM_NORMAL.
1392  */
1393
1394 int ShowClusterInfo(int argc, char **argv)
1395 {
1396   struct qelem *top;
1397
1398   top = GetMCInfo(CLUSTER, argv[1], NULL);
1399   Loop(top, (void *) PrintClusterInfo);
1400   FreeQueue(top);
1401   return DM_NORMAL;
1402 }
1403
1404 /*      Function Name: AddCluster
1405  *      Description: Creates a new cluster.
1406  *      Arguments: argc, argv - the name of the new cluster is argv[1].
1407  *      Returns: DM_NORMAL.
1408  */
1409
1410 int AddCluster(int argc, char **argv)
1411 {
1412   char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1413   int stat;
1414
1415   /*
1416    * Check to see if this cluster already exists.
1417    */
1418   if (!ValidName(name))
1419     return DM_NORMAL;
1420
1421   if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS)
1422     {
1423       Put_message("This cluster already exists.");
1424       return DM_NORMAL;
1425     }
1426   else if (stat != MR_NO_MATCH)
1427     {
1428       com_err(program_name, stat, " in AddCluster.");
1429       return DM_NORMAL;
1430     }
1431   if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1432     {
1433       Put_message("Aborted.");
1434       FreeInfo(info);
1435       return DM_NORMAL;
1436     }
1437
1438   /*
1439    * Actually create the new Cluster.
1440    */
1441   if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL)))
1442     com_err(program_name, stat, " in AddCluster.");
1443
1444   FreeInfo(info);
1445   return DM_NORMAL;
1446 }
1447
1448 /*      Function Name: RealUpdateCluster
1449  *      Description: This function actually performs the cluster update.
1450  *      Arguments: info - all information nesc. for updating the cluster.
1451  *                 junk - an UNUSED boolean.
1452  *      Returns: none.
1453  */
1454
1455 static void RealUpdateCluster(char **info, Bool junk)
1456 {
1457   int stat;
1458   char **args = AskMCDInfo(info, CLUSTER, TRUE);
1459
1460   if (!args)
1461     {
1462       Put_message("Aborted.");
1463       return;
1464     }
1465   if ((stat = do_mr_query("update_cluster", CountArgs(args),
1466                           args, NULL, NULL)))
1467     com_err(program_name, stat, " in UpdateCluster.");
1468   else
1469     Put_message("Cluster successfully updated.");
1470 }
1471
1472 /*      Function Name: UpdateCluster
1473  *      Description: This Function Updates a cluster
1474  *      Arguments: name of the cluster in argv[1].
1475  *      Returns: DM_NORMAL.
1476  */
1477
1478 int UpdateCluster(int argc, char **argv)
1479 {
1480   struct qelem *top;
1481   top = GetMCInfo(CLUSTER, argv[1], NULL);
1482   QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
1483
1484   FreeQueue(top);
1485   return DM_NORMAL;
1486 }
1487
1488 /*      Function Name: CheckAndRemoveMachine
1489  *      Description: This function checks and removes all machines from a
1490  *                   cluster.
1491  *      Arguments: name - name of the cluster.
1492  *                 ask_first - if TRUE, then we will query the user, before
1493  *                             deletion.
1494  *      Returns: SUB_ERROR if all machines not removed.
1495  */
1496
1497 int CheckAndRemoveMachines(char *name, Bool ask_first)
1498 {
1499   int stat, ret_value;
1500   Bool delete_it;
1501   char *args[10], temp_buf[BUFSIZ], *ptr;
1502   struct qelem *top, *elem = NULL;
1503
1504   ret_value = SUB_NORMAL;
1505   args[MAP_MACHINE] = "*";
1506   args[MAP_CLUSTER] = name;
1507   stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
1508   if (stat && stat != MR_NO_MATCH)
1509     {
1510       com_err(program_name, stat, " in get_machine_to_cluster_map.");
1511       return DM_NORMAL;
1512     }
1513   if (stat == MR_SUCCESS)
1514     {
1515       elem = top = QueueTop(elem);
1516       if (ask_first)
1517         {
1518           sprintf(temp_buf, "The cluster %s has the following machines in it:",
1519                   name);
1520           Put_message(temp_buf);
1521           while (elem)
1522             {
1523               char **info = elem->q_data;
1524               Print(1, &info[MAP_MACHINE], (char *) NULL);
1525               elem = elem->q_forw;
1526             }
1527           ptr = "Remove ** ALL ** these machines from this cluster?";
1528
1529           if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1530             delete_it = TRUE;
1531           else
1532             {
1533               Put_message("Aborting...");
1534               FreeQueue(top);
1535               return SUB_ERROR;
1536             }
1537         }
1538       else
1539         delete_it = TRUE;
1540
1541       if (delete_it)
1542         {
1543           elem = top;
1544           while (elem)
1545             {
1546               char **info = elem->q_data;
1547               if ((stat = do_mr_query("delete_machine_from_cluster",
1548                                       2, info, NULL, NULL)))
1549                 {
1550                   ret_value = SUB_ERROR;
1551                   com_err(program_name, stat,
1552                           " in delete_machine_from_cluster.");
1553                   sprintf(temp_buf,
1554                           "Machine %s ** NOT ** removed from cluster %s.",
1555                           info[MAP_MACHINE], info[MAP_CLUSTER]);
1556                   Put_message(temp_buf);
1557                 }
1558               elem = elem->q_forw;
1559             }
1560         }
1561     }
1562   return ret_value;
1563 }
1564
1565 /*      Function Name: RealDeleteCluster
1566  *      Description: Actually performs the cluster deletion.
1567  *      Arguments: info - all information about this cluster.
1568  *                 one_cluster - If true then there was only one cluster in
1569  *                               the queue, and we should confirm.
1570  *      Returns: none.
1571  */
1572
1573 static void RealDeleteCluster(char **info, Bool one_cluster)
1574 {
1575   int stat;
1576   char temp_buf[BUFSIZ];
1577
1578   sprintf(temp_buf,
1579           "Are you sure the you want to delete the cluster %s (y/n) ?",
1580           info[C_NAME]);
1581   if (!one_cluster || Confirm(temp_buf))
1582     {
1583       if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1584         {
1585           if ((stat = do_mr_query("delete_cluster", 1,
1586                                   &info[C_NAME], NULL, NULL)))
1587             {
1588               com_err(program_name, stat, " in delete_cluster.");
1589               sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1590               Put_message(temp_buf);
1591             }
1592           else
1593             {
1594               sprintf(temp_buf, "cluster %s successfully deleted.",
1595                       info[C_NAME]);
1596               Put_message(temp_buf);
1597             }
1598         }
1599     }
1600 }
1601
1602 /*      Function Name: DeleteCluster
1603  *      Description: This function removes a cluster from the database.
1604  *      Arguments: argc, argv - the name of the cluster is stored in argv[1].
1605  *      Returns: DM_NORMAL.
1606  */
1607
1608 int DeleteCluster(int argc, char **argv)
1609 {
1610   struct qelem *top;
1611
1612   top = GetMCInfo(CLUSTER, argv[1], NULL);
1613   QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
1614
1615   FreeQueue(top);
1616   return DM_NORMAL;
1617 }
1618
1619 /* ----------- Cluster Data Menu -------------- */
1620
1621 /*      Function Name: ShowClusterData
1622  *      Description: This function shows the services for one cluster.
1623  *      Arguments: argc, argv - The name of the cluster is argv[1].
1624  *                              The label of the data in argv[2].
1625  *      Returns: DM_NORMAL.
1626  */
1627
1628 int ShowClusterData(int argc, char **argv)
1629 {
1630   struct qelem *elem, *top;
1631   char **info;
1632
1633   top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1634   while (elem)
1635     {
1636       info = elem->q_data;
1637       PrintClusterData(info);
1638       elem = elem->q_forw;
1639     }
1640   FreeQueue(top);
1641   return DM_NORMAL;
1642 }
1643
1644 /*      Function Name: AddClusterData
1645  *      Description: This function adds some data to the cluster.
1646  *      Arguments: argv, argc:   argv[1] - the name of the cluster.
1647  *                               argv[2] - the label of the data.
1648  *                               argv[3] - the data.
1649  *      Returns: DM_NORMAL.
1650  */
1651
1652 int AddClusterData(int argc, char **argv)
1653 {
1654   int stat;
1655
1656   if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
1657     com_err(program_name, stat, " in AddClusterData.");
1658   return DM_NORMAL;
1659 }
1660
1661 /*      Function Name: RealRemoveClusterData
1662  *      Description: actually removes the cluster data.
1663  *      Arguments: info - all info necessary to remove the cluster, in an array
1664  *                        of strings.
1665  *                 one_item - if true then the queue has only one elem and we
1666  *                            should confirm.
1667  *      Returns: none.
1668  */
1669
1670 static void RealRemoveClusterData(char **info, Bool one_item)
1671 {
1672   int stat;
1673   char *temp_ptr;
1674
1675   Put_message(" ");
1676   temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1677   PrintClusterData(info);
1678   if (!one_item || Confirm(temp_ptr))
1679     {
1680       if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
1681         {
1682           com_err(program_name, stat, " in DeleteClusterData.");
1683           Put_message("Data not removed.");
1684         }
1685       else
1686         Put_message("Removal successful.");
1687     }
1688 }
1689
1690 /*      Function Name: RemoveClusterData
1691  *      Description: This function removes data on a given cluster.
1692  *      Arguments: argv, argc:   argv[1] - the name of the cluster.
1693  *                               argv[2] - the label of the data.
1694  *                               argv[3] - the data.
1695  *      Returns: DM_NORMAL.
1696  */
1697
1698 int RemoveClusterData(int argc, char **argv)
1699 {
1700   struct qelem *top;
1701
1702   top = GetMCInfo(DATA, argv[1], argv[2]);
1703   QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1704             "Remove data from cluster");
1705
1706   FreeQueue(top);
1707   return DM_NORMAL;
1708 }
1709
1710 /*      Function Name: MachineToClusterMap
1711  *      Description: This Retrieves the mapping between machine and cluster
1712  *      Arguments: argc, argv - argv[1] -> machine name or wildcard.
1713  *                              argv[2] -> cluster name or wildcard.
1714  *      Returns: none.
1715  */
1716
1717 int MachineToClusterMap(int argc, char **argv)
1718 {
1719   struct qelem *elem, *top;
1720   char *tmpname, temp_buf[256];
1721
1722   tmpname = canonicalize_hostname(strdup(argv[1]));
1723   if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
1724     {
1725       sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1726               argv[1], tmpname);
1727       Put_message(temp_buf);
1728     }
1729   top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1730
1731   Put_message("");              /* blank line on screen */
1732   while (elem)
1733     {
1734       char **info = elem->q_data;
1735       PrintMCMap(info);
1736       elem = elem->q_forw;
1737     }
1738
1739   FreeQueue(top);
1740   free(tmpname);
1741   return DM_NORMAL;
1742 }
This page took 0.1907 seconds and 5 git commands to generate.