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