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