]> andersk Git - moira.git/blame - clients/moira/cluster.c
Implement support for container related queries.
[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>
a721bbae 20#include <mrclient.h>
7ac48069 21
22#include "defs.h"
23#include "f_defs.h"
24#include "globals.h"
25
600b459e 26#include <sys/types.h>
533bacb3 27
28#ifdef HAVE_UNAME
7ac48069 29#include <sys/utsname.h>
533bacb3 30#endif
7ac48069 31
533bacb3 32#ifndef _WIN32
ad7e0e04 33#include <netinet/in.h>
34#include <arpa/inet.h>
5cfca28f 35#include <netdb.h>
533bacb3 36#endif /* _WIN32 */
7ac48069 37
5098c1de 38#include <ctype.h>
7ac48069 39#include <stdio.h>
40#include <stdlib.h>
41#include <string.h>
08345b74 42
7ac48069 43void PrintAliases(char **info);
bc8eefd1 44static void PrintMachine(char **info);
600b459e 45struct mqelem *GetMCInfo(int type, char *name1, char *name2);
7399b4b2 46struct mqelem *GetMachineByOwner(char *type, char *name);
7ac48069 47char **AskMCDInfo(char **info, int type, Bool name);
48int CheckAndRemoveFromCluster(char *name, Bool ask_user);
6d35002c 49int CheckAndRemoveCnames(char *name, Bool ask_user);
7ac48069 50int CheckAndRemoveMachines(char *name, Bool ask_first);
08345b74 51
9cd2d193 52static char *PrintContainerInfo(char **info);
53static void RealUpdateContainer(char **info, Bool junk);
54static void RealDeleteContainer(char **info, Bool one_container);
55static void RealRemoveMachineFromContainer(char **info, Bool one_contmap);
56
57#define MACHINE 0
58#define CLUSTER 1
59#define DATA 2
60#define MAP 3
61#define SUBNET 4
62#define CNAME 5
63#define CONTAINER 6
64#define CONTMAP 7
08345b74 65
85ca828a 66#define M_DEFAULT_TYPE DEFAULT_NONE
67
68#define C_DEFAULT_DESCRIPT DEFAULT_NONE
69#define C_DEFAULT_LOCATION DEFAULT_NONE
70
9cd2d193 71#define CON_DEFAULT_TYPE DEFAULT_NONE
72
85ca828a 73#define CD_DEFAULT_LABEL DEFAULT_NONE
74#define CD_DEFAULT_DATA DEFAULT_NONE
75
54864ee6 76#define S_DEFAULT_LOW "18.0.0.20"
77#define S_DEFAULT_HIGH "18.0.2.249"
ad7e0e04 78
5eaef520 79static char *states[] = {
80 "Reserved (0)",
81 "Active (1)",
82 "None (2)",
83 "Deleted (3)"
84};
85
86static char *MacState(int state)
ad7e0e04 87{
5eaef520 88 static char buf[BUFSIZ];
ad7e0e04 89
5eaef520 90 if (state < 0 || state > 3)
91 {
92 sprintf(buf, "Unknown (%d)", state);
93 return buf;
ad7e0e04 94 }
5eaef520 95 return states[state];
ad7e0e04 96}
97
98
99
85ca828a 100/* -------------------- Set Defaults -------------------- */
101
102/* Function Name: SetMachineDefaults
103 * Description: sets machine defaults.
104 * Arguments: info - an array to put the defaults into.
105 * name - Canonacalized name of the machine.
106 * Returns: info - the array.
107 */
108
5eaef520 109static char **SetMachineDefaults(char **info, char *name)
85ca828a 110{
7ac48069 111 info[M_NAME] = strdup(name);
112 info[M_VENDOR] = strdup(M_DEFAULT_TYPE);
113 info[M_MODEL] = strdup(M_DEFAULT_TYPE);
114 info[M_OS] = strdup(M_DEFAULT_TYPE);
115 info[M_LOC] = strdup(M_DEFAULT_TYPE);
116 info[M_CONTACT] = strdup(M_DEFAULT_TYPE);
2f2d9dfc 117 info[M_BILL_CONTACT] = strdup(M_DEFAULT_TYPE);
7ac48069 118 info[M_USE] = strdup("0");
119 info[M_STAT] = strdup("1");
120 info[M_SUBNET] = strdup("NONE");
121 info[M_ADDR] = strdup("unique");
122 info[M_OWNER_TYPE] = strdup("NONE");
123 info[M_OWNER_NAME] = strdup("NONE");
124 info[M_ACOMMENT] = strdup("");
125 info[M_OCOMMENT] = strdup("");
2f2d9dfc 126 info[16] = info[17] = NULL;
5eaef520 127 return info;
85ca828a 128}
129
130/* Function Name: SetClusterDefaults
131 * Description: sets Cluster defaults.
132 * Arguments: info - an array to put the defaults into.
133 * name - name of the Cluster.
134 * Returns: info - the array.
135 */
136
5eaef520 137static char **SetClusterDefaults(char **info, char *name)
85ca828a 138{
7ac48069 139 info[C_NAME] = strdup(name);
140 info[C_DESCRIPT] = strdup(C_DEFAULT_DESCRIPT);
141 info[C_LOCATION] = strdup(C_DEFAULT_LOCATION);
5eaef520 142 info[C_MODBY] = info[C_MODTIME] = info[C_MODWITH] = info[C_END] = NULL;
143 return info;
85ca828a 144}
145
9cd2d193 146static char **SetContainerDefaults(char **info, char *name)
147{
148 info[CON_NAME] = strdup(name);
149 info[CON_DESCRIPT] = strdup(CON_DEFAULT_TYPE);
150 info[CON_LOCATION] = strdup(CON_DEFAULT_TYPE);
151 info[CON_CONTACT] = strdup(CON_DEFAULT_TYPE);
152 info[CON_OWNER_TYPE] = strdup("NONE");
153 info[CON_OWNER_NAME] = strdup("NONE");
154 info[CON_MEMACE_TYPE] = strdup("NONE");
155 info[CON_MEMACE_NAME] = strdup("NONE");
156 info[CON_MODBY] = info[CON_MODTIME] = info[CON_MODWITH] = NULL;
157 info[CON_END] = NULL;
158 return info;
159}
160
ad7e0e04 161/* Function Name: SetSubnetDefaults
162 * Description: sets Subnet defaults.
163 * Arguments: info - an array to put the defaults into.
164 * name - name of the Subnet.
165 * Returns: info - the array.
166 */
167
5eaef520 168static char **SetSubnetDefaults(char **info, char *name)
ad7e0e04 169{
5eaef520 170 char buf[256];
171
7ac48069 172 info[C_NAME] = strdup(name);
173 info[SN_DESC] = strdup("");
5eaef520 174 sprintf(buf, "%ld", ntohl(inet_addr("18.255.0.0")));
7ac48069 175 info[SN_ADDRESS] = strdup(buf);
5eaef520 176 sprintf(buf, "%ld", ntohl(inet_addr("255.255.0.0")));
7ac48069 177 info[SN_MASK] = strdup(buf);
5eaef520 178 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_LOW)));
7ac48069 179 info[SN_LOW] = strdup(buf);
5eaef520 180 sprintf(buf, "%ld", ntohl(inet_addr(S_DEFAULT_HIGH)));
7ac48069 181 info[SN_HIGH] = strdup(buf);
182 info[SN_PREFIX] = strdup("");
183 info[SN_ACE_TYPE] = strdup("LIST");
184 info[SN_ACE_NAME] = strdup("network");
5eaef520 185 info[SN_MODBY] = info[SN_MODTIME] = info[SN_MODWITH] = info[SN_END] = NULL;
186 return info;
ad7e0e04 187}
188
85ca828a 189/* -------------------- General Functions -------------------- */
190
5cfca28f 191static char aliasbuf[256];
192
7ac48069 193void PrintAliases(char **info)
5cfca28f 194{
5eaef520 195 if (strlen(aliasbuf) == 0)
196 sprintf(aliasbuf, "Aliases: %s", info[0]);
197 else
198 {
199 strcat(aliasbuf, ", ");
200 strcat(aliasbuf, info[0]);
5cfca28f 201 }
202}
203
204
08345b74 205/* Function Name: PrintMachInfo
5eaef520 206 * Description: This function Prints out the Machine info in
08345b74 207 * a coherent form.
208 * Arguments: info - array of information about a machine.
402461ad 209 * Returns: The name of the Machine
08345b74 210 */
211
5eaef520 212static char *PrintMachInfo(char **info)
08345b74 213{
5eaef520 214 char buf[BUFSIZ], tbuf[256];
215 char *args[3];
600b459e 216 struct mqelem *elem = NULL;
5eaef520 217 int stat;
218
219 Put_message("");
220 sprintf(buf, "Machine: %s", info[M_NAME]);
221 Put_message(buf);
222 args[0] = "*";
223 args[1] = info[M_NAME];
7ac48069 224 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
5eaef520 225 {
226 if (stat != MR_NO_MATCH)
227 com_err(program_name, stat, " looking up aliases");
228 }
229 else
230 {
231 aliasbuf[0] = 0;
a6da9354 232 Loop(QueueTop(elem), (void (*)(char **)) PrintAliases);
5eaef520 233 FreeQueue(elem);
234 Put_message(aliasbuf);
5cfca28f 235 }
5eaef520 236 sprintf(tbuf, "%s %s", info[M_OWNER_TYPE],
237 strcmp(info[M_OWNER_TYPE], "NONE") ? info[M_OWNER_NAME] : "");
238 sprintf(buf, "Address: %-16s Network: %-16s",
239 info[M_ADDR], info[M_SUBNET]);
240 Put_message(buf);
241 sprintf(buf, "Owner: %-16s Use data: %s", tbuf, info[M_INUSE]);
242 Put_message(buf);
243 sprintf(buf, "Status: %-16s Changed: %s",
244 MacState(atoi(info[M_STAT])), info[M_STAT_CHNG]);
245 Put_message(buf);
246 Put_message("");
247
2f2d9dfc 248 sprintf(buf, "Vendor: %-16s Location: %s", info[M_VENDOR],
249 info[M_LOC]);
5eaef520 250 Put_message(buf);
2f2d9dfc 251 sprintf(buf, "Model: %-16s Contact: %s", info[M_MODEL],
252 info[M_CONTACT]);
253 Put_message(buf);
254 sprintf(buf, "OS: %-16s Billing Contact: %s", info[M_OS],
255 info[M_BILL_CONTACT]);
256 Put_message(buf);
8595ce23 257 Put_message("");
258 sprintf(buf, "Opt: %s", info[M_USE]);
5eaef520 259 Put_message(buf);
8595ce23 260 Put_message("");
261 sprintf(buf, "Adm cmt: %s", info[M_ACOMMENT]);
5eaef520 262 Put_message(buf);
263 sprintf(buf, "Op cmt: %s", info[M_OCOMMENT]);
264 Put_message(buf);
265 Put_message("");
266 sprintf(buf, "Created by %s on %s", info[M_CREATOR], info[M_CREATED]);
267 Put_message(buf);
268 sprintf(buf, MOD_FORMAT, info[M_MODBY], info[M_MODTIME], info[M_MODWITH]);
269 Put_message(buf);
270 return info[M_NAME];
08345b74 271}
272
7399b4b2 273/* Function Name: PrintMachine
274 * Description: Prints the name of a machine record
275 * Arguments: info - array of information about the machine.
276 * Returns: nothing.
277 */
278
279static void PrintMachine(char **info)
280{
281 char buf[BUFSIZ];
282
283 sprintf(buf, "Machine: %s", info[M_NAME]);
284 Put_message(buf);
285}
286
ad7e0e04 287/* Function Name: PrintCname
288 * Description: Prints the Data on a host alias
289 * Arguments: info a pointer to the data array.
290 * Returns: The name of the alias.
291 */
292
5eaef520 293static char *PrintCname(char **info)
ad7e0e04 294{
5eaef520 295 char buf[BUFSIZ];
ad7e0e04 296
5eaef520 297 sprintf(buf, "Alias: %-32s Canonical Name: %s", info[0], info[1]);
298 Put_message(buf);
299 return info[0];
ad7e0e04 300}
301
08345b74 302/* Function Name: PrintClusterInfo
5eaef520 303 * Description: This function Prints out the cluster info
08345b74 304 * in a coherent form.
305 * Arguments: info - array of information about a cluster.
402461ad 306 * Returns: The name of the cluster.
08345b74 307 */
308
5eaef520 309static char *PrintClusterInfo(char **info)
08345b74 310{
5eaef520 311 char buf[BUFSIZ];
312
313 Put_message("");
314 sprintf(buf, "Cluster: %s", info[C_NAME]);
315 Put_message(buf);
316 sprintf(buf, "Description: %s", info[C_DESCRIPT]);
317 Put_message(buf);
318 sprintf(buf, "Location: %s", info[C_LOCATION]);
319 Put_message(buf);
320 sprintf(buf, MOD_FORMAT, info[C_MODBY], info[C_MODTIME], info[C_MODWITH]);
321 Put_message(buf);
322 return info[C_NAME];
08345b74 323}
324
325/* Function Name: PrintClusterData
326 * Description: Prints the Data on a cluster
327 * Arguments: info a pointer to the data array.
402461ad 328 * Returns: The name of the cluster.
08345b74 329 */
330
5eaef520 331static char *PrintClusterData(char **info)
08345b74 332{
5eaef520 333 char buf[BUFSIZ];
85ca828a 334
5eaef520 335 Put_message("");
336 sprintf(buf, "Cluster: %-20s Label: %-15s Data: %s",
337 info[CD_NAME], info[CD_LABEL], info[CD_DATA]);
338 Put_message(buf);
339 return info[CD_NAME];
08345b74 340}
341
461c03b6 342/* Function Name: PrintMCMap
343 * Description: Prints the data about a machine to cluster mapping.
344 * Arguments: info a pointer to the data array.
345 * Returns: none
346 */
347
5eaef520 348static char *PrintMCMap(char **info)
461c03b6 349{
5eaef520 350 char buf[BUFSIZ];
351 sprintf(buf, "Cluster: %-30s Machine: %-20s",
352 info[MAP_CLUSTER], info[MAP_MACHINE]);
353 Put_message(buf);
354 return ""; /* Used by QueryLoop(). */
461c03b6 355}
356
ad7e0e04 357/* Function Name: PrintSubnetInfo
5eaef520 358 * Description: This function Prints out the subnet info
ad7e0e04 359 * in a coherent form.
360 * Arguments: info - array of information about a subnet.
361 * Returns: The name of the subnet.
362 */
363
5eaef520 364static char *PrintSubnetInfo(char **info)
ad7e0e04 365{
5eaef520 366 char buf[BUFSIZ];
367 struct in_addr addr, mask, low, high;
368
369 Put_message("");
370 sprintf(buf, " Network: %s", info[SN_NAME]);
371 Put_message(buf);
372 sprintf(buf, " Description: %s", info[SN_DESC]);
373 Put_message(buf);
374 addr.s_addr = htonl(atoi(info[SN_ADDRESS]));
375 mask.s_addr = htonl(atoi(info[SN_MASK]));
376 low.s_addr = htonl(atoi(info[SN_LOW]));
377 high.s_addr = htonl(atoi(info[SN_HIGH]));
378 /* screwy sequence is here because inet_ntoa returns a pointer to
379 a static buf. If it were all one sprintf, the last value would
380 appear 4 times. */
381 sprintf(buf, " Address: %s Mask: ", inet_ntoa(addr));
382 strcat(buf, inet_ntoa(mask));
383 strcat(buf, "\n High: ");
384 strcat(buf, inet_ntoa(high));
385 strcat(buf, " Low: ");
386 strcat(buf, inet_ntoa(low));
387 Put_message(buf);
388 sprintf(buf, "Hostname prefix: %s", info[SN_PREFIX]);
389 Put_message(buf);
390 sprintf(buf, " Owner: %s %s\n", info[SN_ACE_TYPE],
391 strcmp(info[SN_ACE_TYPE], "NONE") ? info[SN_ACE_NAME] : "");
392 Put_message(buf);
393 sprintf(buf, MOD_FORMAT, info[SN_MODBY], info[SN_MODTIME], info[SN_MODWITH]);
394 Put_message(buf);
395 return info[SN_NAME];
ad7e0e04 396}
397
08345b74 398/* Function Name: GetMCInfo.
399 * Description: This function stores info about a machine.
400 * type - type of data we are trying to retrieve.
401 * name1 - the name of argv[0] for the call.
402 * name2 - the name of argv[1] for the call.
403 * Returns: the top element of a queue containing the data or NULL.
404 */
405
600b459e 406struct mqelem *GetMCInfo(int type, char *name1, char *name2)
08345b74 407{
5eaef520 408 int stat;
600b459e 409 struct mqelem *elem = NULL;
5eaef520 410 char *args[5];
08345b74 411
5eaef520 412 switch (type)
413 {
461c03b6 414 case MACHINE:
5eaef520 415 args[0] = name1;
416 args[1] = args[2] = args[3] = "*";
7ac48069 417 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
5eaef520 418 {
419 if (stat == MR_NO_MATCH)
420 {
421 char buf[128];
422 sprintf(buf, "Machine '%s' is not in the database.", name1);
423 Put_message(buf);
424 }
425 else
426 com_err(program_name, stat, " in get_machine.");
427 return NULL;
08345b74 428 }
5eaef520 429 break;
ad7e0e04 430 case CNAME:
5eaef520 431 args[0] = name1;
432 args[1] = name2;
7ac48069 433 if ((stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem)))
5eaef520 434 {
435 com_err(program_name, stat, " in get_hostalias.");
436 return NULL;
ad7e0e04 437 }
5eaef520 438 break;
ad7e0e04 439 case SUBNET:
7ac48069 440 if ((stat = do_mr_query("get_subnet", 1, &name1, StoreInfo, &elem)))
5eaef520 441 {
442 if (stat == MR_NO_MATCH)
443 {
444 char buf[128];
445 sprintf(buf, "Network '%s' is not in the database.", name1);
446 Put_message(buf);
447 }
448 else
449 com_err(program_name, stat, " in get_subnet.");
450 return NULL;
ad7e0e04 451 }
5eaef520 452 break;
461c03b6 453 case CLUSTER:
7ac48069 454 if ((stat = do_mr_query("get_cluster", 1, &name1, StoreInfo, &elem)))
5eaef520 455 {
456 com_err(program_name, stat, " in get_cluster.");
457 return NULL;
08345b74 458 }
5eaef520 459 break;
461c03b6 460 case MAP:
5eaef520 461 args[MAP_MACHINE] = name1;
462 args[MAP_CLUSTER] = name2;
463 if ((stat = do_mr_query("get_machine_to_cluster_map", 2, args,
7ac48069 464 StoreInfo, &elem)))
5eaef520 465 {
466 com_err(program_name, stat, " in get_machine_to_cluster_map.");
467 return NULL;
08345b74 468 }
5eaef520 469 break;
461c03b6 470 case DATA:
5eaef520 471 args[CD_NAME] = name1;
472 args[CD_LABEL] = name2;
7ac48069 473 if ((stat = do_mr_query("get_cluster_data", 2, args, StoreInfo, &elem)))
5eaef520 474 {
475 com_err(program_name, stat, " in get_cluster_data.");
476 return NULL;
08345b74 477 }
9cd2d193 478 break;
479 case CONTAINER:
480 args[CON_NAME] = name1;
481 if ((stat = do_mr_query("get_container", 1, &name1, StoreInfo, &elem)))
482 {
483 com_err(program_name, stat, " in get_container.");
484 return NULL;
485 }
486 break;
487 case CONTMAP:
488 args[0] = name1;
489 if ((stat = do_mr_query("get_machine_to_container_map", 1, &name1,
490 StoreInfo, &elem)))
491 {
492 com_err(program_name, stat, " in get_machine_to_container_map.");
493 return NULL;
494 }
08345b74 495 }
5eaef520 496 return QueueTop(elem);
08345b74 497}
498
461c03b6 499/* Function Name: AskMCDInfo.
5eaef520 500 * Description: This function askes the user for information about a
08345b74 501 * machine and saves it into a structure.
502 * Arguments: info - a pointer the information to ask about
461c03b6 503 * type - type of information - MACHINE
504 * CLUSTER
505 * DATA
9cd2d193 506 * CONTAINER
08345b74 507 * name - T/F : change the name of this type.
508 * Returns: none.
509 */
510
5eaef520 511char **AskMCDInfo(char **info, int type, Bool name)
08345b74 512{
5eaef520 513 char temp_buf[BUFSIZ], *newname, *oldnewname;
08345b74 514
5eaef520 515 switch (type)
516 {
461c03b6 517 case MACHINE:
5eaef520 518 sprintf(temp_buf, "\nSetting the information for the Machine %s...",
519 info[M_NAME]);
520 break;
ad7e0e04 521 case SUBNET:
5eaef520 522 sprintf(temp_buf, "Setting the information for the Network %s...",
523 info[SN_NAME]);
524 break;
461c03b6 525 case CLUSTER:
5eaef520 526 sprintf(temp_buf, "Setting the information for the Cluster %s...",
527 info[C_NAME]);
528 break;
461c03b6 529 case DATA:
5eaef520 530 sprintf(temp_buf, "Setting the Data for the Cluster %s...",
531 info[CD_NAME]);
532 break;
9cd2d193 533 case CONTAINER:
534 sprintf(temp_buf, "Setting the Data for the Container %s...",
535 info[CON_NAME]);
536 break;
08345b74 537 }
5eaef520 538 Put_message(temp_buf);
08345b74 539
5eaef520 540 if (name)
541 {
542 switch (type)
543 {
461c03b6 544 case MACHINE:
7ac48069 545 newname = strdup(info[M_NAME]);
5eaef520 546 if (GetValueFromUser("The new name for this machine? ", &newname) ==
547 SUB_ERROR)
548 return NULL;
7ac48069 549 oldnewname = strdup(newname);
5eaef520 550 newname = canonicalize_hostname(newname);
551 if (strcasecmp(newname, oldnewname) && *oldnewname != '"')
552 {
553 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'\n",
554 oldnewname, newname);
555 Put_message(temp_buf);
576ba5e7 556 }
5eaef520 557 free(oldnewname);
558 break;
ad7e0e04 559 case SUBNET:
7ac48069 560 newname = strdup(info[SN_NAME]);
5eaef520 561 if (GetValueFromUser("The new name for this network? ", &newname) ==
562 SUB_ERROR)
563 return NULL;
564 break;
461c03b6 565 case CLUSTER:
7ac48069 566 newname = strdup(info[C_NAME]);
5eaef520 567 if (GetValueFromUser("The new name for this cluster? ", &newname) ==
568 SUB_ERROR)
569 return NULL;
570 break;
9cd2d193 571 case CONTAINER:
572 newname = strdup(info[CON_NAME]);
573 if (GetValueFromUser("The new name for this container? ", &newname)
574 == SUB_ERROR)
575 return NULL;
576 break;
08345b74 577 default:
5eaef520 578 Put_message("Unknown type in AskMCDInfo, programmer botch");
579 return NULL;
08345b74 580 }
581 }
582
5eaef520 583 switch (type)
584 {
461c03b6 585 case MACHINE:
5eaef520 586 if (GetValueFromUser("Machine's vendor", &info[M_VENDOR]) == SUB_ERROR)
587 return NULL;
588 if (GetValueFromUser("Machine's model", &info[M_MODEL]) == SUB_ERROR)
589 return NULL;
590 if (GetValueFromUser("Machine's operating system", &info[M_OS]) ==
591 SUB_ERROR)
592 return NULL;
593 if (GetValueFromUser("Machine's location", &info[M_LOC]) == SUB_ERROR)
594 return NULL;
595 if (GetValueFromUser("Machine's contact", &info[M_CONTACT]) ==
596 SUB_ERROR)
597 return NULL;
2f2d9dfc 598 if (GetValueFromUser("Machine's billing contact",
599 &info[M_BILL_CONTACT]) == SUB_ERROR)
600 return NULL;
5eaef520 601 while (1)
602 {
603 int i;
604 if (GetValueFromUser("Machine's status (? for help)",
ad7e0e04 605 &info[M_STAT]) == SUB_ERROR)
5eaef520 606 return NULL;
607 if (isdigit(info[M_STAT][0]))
608 break;
609 Put_message("Valid status numbers:");
610 for (i = 0; i < 4; i++)
611 Put_message(states[i]);
612 }
613
614 /* there appears to be some argument mismatch between the client
615 * and the server.. so here is this argument shuffler.
616 * I have since modified this to always shuffle the arguments..
617 * not just do so when performing a modify all fields request.
618 * The SetMachinedefaults() has been changed to reflect this.
619 * pray for us and may we attain enlightenment through structures.
620 */
621
622 if (name)
623 {
624 /* info did not come from SetMachineDefaults(), which does not
625 * initialize entry 8 (M_STAT_CHNG), therefore we can
626 * free it.
627 */
628 /* This is an update of an existing machine and the structure
629 * was filled in thru a query to the db which does fill in this
630 * field.
631 */
2f2d9dfc 632 free(info[9]);
ad7e0e04 633 }
5eaef520 634
2f2d9dfc 635 info[9] = info[M_SUBNET];
636 info[10] = info[M_ADDR];
637 info[11] = info[M_OWNER_TYPE];
638 info[12] = info[M_OWNER_NAME];
639 info[13] = info[M_ACOMMENT];
640 info[14] = info[M_OCOMMENT];
5eaef520 641
642 if (name)
643 {
2f2d9dfc 644 if (GetValueFromUser("Machine's network (or 'none')", &info[9])
5eaef520 645 == SUB_ERROR)
646 return NULL;
4bae4be1 647 }
5eaef520 648 if (GetValueFromUser("Machine's address (or 'unassigned' or 'unique')",
2f2d9dfc 649 &info[10]) == SUB_ERROR)
5eaef520 650 return NULL;
2f2d9dfc 651 if (GetTypeFromUser("Machine's owner type", "ace_type", &info[11]) ==
5eaef520 652 SUB_ERROR)
653 return NULL;
2f2d9dfc 654 if (strcmp(info[11], "NONE") &&
655 GetValueFromUser("Owner's Name", &info[12]) == SUB_ERROR)
5eaef520 656 return NULL;
5cef9ecf 657 if (!strcmp(info[11], "KERBEROS"))
658 {
659 char *canon;
660
661 mrcl_validate_kerberos_member(info[12], &canon);
662 if (mrcl_get_message())
663 Put_message(mrcl_get_message());
664 free(info[12]);
665 info[12] = canon;
666 }
2f2d9dfc 667 if (GetValueFromUser("Administrative comment", &info[13]) == SUB_ERROR)
5eaef520 668 return NULL;
2f2d9dfc 669 if (GetValueFromUser("Operational comment", &info[14]) == SUB_ERROR)
5eaef520 670 return NULL;
2f2d9dfc 671 info[15] = NULL;
5eaef520 672 FreeAndClear(&info[16], TRUE);
2f2d9dfc 673 FreeAndClear(&info[17], TRUE);
5eaef520 674 break;
ad7e0e04 675 case SUBNET:
5eaef520 676 if (GetValueFromUser("Network description", &info[SN_DESC]) == SUB_ERROR)
677 return NULL;
678 if (GetAddressFromUser("Network address", &info[SN_ADDRESS]) == SUB_ERROR)
679 return NULL;
680 if (GetAddressFromUser("Network mask", &info[SN_MASK]) == SUB_ERROR)
681 return NULL;
533bacb3 682 if (atoi(info[SN_LOW]) == (int)ntohl(inet_addr(S_DEFAULT_LOW)))
5eaef520 683 {
684 struct in_addr low;
685 unsigned long mask, addr;
686
687 addr = atoi(info[SN_ADDRESS]);
688 mask = atoi(info[SN_MASK]);
689 low.s_addr = atoi(info[SN_LOW]);
690 low.s_addr = (low.s_addr & ~mask) | (addr & mask);
691 free(info[SN_LOW]);
7ac48069 692 sprintf(temp_buf, "%ld", low.s_addr);
693 info[SN_LOW] = strdup(temp_buf);
5cfca28f 694 }
5eaef520 695 if (GetAddressFromUser("Lowest assignable address", &info[SN_LOW]) ==
696 SUB_ERROR)
697 return NULL;
533bacb3 698 if (atoi(info[SN_HIGH]) == (int)ntohl(inet_addr(S_DEFAULT_HIGH)))
5eaef520 699 {
700 struct in_addr high;
701 unsigned long mask, addr;
702
703 addr = atoi(info[SN_ADDRESS]);
704 mask = atoi(info[SN_MASK]);
705 high.s_addr = atoi(info[SN_HIGH]);
706 high.s_addr = (high.s_addr & ~mask) | (addr & mask);
707 free(info[SN_HIGH]);
7ac48069 708 sprintf(temp_buf, "%ld", high.s_addr);
709 info[SN_HIGH] = strdup(temp_buf);
5cfca28f 710 }
5eaef520 711 if (GetAddressFromUser("Highest assignable address", &info[SN_HIGH]) ==
712 SUB_ERROR)
713 return NULL;
714 if (GetValueFromUser("Hostname prefix", &info[SN_PREFIX]) == SUB_ERROR)
715 return NULL;
716 if (GetTypeFromUser("Owner type", "ace_type", &info[SN_ACE_TYPE]) ==
717 SUB_ERROR)
718 return NULL;
719 if (strcmp(info[SN_ACE_TYPE], "NONE") &&
720 GetValueFromUser("Owner name", &info[SN_ACE_NAME]) == SUB_ERROR)
721 return NULL;
5cef9ecf 722 if (!strcmp(info[SN_ACE_TYPE], "KERBEROS"))
723 {
724 char *canon;
725
726 mrcl_validate_kerberos_member(info[SN_ACE_NAME], &canon);
727 if (mrcl_get_message())
728 Put_message(mrcl_get_message());
729 free(info[SN_ACE_NAME]);
730 info[SN_ACE_NAME] = canon;
731 }
5eaef520 732 FreeAndClear(&info[SN_MODTIME], TRUE);
733 FreeAndClear(&info[SN_MODBY], TRUE);
734 FreeAndClear(&info[SN_MODWITH], TRUE);
735 break;
461c03b6 736 case CLUSTER:
5eaef520 737 if (GetValueFromUser("Cluster's Description:", &info[C_DESCRIPT]) ==
738 SUB_ERROR)
739 return NULL;
740 if (GetValueFromUser("Cluster's Location:", &info[C_LOCATION]) ==
741 SUB_ERROR)
742 return NULL;
743 FreeAndClear(&info[C_MODTIME], TRUE);
744 FreeAndClear(&info[C_MODBY], TRUE);
745 FreeAndClear(&info[C_MODWITH], TRUE);
746 break;
461c03b6 747 case DATA:
5eaef520 748 if (GetValueFromUser("Label defining this data?", &info[CD_LABEL]) ==
749 SUB_ERROR)
750 return NULL;
751 if (GetValueFromUser("The data itself ? ", &info[CD_DATA]) == SUB_ERROR)
752 return NULL;
753 break;
9cd2d193 754 case CONTAINER:
755 if (GetValueFromUser("Container's Description:", &info[CON_DESCRIPT]) ==
756 SUB_ERROR)
757 return NULL;
758 if (GetValueFromUser("Container's Location:", &info[CON_LOCATION]) ==
759 SUB_ERROR)
760 return NULL;
761 if (GetValueFromUser("Container's Contact:", &info[CON_CONTACT]) ==
762 SUB_ERROR)
763 return NULL;
764 if (GetTypeFromUser("Container's owner type", "ace_type",
765 &info[CON_OWNER_TYPE]) == SUB_ERROR)
766 return NULL;
767 if (strcmp(info[CON_OWNER_TYPE], "NONE") &&
768 GetValueFromUser("Owner's Name", &info[CON_OWNER_NAME]) == SUB_ERROR)
769 return NULL;
770 if (!strcmp(info[CON_OWNER_TYPE], "KERBEROS"))
771 {
772 char *canon;
773
774 mrcl_validate_kerberos_member(info[CON_OWNER_NAME], &canon);
775 if (mrcl_get_message())
776 Put_message(mrcl_get_message());
777 free(info[CON_OWNER_NAME]);
778 info[CON_OWNER_NAME] = canon;
779 }
780 if (GetTypeFromUser("Container's Membership ACL", "ace_type",
781 &info[CON_MEMACE_TYPE]) == SUB_ERROR)
782 return NULL;
783 if (strcmp(info[CON_MEMACE_TYPE], "NONE") &&
784 GetValueFromUser("Membership ACL", &info[CON_MEMACE_NAME])
785 == SUB_ERROR)
786 return NULL;
787 if (!strcmp(info[CON_MEMACE_TYPE], "KERBEROS"))
788 {
789 char *canon;
790
791 mrcl_validate_kerberos_member(info[CON_MEMACE_NAME], &canon);
792 if (mrcl_get_message())
793 Put_message(mrcl_get_message());
794 free(info[CON_MEMACE_NAME]);
795 info[CON_MEMACE_NAME] = canon;
796 }
797 FreeAndClear(&info[CON_MODTIME], TRUE);
798 FreeAndClear(&info[CON_MODBY], TRUE);
799 FreeAndClear(&info[CON_MODWITH], TRUE);
800 break;
08345b74 801 }
802
5eaef520 803 /*
804 * Slide the newname into the #2 slot, this screws up all future references
805 * to this list.
806 */
807 if (name)
808 SlipInNewName(info, newname);
08345b74 809
5eaef520 810 return info;
08345b74 811}
812
813/* ----------- Machine Menu ----------- */
814
815/* Function Name: ShowMachineInfo
816 * Description: This function shows the information about a machine.
817 * Arguments: argc, argv - the name of the machine in argv[1].
818 * Returns: DM_NORMAL.
819 */
820
5eaef520 821int ShowMachineInfo(int argc, char **argv)
08345b74 822{
600b459e 823 struct mqelem *top;
5eaef520 824 char *tmpname;
825
7ac48069 826 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 827 top = GetMCInfo(MACHINE, tmpname, NULL);
a6da9354 828 Loop(top, ((void (*)(char **)) PrintMachInfo));
5eaef520 829 FreeQueue(top);
830 return DM_NORMAL;
08345b74 831}
832
ad7e0e04 833/* Function Name: ShowMachineQuery
834 * Description: This function shows the information about a machine.
835 * or group of machines, which may be selected through a
5eaef520 836 * number of criteria.
ad7e0e04 837 * Arguments: argc, argv - the name of the machine in argv[1],
838 * the address of the machine in argv[2],
839 * the location of the machine in argv[3],
840 * and the contact name in argv[4].
841 * any of these may be wildcards.
842 * Returns: DM_NORMAL.
843 */
844
5eaef520 845int ShowMachineQuery(int argc, char **argv)
ad7e0e04 846{
5eaef520 847 int stat;
600b459e 848 struct mqelem *top, *elem = NULL;
5eaef520 849 char *args[5];
850
851 if (!strcmp(argv[1], "") && !strcmp(argv[2], "") &&
852 !strcmp(argv[3], "") && !strcmp(argv[4], ""))
853 {
854 Put_message("You must specify at least one parameter of the query.");
855 return DM_NORMAL;
ad7e0e04 856 }
857
5eaef520 858 if (*argv[1])
7ac48069 859 args[0] = canonicalize_hostname(strdup(argv[1]));
5eaef520 860 else
861 args[0] = "*";
862 if (*argv[2])
863 args[1] = argv[2];
864 else
865 args[1] = "*";
866 if (*argv[3])
867 args[2] = argv[3];
868 else
869 args[2] = "*";
870 if (*argv[4])
871 args[3] = argv[4];
872 else
873 args[3] = "*";
874
7ac48069 875 if ((stat = do_mr_query("get_host", 4, args, StoreInfo, &elem)))
5eaef520 876 {
877 if (stat == MR_NO_MATCH)
878 Put_message("No machine(s) found matching query in the database.");
879 else
880 com_err(program_name, stat, " in get_machine.");
881 return DM_NORMAL;
ad7e0e04 882 }
5eaef520 883 top = QueueTop(elem);
a6da9354 884 Loop(top, ((void (*)(char **)) PrintMachInfo));
5eaef520 885 FreeQueue(top);
886 return DM_NORMAL;
ad7e0e04 887}
888
08345b74 889/* Function Name: AddMachine
890 * Description: This function adds a new machine to the database.
54864ee6 891 * Arguments: argc, argv - the name of the network in argv[1].
08345b74 892 * Returns: DM_NORMAL.
893 */
894
5eaef520 895int AddMachine(int argc, char **argv)
08345b74 896{
5eaef520 897 char **args, *info[MAX_ARGS_SIZE], *name, buf[256], *xargs[5];
898 char **rinfo;
600b459e 899 struct mqelem *elem = NULL;
5eaef520 900 int stat;
901
902 if (!ValidName(argv[1])) /* Checks for wildcards. */
903 return DM_NORMAL;
904
905 /*
906 * get the network record
907 */
908
909 if (strcasecmp(argv[1], "none") &&
7ac48069 910 (stat = do_mr_query("get_subnet", 1, &argv[1], StoreInfo, &elem)))
5eaef520 911 {
912 if (stat == MR_NO_MATCH)
913 {
914 char buf[128];
915 sprintf(buf, "Network '%s' is not in the database.", argv[1]);
916 Put_message(buf);
54864ee6 917 } else
5eaef520 918 com_err(program_name, stat, " in get_subnet.");
919 return DM_NORMAL;
920 }
54864ee6 921
5eaef520 922 /*
923 * Check to see if this machine already exists.
924 */
54864ee6 925
7ac48069 926 name = strdup(""); /* want to put prefix here */
5eaef520 927 if (GetValueFromUser("Machine name", &name) == SUB_ERROR)
928 return 0;
08345b74 929
7ac48069 930 name = canonicalize_hostname(strdup(name));
5eaef520 931
932 xargs[0] = name;
933 xargs[1] = xargs[2] = xargs[3] = "*";
7ac48069 934 if (!(stat = do_mr_query("get_host", 4, xargs, NULL, NULL)))
5eaef520 935 {
936 sprintf(buf, "The machine '%s' already exists.", name);
937 Put_message(buf);
938 free(name);
939 return DM_NORMAL;
08345b74 940 }
5eaef520 941 else if (stat != MR_NO_MATCH)
942 {
943 com_err(program_name, stat,
944 " while checking machine '%s' in AddMachine.", name);
945 free(name);
946 return DM_NORMAL;
08345b74 947 }
5eaef520 948 rinfo = SetMachineDefaults(info, name);
7ac48069 949 rinfo[M_SUBNET] = strdup(argv[1]);
5eaef520 950 if (!(args = AskMCDInfo(rinfo, MACHINE, FALSE)))
951 {
952 Put_message("Aborted.");
953 return DM_NORMAL;
576ba5e7 954 }
08345b74 955
5eaef520 956 /*
957 * Actually create the new Machine.
958 */
959
7ac48069 960 if ((stat = do_mr_query("add_host", CountArgs(args), args, NULL, NULL)))
5eaef520 961 com_err(program_name, stat, " in AddMachine.");
962
963 FreeInfo(info);
964 free(name);
965 return DM_NORMAL;
08345b74 966}
967
402461ad 968/* Function Name: RealUpdateMachine
969 * Description: Performs the actual update of the machine data.
970 * Arguments: info - the information on the machine to update.
971 * junk - an UNUSED Boolean.
972 * Returns: none.
973 */
974
5eaef520 975static void RealUpdateMachine(char **info, Bool junk)
402461ad 976{
44d12d58 977 int stat;
5eaef520 978 char **args = AskMCDInfo(info, MACHINE, TRUE);
979 if (!args)
980 {
981 Put_message("Aborted.");
982 return;
576ba5e7 983 }
7ac48069 984 if ((stat = do_mr_query("update_host", CountArgs(args), args, NULL, NULL)))
5eaef520 985 com_err(program_name, stat, " in UpdateMachine.");
986 else
987 Put_message("Machine successfully updated.");
402461ad 988}
989
08345b74 990/* Function Name: UpdateMachine
991 * Description: This function adds a new machine to the database.
992 * Arguments: argc, argv - the name of the machine in argv[1].
993 * Returns: DM_NORMAL.
994 */
995
5eaef520 996int UpdateMachine(int argc, char **argv)
08345b74 997{
600b459e 998 struct mqelem *top;
5eaef520 999 char *tmpname;
1c3831ea 1000
7ac48069 1001 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 1002 top = GetMCInfo(MACHINE, tmpname, NULL);
1003 QueryLoop(top, NullPrint, RealUpdateMachine, "Update the machine");
08345b74 1004
5eaef520 1005 FreeQueue(top);
1006 free(tmpname);
1007 return DM_NORMAL;
08345b74 1008}
1009
85ca828a 1010/* Function Name: CheckAndRemoveFromCluster
1011 * Description: This func tests to see if a machine is in a cluster.
1012 * and if so then removes it
6d35002c 1013 * Arguments: name - name of the machine (already Canonicalized).
85ca828a 1014 * ask_user- query the user before removing if from clusters?
8defc06b 1015 * Returns: MR_ERROR if machine left in a cluster, or mr_error.
85ca828a 1016 */
1017
5eaef520 1018int CheckAndRemoveFromCluster(char *name, Bool ask_user)
85ca828a 1019{
44d12d58 1020 int stat, ret_value;
5eaef520 1021 Bool delete_it;
1022 char *args[10], temp_buf[BUFSIZ], *ptr;
600b459e 1023 struct mqelem *top, *elem = NULL;
5eaef520 1024
1025 ret_value = SUB_NORMAL; /* initialize ret_value. */
1026 args[0] = name;
1027 args[1] = "*";
7ac48069 1028 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
5eaef520 1029 if (stat && stat != MR_NO_MATCH)
1030 {
1031 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1032 return DM_NORMAL;
85ca828a 1033 }
5eaef520 1034 if (stat == MR_SUCCESS)
1035 {
1036 elem = top = QueueTop(elem);
1037 if (ask_user)
1038 {
1039 sprintf(temp_buf, "%s is assigned to the following clusters.", name);
1040 Put_message(temp_buf);
a6da9354 1041 Loop(top, (void (*)(char **)) PrintMCMap);
5eaef520 1042 ptr = "Remove this machine from ** ALL ** these clusters?";
1043 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1044 delete_it = TRUE;
1045 else
1046 {
1047 Put_message("Aborting...");
1048 FreeQueue(top);
1049 return SUB_ERROR;
85ca828a 1050 }
1051 }
5eaef520 1052 else
1053 delete_it = TRUE;
1054
1055 if (delete_it)
1056 {
1057 while (elem)
1058 {
7ac48069 1059 char **info = elem->q_data;
5eaef520 1060 if ((stat = do_mr_query("delete_machine_from_cluster",
7ac48069 1061 2, info, NULL, NULL)))
5eaef520 1062 {
1063 ret_value = SUB_ERROR;
1064 com_err(program_name, stat,
1065 " in delete_machine_from_cluster.");
1066 sprintf(temp_buf,
1067 "Machine %s ** NOT ** removed from cluster %s.",
1068 info[MAP_MACHINE], info[MAP_CLUSTER]);
1069 Put_message(temp_buf);
85ca828a 1070 }
5eaef520 1071 elem = elem->q_forw;
85ca828a 1072 }
1073 }
1074 }
5eaef520 1075 return ret_value;
85ca828a 1076}
1077
6d35002c 1078/* Function Name: CheckAndRemoveCnames
1079 * Description: This func tests to see if a machine has cnames,
1080 * and if so then removes them.
1081 * Arguments: name - name of the machine (already Canonicalized).
1082 * ask_user- query the user before removing cnames?
7811165a 1083 * Returns: MR_ERROR if machine left with a cname, or mr_error.
6d35002c 1084 */
1085
1086int CheckAndRemoveCnames(char *name, Bool ask_user)
1087{
1088 int stat, ret_value;
1089 Bool delete_it;
1090 char *args[10], temp_buf[BUFSIZ], *ptr;
1091 struct mqelem *top, *elem = NULL;
1092
1093 ret_value = SUB_NORMAL;
1094 args[0] = "*";
1095 args[1] = name;
1096 stat = do_mr_query("get_hostalias", 2, args, StoreInfo, &elem);
1097 if (stat && stat != MR_NO_MATCH)
1098 {
1099 com_err(program_name, stat, " in get_hostalias.");
1100 return DM_NORMAL;
1101 }
1102 if (stat == MR_SUCCESS)
1103 {
1104 elem = top = QueueTop(elem);
1105 if (ask_user)
1106 {
1107 sprintf(temp_buf, "%s has the following cnames.", name);
1108 Put_message(temp_buf);
1109 Loop(top, (void (*)(char **)) PrintCname);
1110 ptr = "Remove ** ALL ** these cnames?";
1111 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1112 delete_it = TRUE;
1113 else
1114 {
1115 Put_message("Aborting...");
1116 FreeQueue(top);
1117 return SUB_ERROR;
1118 }
1119 }
1120 else
1121 delete_it = TRUE;
1122
1123 if (delete_it)
1124 {
1125 while (elem)
1126 {
1127 char **info = elem->q_data;
1128 if ((stat = do_mr_query("delete_hostalias", 2, info,
1129 NULL, NULL)))
1130 {
1131 ret_value = SUB_ERROR;
1132 com_err(program_name, stat, " in delete_hostalias.");
1133 sprintf(temp_buf,
1134 "Cname %s ** NOT ** removed from host %s.",
1135 info[0], info[1]);
1136 Put_message(temp_buf);
1137 }
1138 elem = elem->q_forw;
1139 }
1140 }
1141 }
1142 return ret_value;
1143}
1144
402461ad 1145/* Function Name: RealDeleteMachine
1146 * Description: Actually Deletes the Machine.
1147 * Arguments: info - nescessary information stored as an array of char *'s
1148 * one_machine - a boolean, true if there is only one item in
1149 * the query.
1150 * Returns: none.
1151 */
1152
5eaef520 1153static void RealDeleteMachine(char **info, Bool one_machine)
402461ad 1154{
44d12d58 1155 int stat;
5eaef520 1156 char temp_buf[BUFSIZ];
1157
1158 sprintf(temp_buf, "Are you sure you want to delete the machine %s (y/n)? ",
1159 info[M_NAME]);
1160 if (!one_machine || Confirm(temp_buf))
1161 {
1162 if (CheckAndRemoveFromCluster(info[M_NAME], TRUE) != SUB_ERROR)
1163 {
6d35002c 1164 if (CheckAndRemoveCnames(info[M_NAME], TRUE) != SUB_ERROR)
5eaef520 1165 {
6d35002c 1166 if ((stat = do_mr_query("delete_host", 1,
1167 &info[M_NAME], NULL, NULL)))
1168 {
1169 com_err(program_name, stat, " in DeleteMachine.");
1170 sprintf(temp_buf, "%s ** NOT ** deleted.",
1171 info[M_NAME]);
1172 Put_message(temp_buf);
1173 }
1174 else
1175 {
1176 sprintf(temp_buf, "%s successfully Deleted.", info[M_NAME]);
1177 Put_message(temp_buf);
1178 }
402461ad 1179 }
1180 }
1181 }
1182}
7811165a 1183
08345b74 1184/* Function Name: DeleteMachine
1185 * Description: This function removes a machine from the data base.
1186 * Arguments: argc, argv - the machines name int argv[1].
1187 * Returns: DM_NORMAL.
1188 */
1189
85ca828a 1190/* Perhaps we should remove the cluster if it has no machine now. */
1191
5eaef520 1192int DeleteMachine(int argc, char **argv)
08345b74 1193{
600b459e 1194 struct mqelem *top;
5eaef520 1195 char *tmpname;
1196
7ac48069 1197 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 1198 top = GetMCInfo(MACHINE, tmpname, (char *) NULL);
1199 QueryLoop(top, PrintMachInfo, RealDeleteMachine, "Delete the machine");
1200 FreeQueue(top);
1201 free(tmpname);
1202 return DM_NORMAL;
08345b74 1203}
1204
5cfca28f 1205
ad7e0e04 1206/* Function Name: ShowCname
1207 * Description: This function shows machine aliases
1208 * Arguments: argc, argv - the alias argv[1], the real name in argv[2]
1209 * Returns: DM_NORMAL.
1210 */
1211
5eaef520 1212int ShowCname(int argc, char **argv)
ad7e0e04 1213{
600b459e 1214 struct mqelem *top;
5eaef520 1215 char *tmpalias, *tmpname;
1216
7ac48069 1217 tmpalias = partial_canonicalize_hostname(strdup(argv[1]));
1218 tmpname = canonicalize_hostname(strdup(argv[2]));
5eaef520 1219 top = GetMCInfo(CNAME, tmpalias, tmpname);
1220 Put_message(""); /* blank line on screen */
a6da9354 1221 Loop(top, ((void (*)(char **)) PrintCname));
5eaef520 1222 FreeQueue(top);
1223 return DM_NORMAL;
ad7e0e04 1224}
1225
1226
5eaef520 1227int AddCname(int argc, char **argv)
ad7e0e04 1228{
5eaef520 1229 int stat;
1230 char *args[10];
1231
7ac48069 1232 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1233 args[1] = canonicalize_hostname(strdup(argv[2]));
1234 stat = do_mr_query("add_hostalias", 2, args, NULL, NULL);
5eaef520 1235 switch (stat)
1236 {
ad7e0e04 1237 case MR_SUCCESS:
5eaef520 1238 break;
ad7e0e04 1239 case MR_EXISTS:
5eaef520 1240 Put_message("That alias name is already in use.");
1241 break;
ad7e0e04 1242 case MR_PERM:
5eaef520 1243 Put_message("Permission denied. "
1244 "(Regular users can only add two aliases to a host.");
1245 break;
ad7e0e04 1246 default:
5eaef520 1247 com_err(program_name, stat, " in add_hostalias");
ad7e0e04 1248 }
5eaef520 1249 return DM_NORMAL;
ad7e0e04 1250}
1251
1252
5eaef520 1253int DeleteCname(int argc, char **argv)
ad7e0e04 1254{
5eaef520 1255 int stat;
7ac48069 1256 char *args[10];
5eaef520 1257
7ac48069 1258 args[0] = partial_canonicalize_hostname(strdup(argv[1]));
1259 args[1] = canonicalize_hostname(strdup(argv[2]));
1260 stat = do_mr_query("delete_hostalias", 2, args, NULL, NULL);
5eaef520 1261 if (stat)
1262 com_err(program_name, stat, " in delete_hostalias");
1263 return DM_NORMAL;
ad7e0e04 1264}
1265
1266
08345b74 1267/* Function Name: AddMachineToCluster
1268 * Description: This function adds a machine to a cluster
1269 * Arguments: argc, argv - The machine name is argv[1].
1270 * The cluster name in argv[2].
1271 * Returns: DM_NORMAL.
1272 */
1273
5eaef520 1274int AddMachineToCluster(int argc, char **argv)
08345b74 1275{
5eaef520 1276 int stat;
1277 char *machine, *cluster, temp_buf[BUFSIZ], *args[10];
1278 Bool add_it, one_machine, one_cluster;
600b459e 1279 struct mqelem *melem, *mtop, *celem, *ctop;
5eaef520 1280
7ac48069 1281 machine = canonicalize_hostname(strdup(argv[1]));
5eaef520 1282 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
1283 {
1284 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1285 argv[1], machine);
1286 Put_message(temp_buf);
576ba5e7 1287 }
5eaef520 1288 cluster = argv[2];
1289
1290 celem = ctop = GetMCInfo(CLUSTER, cluster, NULL);
1291 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
1292 free(machine);
1293
1294 one_machine = (QueueCount(mtop) == 1);
1295 one_cluster = (QueueCount(ctop) == 1);
1296
1297 /* No good way to use QueryLoop() here, sigh */
1298
1299 while (melem)
1300 {
7ac48069 1301 char **minfo = melem->q_data;
5eaef520 1302 while (celem)
1303 {
7ac48069 1304 char **cinfo = celem->q_data;
5eaef520 1305 if (one_machine && one_cluster)
1306 add_it = TRUE;
1307 else
1308 {
1309 sprintf(temp_buf, "Add machine %s to cluster %s (y/n/q) ?",
1310 minfo[M_NAME], cinfo[C_NAME]);
1311 switch (YesNoQuitQuestion(temp_buf, FALSE))
1312 {
85ca828a 1313 case TRUE:
5eaef520 1314 add_it = TRUE;
1315 break;
85ca828a 1316 case FALSE:
5eaef520 1317 add_it = FALSE;
1318 break;
85ca828a 1319 default:
5eaef520 1320 Put_message("Aborting...");
1321 FreeQueue(ctop);
1322 FreeQueue(mtop);
1323 return DM_NORMAL;
85ca828a 1324 }
1325 }
5eaef520 1326 if (add_it)
1327 {
1328 args[0] = minfo[M_NAME];
1329 args[1] = cinfo[C_NAME];
1330 stat = do_mr_query("add_machine_to_cluster", 2, args,
7ac48069 1331 NULL, NULL);
5eaef520 1332 switch (stat)
1333 {
8defc06b 1334 case MR_SUCCESS:
5eaef520 1335 break;
8defc06b 1336 case MR_EXISTS:
5eaef520 1337 sprintf(temp_buf, "%s is already in cluster %s",
1338 minfo[M_NAME], cinfo[C_NAME]);
1339 Put_message(temp_buf);
1340 break;
85ca828a 1341 default:
5eaef520 1342 com_err(program_name, stat, " in AddMachineToCluster.");
1343 break;
85ca828a 1344 }
1345 }
5eaef520 1346 celem = celem->q_forw;
85ca828a 1347 }
5eaef520 1348 celem = ctop; /* reset cluster element. */
1349 melem = melem->q_forw;
85ca828a 1350 }
5eaef520 1351 FreeQueue(ctop);
1352 FreeQueue(mtop);
1353 return DM_NORMAL;
08345b74 1354}
1355
402461ad 1356/* Function Name: RealRemoveMachineFromCluster
5eaef520 1357 * Description: This function actually removes the machine from its
402461ad 1358 * cluster.
1359 * Arguments: info - all information nescessary to perform the removal.
1360 * one_map - True if there is only one case, and we should
1361 * confirm.
1362 * Returns: none.
1363 */
1364
5eaef520 1365static void RealRemoveMachineFromCluster(char **info, Bool one_map)
402461ad 1366{
5eaef520 1367 char temp_buf[BUFSIZ];
44d12d58 1368 int stat;
5eaef520 1369
1370 sprintf(temp_buf, "Remove %s from the cluster %s",
1371 info[MAP_MACHINE], info[MAP_CLUSTER]);
1372 if (!one_map || Confirm(temp_buf))
1373 {
1374 if ((stat = do_mr_query("delete_machine_from_cluster", 2,
7ac48069 1375 info, NULL, NULL)))
5eaef520 1376 com_err(program_name, stat, " in delete_machine_from_cluster");
1377 else
1378 {
1379 sprintf(temp_buf, "%s has been removed from the cluster %s.",
1380 info[MAP_MACHINE], info[MAP_CLUSTER]);
1381 Put_message(temp_buf);
402461ad 1382 }
1383 }
5eaef520 1384 else
1385 Put_message("Machine not removed.");
402461ad 1386}
1387
08345b74 1388/* Function Name: RemoveMachineFromCluster
1389 * Description: Removes this machine form a specific cluster.
1390 * Arguments: argc, argv - Name of machine in argv[1].
85ca828a 1391 * Name of cluster in argv[2].
08345b74 1392 * Returns: none.
1393 */
1394
5eaef520 1395int RemoveMachineFromCluster(int argc, char **argv)
08345b74 1396{
600b459e 1397 struct mqelem *elem = NULL;
9cd2d193 1398 char buf[BUFSIZ], *args[10];
44d12d58 1399 int stat;
5eaef520 1400
7ac48069 1401 args[MAP_MACHINE] = canonicalize_hostname(strdup(argv[1]));
5eaef520 1402 if (strcasecmp(args[MAP_MACHINE], argv[1]) && *argv[1] != '"')
1403 {
1404 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
1405 argv[1], args[MAP_MACHINE]);
1406 Put_message(buf);
576ba5e7 1407 }
5eaef520 1408 args[MAP_CLUSTER] = argv[2];
1409 args[MAP_END] = NULL;
1410
1411 stat = do_mr_query("get_machine_to_cluster_map", CountArgs(args), args,
7ac48069 1412 StoreInfo, &elem);
5eaef520 1413 if (stat == MR_NO_MATCH)
1414 {
9cd2d193 1415 sprintf(buf, "The machine %s is not in the cluster %s.",
5eaef520 1416 args[MAP_MACHINE], args[MAP_CLUSTER]);
1417 Put_message(buf);
1418 free(args[MAP_MACHINE]);
1419 return DM_NORMAL;
08345b74 1420 }
5eaef520 1421 if (stat != MR_SUCCESS)
1422 com_err(program_name, stat, " in delete_machine_from_cluster");
85ca828a 1423
5eaef520 1424 elem = QueueTop(elem);
1425 QueryLoop(elem, PrintMCMap, RealRemoveMachineFromCluster,
1426 "Remove this machine from this cluster");
402461ad 1427
5eaef520 1428 FreeQueue(elem);
1429 free(args[MAP_MACHINE]);
1430 return DM_NORMAL;
08345b74 1431}
1432
ad7e0e04 1433/* ---------- Subnet Menu -------- */
1434
1435/* Function Name: ShowSubnetInfo
1436 * Description: Gets information about a subnet given its name.
1437 * Arguments: argc, argc - the name of the subnet in in argv[1].
1438 * Returns: DM_NORMAL.
1439 */
1440
5eaef520 1441int ShowSubnetInfo(int argc, char **argv)
ad7e0e04 1442{
600b459e 1443 struct mqelem *top;
ad7e0e04 1444
5eaef520 1445 top = GetMCInfo(SUBNET, argv[1], (char *) NULL);
a6da9354 1446 Loop(top, (void (*)(char **)) PrintSubnetInfo);
5eaef520 1447 FreeQueue(top);
1448 return DM_NORMAL;
ad7e0e04 1449}
1450
1451/* Function Name: AddSubnet
1452 * Description: Creates a new subnet.
1453 * Arguments: argc, argv - the name of the new subnet is argv[1].
1454 * Returns: DM_NORMAL.
1455 */
1456
5eaef520 1457int AddSubnet(int argc, char **argv)
ad7e0e04 1458{
5eaef520 1459 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1460 int stat;
1461
1462 /*
1463 * Check to see if this subnet already exists.
1464 */
1465 if (!ValidName(name))
1466 return DM_NORMAL;
1467
7ac48069 1468 if ((stat = do_mr_query("get_subnet", 1, &name, NULL, NULL)) == MR_SUCCESS)
5eaef520 1469 {
1470 Put_message("This subnet already exists.");
1471 return DM_NORMAL;
ad7e0e04 1472 }
5eaef520 1473 else if (stat != MR_NO_MATCH)
1474 {
1475 com_err(program_name, stat, " in AddSubnet.");
1476 return DM_NORMAL;
ad7e0e04 1477 }
5eaef520 1478 if (!(args = AskMCDInfo(SetSubnetDefaults(info, name), SUBNET, FALSE)))
1479 {
1480 Put_message("Aborted.");
1481 FreeInfo(info);
1482 return DM_NORMAL;
ad7e0e04 1483 }
1484
5eaef520 1485 /*
1486 * Actually create the new Subnet.
1487 */
7ac48069 1488 if ((stat = do_mr_query("add_subnet", CountArgs(args), args, NULL, NULL)))
5eaef520 1489 com_err(program_name, stat, " in AddSubnet.");
ad7e0e04 1490
5eaef520 1491 FreeInfo(info);
1492 return DM_NORMAL;
ad7e0e04 1493}
1494
1495/* Function Name: RealUpdateSubnet
1496 * Description: This function actually performs the subnet update.
1497 * Arguments: info - all information nesc. for updating the subnet.
1498 * junk - an UNUSED boolean.
1499 * Returns: none.
1500 */
1501
5eaef520 1502static void RealUpdateSubnet(char **info, Bool junk)
ad7e0e04 1503{
44d12d58 1504 int stat;
5eaef520 1505 char **args = AskMCDInfo(info, SUBNET, TRUE);
1506 if (!args)
1507 {
1508 Put_message("Aborted.");
1509 return;
ad7e0e04 1510 }
7ac48069 1511 if ((stat = do_mr_query("update_subnet", CountArgs(args), args, NULL, NULL)))
5eaef520 1512 com_err(program_name, stat, " in UpdateSubnet.");
1513 else
1514 Put_message("Subnet successfully updated.");
ad7e0e04 1515}
1516
1517/* Function Name: UpdateSubnet
1518 * Description: This Function Updates a subnet
1519 * Arguments: name of the subnet in argv[1].
1520 * Returns: DM_NORMAL.
1521 */
1522
5eaef520 1523int UpdateSubnet(int argc, char **argv)
ad7e0e04 1524{
600b459e 1525 struct mqelem *top;
5eaef520 1526 top = GetMCInfo(SUBNET, argv[1], NULL);
1527 QueryLoop(top, NullPrint, RealUpdateSubnet, "Update the subnet");
ad7e0e04 1528
5eaef520 1529 FreeQueue(top);
1530 return DM_NORMAL;
ad7e0e04 1531}
1532
1533/* Function Name: RealDeleteSubnet
1534 * Description: Actually performs the subnet deletion.
1535 * Arguments: info - all information about this subnet.
1536 * one_subnet - If true then there was only one subnet in
1537 * the queue, and we should confirm.
1538 * Returns: none.
1539 */
1540
5eaef520 1541static void RealDeleteSubnet(char **info, Bool one_subnet)
ad7e0e04 1542{
44d12d58 1543 int stat;
5eaef520 1544 char temp_buf[BUFSIZ];
1545
1546 sprintf(temp_buf,
1547 "Are you sure the you want to delete the subnet %s (y/n) ?",
1548 info[C_NAME]);
1549 if (!one_subnet || Confirm(temp_buf))
1550 {
7ac48069 1551 if ((stat = do_mr_query("delete_subnet", 1, &info[C_NAME], NULL, NULL)))
5eaef520 1552 {
1553 com_err(program_name, stat, " in delete_subnet.");
1554 sprintf(temp_buf, "Subnet %s ** NOT ** deleted.", info[C_NAME]);
1555 Put_message(temp_buf);
ad7e0e04 1556 }
5eaef520 1557 else
1558 {
1559 sprintf(temp_buf, "subnet %s successfully deleted.",
1560 info[C_NAME]);
1561 Put_message(temp_buf);
ad7e0e04 1562 }
1563 }
1564}
1565
1566/* Function Name: DeleteSubnet
1567 * Description: This function removes a subnet from the database.
1568 * Arguments: argc, argv - the name of the subnet is stored in argv[1].
1569 * Returns: DM_NORMAL.
1570 */
1571
5eaef520 1572int DeleteSubnet(int argc, char **argv)
ad7e0e04 1573{
600b459e 1574 struct mqelem *top;
ad7e0e04 1575
5eaef520 1576 top = GetMCInfo(SUBNET, argv[1], NULL);
1577 QueryLoop(top, PrintSubnetInfo, RealDeleteSubnet, "Delete the subnet");
ad7e0e04 1578
5eaef520 1579 FreeQueue(top);
1580 return DM_NORMAL;
ad7e0e04 1581}
5eaef520 1582
08345b74 1583/* ---------- Cluster Menu -------- */
1584
1585/* Function Name: ShowClusterInfo
1586 * Description: Gets information about a cluser given its name.
1587 * Arguments: argc, argc - the name of the cluster in in argv[1].
1588 * Returns: DM_NORMAL.
1589 */
1590
5eaef520 1591int ShowClusterInfo(int argc, char **argv)
08345b74 1592{
600b459e 1593 struct mqelem *top;
08345b74 1594
5eaef520 1595 top = GetMCInfo(CLUSTER, argv[1], NULL);
a6da9354 1596 Loop(top, (void (*)(char **)) PrintClusterInfo);
5eaef520 1597 FreeQueue(top);
1598 return DM_NORMAL;
08345b74 1599}
1600
1601/* Function Name: AddCluster
1602 * Description: Creates a new cluster.
1603 * Arguments: argc, argv - the name of the new cluster is argv[1].
1604 * Returns: DM_NORMAL.
1605 */
1606
5eaef520 1607int AddCluster(int argc, char **argv)
08345b74 1608{
5eaef520 1609 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
1610 int stat;
1611
1612 /*
1613 * Check to see if this cluster already exists.
1614 */
1615 if (!ValidName(name))
1616 return DM_NORMAL;
1617
7ac48069 1618 if ((stat = do_mr_query("get_cluster", 1, &name, NULL, NULL)) == MR_SUCCESS)
5eaef520 1619 {
1620 Put_message("This cluster already exists.");
1621 return DM_NORMAL;
08345b74 1622 }
5eaef520 1623 else if (stat != MR_NO_MATCH)
1624 {
1625 com_err(program_name, stat, " in AddCluster.");
1626 return DM_NORMAL;
08345b74 1627 }
5eaef520 1628 if (!(args = AskMCDInfo(SetClusterDefaults(info, name), CLUSTER, FALSE)))
1629 {
1630 Put_message("Aborted.");
1631 FreeInfo(info);
1632 return DM_NORMAL;
576ba5e7 1633 }
1634
5eaef520 1635 /*
1636 * Actually create the new Cluster.
1637 */
7ac48069 1638 if ((stat = do_mr_query("add_cluster", CountArgs(args), args, NULL, NULL)))
5eaef520 1639 com_err(program_name, stat, " in AddCluster.");
08345b74 1640
5eaef520 1641 FreeInfo(info);
1642 return DM_NORMAL;
08345b74 1643}
1644
402461ad 1645/* Function Name: RealUpdateCluster
1646 * Description: This function actually performs the cluster update.
1647 * Arguments: info - all information nesc. for updating the cluster.
1648 * junk - an UNUSED boolean.
1649 * Returns: none.
1650 */
1651
5eaef520 1652static void RealUpdateCluster(char **info, Bool junk)
402461ad 1653{
44d12d58 1654 int stat;
5eaef520 1655 char **args = AskMCDInfo(info, CLUSTER, TRUE);
1656
1657 if (!args)
1658 {
1659 Put_message("Aborted.");
1660 return;
576ba5e7 1661 }
5eaef520 1662 if ((stat = do_mr_query("update_cluster", CountArgs(args),
7ac48069 1663 args, NULL, NULL)))
5eaef520 1664 com_err(program_name, stat, " in UpdateCluster.");
1665 else
1666 Put_message("Cluster successfully updated.");
402461ad 1667}
1668
08345b74 1669/* Function Name: UpdateCluster
1670 * Description: This Function Updates a cluster
1671 * Arguments: name of the cluster in argv[1].
1672 * Returns: DM_NORMAL.
1673 */
1674
5eaef520 1675int UpdateCluster(int argc, char **argv)
08345b74 1676{
600b459e 1677 struct mqelem *top;
5eaef520 1678 top = GetMCInfo(CLUSTER, argv[1], NULL);
1679 QueryLoop(top, NullPrint, RealUpdateCluster, "Update the cluster");
08345b74 1680
5eaef520 1681 FreeQueue(top);
1682 return DM_NORMAL;
08345b74 1683}
1684
85ca828a 1685/* Function Name: CheckAndRemoveMachine
1686 * Description: This function checks and removes all machines from a
1687 * cluster.
1688 * Arguments: name - name of the cluster.
1689 * ask_first - if TRUE, then we will query the user, before
1690 * deletion.
1691 * Returns: SUB_ERROR if all machines not removed.
1692 */
1693
5eaef520 1694int CheckAndRemoveMachines(char *name, Bool ask_first)
85ca828a 1695{
44d12d58 1696 int stat, ret_value;
5eaef520 1697 Bool delete_it;
1698 char *args[10], temp_buf[BUFSIZ], *ptr;
600b459e 1699 struct mqelem *top, *elem = NULL;
5eaef520 1700
1701 ret_value = SUB_NORMAL;
1702 args[MAP_MACHINE] = "*";
1703 args[MAP_CLUSTER] = name;
7ac48069 1704 stat = do_mr_query("get_machine_to_cluster_map", 2, args, StoreInfo, &elem);
5eaef520 1705 if (stat && stat != MR_NO_MATCH)
1706 {
1707 com_err(program_name, stat, " in get_machine_to_cluster_map.");
1708 return DM_NORMAL;
85ca828a 1709 }
5eaef520 1710 if (stat == MR_SUCCESS)
1711 {
1712 elem = top = QueueTop(elem);
1713 if (ask_first)
1714 {
1715 sprintf(temp_buf, "The cluster %s has the following machines in it:",
1716 name);
1717 Put_message(temp_buf);
1718 while (elem)
1719 {
7ac48069 1720 char **info = elem->q_data;
5eaef520 1721 Print(1, &info[MAP_MACHINE], (char *) NULL);
1722 elem = elem->q_forw;
85ca828a 1723 }
5eaef520 1724 ptr = "Remove ** ALL ** these machines from this cluster?";
1725
1726 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
1727 delete_it = TRUE;
1728 else
1729 {
1730 Put_message("Aborting...");
1731 FreeQueue(top);
1732 return SUB_ERROR;
85ca828a 1733 }
1734 }
5eaef520 1735 else
1736 delete_it = TRUE;
1737
1738 if (delete_it)
1739 {
1740 elem = top;
1741 while (elem)
1742 {
7ac48069 1743 char **info = elem->q_data;
5eaef520 1744 if ((stat = do_mr_query("delete_machine_from_cluster",
7ac48069 1745 2, info, NULL, NULL)))
5eaef520 1746 {
1747 ret_value = SUB_ERROR;
1748 com_err(program_name, stat,
1749 " in delete_machine_from_cluster.");
1750 sprintf(temp_buf,
1751 "Machine %s ** NOT ** removed from cluster %s.",
1752 info[MAP_MACHINE], info[MAP_CLUSTER]);
1753 Put_message(temp_buf);
85ca828a 1754 }
5eaef520 1755 elem = elem->q_forw;
85ca828a 1756 }
1757 }
1758 }
5eaef520 1759 return ret_value;
85ca828a 1760}
1761
402461ad 1762/* Function Name: RealDeleteCluster
1763 * Description: Actually performs the cluster deletion.
1764 * Arguments: info - all information about this cluster.
1765 * one_cluster - If true then there was only one cluster in
1766 * the queue, and we should confirm.
1767 * Returns: none.
1768 */
1769
5eaef520 1770static void RealDeleteCluster(char **info, Bool one_cluster)
402461ad 1771{
44d12d58 1772 int stat;
5eaef520 1773 char temp_buf[BUFSIZ];
1774
1775 sprintf(temp_buf,
1776 "Are you sure the you want to delete the cluster %s (y/n) ?",
1777 info[C_NAME]);
1778 if (!one_cluster || Confirm(temp_buf))
1779 {
1780 if (CheckAndRemoveMachines(info[C_NAME], TRUE) != SUB_ERROR)
1781 {
1782 if ((stat = do_mr_query("delete_cluster", 1,
7ac48069 1783 &info[C_NAME], NULL, NULL)))
5eaef520 1784 {
1785 com_err(program_name, stat, " in delete_cluster.");
1786 sprintf(temp_buf, "Cluster %s ** NOT ** deleted.", info[C_NAME]);
1787 Put_message(temp_buf);
402461ad 1788 }
5eaef520 1789 else
1790 {
1791 sprintf(temp_buf, "cluster %s successfully deleted.",
1792 info[C_NAME]);
1793 Put_message(temp_buf);
402461ad 1794 }
1795 }
1796 }
1797}
85ca828a 1798
08345b74 1799/* Function Name: DeleteCluster
1800 * Description: This function removes a cluster from the database.
1801 * Arguments: argc, argv - the name of the cluster is stored in argv[1].
1802 * Returns: DM_NORMAL.
1803 */
1804
5eaef520 1805int DeleteCluster(int argc, char **argv)
08345b74 1806{
600b459e 1807 struct mqelem *top;
08345b74 1808
5eaef520 1809 top = GetMCInfo(CLUSTER, argv[1], NULL);
1810 QueryLoop(top, PrintClusterInfo, RealDeleteCluster, "Delete the cluster");
08345b74 1811
5eaef520 1812 FreeQueue(top);
1813 return DM_NORMAL;
08345b74 1814}
5eaef520 1815
08345b74 1816/* ----------- Cluster Data Menu -------------- */
1817
1818/* Function Name: ShowClusterData
1819 * Description: This function shows the services for one cluster.
1820 * Arguments: argc, argv - The name of the cluster is argv[1].
461c03b6 1821 * The label of the data in argv[2].
08345b74 1822 * Returns: DM_NORMAL.
1823 */
1824
5eaef520 1825int ShowClusterData(int argc, char **argv)
1826{
600b459e 1827 struct mqelem *elem, *top;
5eaef520 1828 char **info;
1829
1830 top = elem = GetMCInfo(DATA, argv[1], argv[2]);
1831 while (elem)
1832 {
7ac48069 1833 info = elem->q_data;
5eaef520 1834 PrintClusterData(info);
1835 elem = elem->q_forw;
08345b74 1836 }
5eaef520 1837 FreeQueue(top);
1838 return DM_NORMAL;
08345b74 1839}
1840
1841/* Function Name: AddClusterData
1842 * Description: This function adds some data to the cluster.
1843 * Arguments: argv, argc: argv[1] - the name of the cluster.
1844 * argv[2] - the label of the data.
1845 * argv[3] - the data.
1846 * Returns: DM_NORMAL.
1847 */
1848
5eaef520 1849int AddClusterData(int argc, char **argv)
1850{
1851 int stat;
1852
7ac48069 1853 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
5eaef520 1854 com_err(program_name, stat, " in AddClusterData.");
1855 return DM_NORMAL;
08345b74 1856}
1857
402461ad 1858/* Function Name: RealRemoveClusterData
1859 * Description: actually removes the cluster data.
1860 * Arguments: info - all info necessary to remove the cluster, in an array
1861 * of strings.
1862 * one_item - if true then the queue has only one elem and we
1863 * should confirm.
1864 * Returns: none.
1865 */
1866
5eaef520 1867static void RealRemoveClusterData(char **info, Bool one_item)
402461ad 1868{
44d12d58 1869 int stat;
5eaef520 1870 char *temp_ptr;
1871
1872 Put_message(" ");
1873 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1874 PrintClusterData(info);
1875 if (!one_item || Confirm(temp_ptr))
1876 {
7ac48069 1877 if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
5eaef520 1878 {
1879 com_err(program_name, stat, " in DeleteClusterData.");
1880 Put_message("Data not removed.");
402461ad 1881 }
5eaef520 1882 else
1883 Put_message("Removal successful.");
402461ad 1884 }
1885}
1886
461c03b6 1887/* Function Name: RemoveClusterData
1888 * Description: This function removes data on a given cluster.
08345b74 1889 * Arguments: argv, argc: argv[1] - the name of the cluster.
1890 * argv[2] - the label of the data.
1891 * argv[3] - the data.
1892 * Returns: DM_NORMAL.
1893 */
1894
5eaef520 1895int RemoveClusterData(int argc, char **argv)
08345b74 1896{
600b459e 1897 struct mqelem *top;
08345b74 1898
5eaef520 1899 top = GetMCInfo(DATA, argv[1], argv[2]);
1900 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1901 "Remove data from cluster");
08345b74 1902
5eaef520 1903 FreeQueue(top);
1904 return DM_NORMAL;
08345b74 1905}
1906
08345b74 1907/* Function Name: MachineToClusterMap
1908 * Description: This Retrieves the mapping between machine and cluster
1909 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1910 * argv[2] -> cluster name or wildcard.
1911 * Returns: none.
1912 */
1913
5eaef520 1914int MachineToClusterMap(int argc, char **argv)
08345b74 1915{
600b459e 1916 struct mqelem *elem, *top;
5eaef520 1917 char *tmpname, temp_buf[256];
1918
7ac48069 1919 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 1920 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
1921 {
1922 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1923 argv[1], tmpname);
1924 Put_message(temp_buf);
576ba5e7 1925 }
5eaef520 1926 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1927
1928 Put_message(""); /* blank line on screen */
1929 while (elem)
1930 {
7ac48069 1931 char **info = elem->q_data;
5eaef520 1932 PrintMCMap(info);
1933 elem = elem->q_forw;
461c03b6 1934 }
1935
5eaef520 1936 FreeQueue(top);
1937 free(tmpname);
1938 return DM_NORMAL;
461c03b6 1939}
7399b4b2 1940
1941/* Function Name: MachineByOwner
1942 * Description: This function prints all machines which are owned by
1943 * a given user or group.
1944 * Arguments: none.
1945 * Returns: DM_NORMAL.
1946 */
1947
1948int MachineByOwner(int argc, char **argv)
1949{
1950 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
1951 struct mqelem *top;
1952
1953 type = strdup("USER");
1954 if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR)
1955 return DM_NORMAL;
1956
1957 sprintf(buf, "Name of %s", type);
1958 name = strdup(user);
1959 if (GetValueFromUser(buf, &name) == SUB_ERROR)
1960 return DM_NORMAL;
1961
1962 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
1963 {
1964 case TRUE:
1965 sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */
1966 free(type);
1967 type = strdup(temp_buf);
1968 break;
1969 case FALSE:
1970 break;
1971 default:
1972 return DM_NORMAL;
1973 }
1974
1975 top = GetMachineByOwner(type, name);
1976 Loop(top, PrintMachine);
1977
1978 FreeQueue(top);
1979 return DM_NORMAL;
1980}
1981
1982/* Function Name: GetMachineByOwner
1983 * Description: This function stores information retrieved by
1984 * the get_host_by_owner query
1985 * Arguments: type - an ace_type, argv[0] for the query
1986 * name - name of machine, argv[1] for the query
1987 * Returns: the top element of a queue returning the data, or NULL.
1988 */
1989
1990struct mqelem *GetMachineByOwner(char *type, char *name)
1991{
1992 char *args[2];
1993 struct mqelem *elem = NULL;
1994 int status;
1995
1996 args[0] = type;
1997 args[1] = name;
1998 if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem)))
1999 {
2000 com_err(program_name, status, " in get_host_by_owner");
2001 return NULL;
2002 }
2003 return QueueTop(elem);
2004}
9cd2d193 2005
2006int ShowContainerInfo(int argc, char **argv)
2007{
2008 struct mqelem *top;
2009
2010 top = GetMCInfo(CONTAINER, argv[1], NULL);
2011 Loop(top, (void (*)(char **)) PrintContainerInfo);
2012 FreeQueue(top);
2013 return DM_NORMAL;
2014}
2015
2016static char *PrintContainerInfo(char **info)
2017{
2018 char buf[BUFSIZ], tbuf[256];
2019
2020 Put_message("");
2021 sprintf(buf, "Container: %-16s", info[CON_NAME]);
2022 Put_message(buf);
2023 sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]);
2024 Put_message(buf);
2025 sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION],
2026 info[CON_CONTACT]);
2027 Put_message(buf);
2028 sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE],
2029 strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : "");
2030 sprintf(buf, "Owner: %-16s", tbuf);
2031 Put_message(buf);
2032 sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE],
2033 strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : "");
2034 sprintf(buf, "Membership ACL: %-16s", tbuf);
2035 Put_message(buf);
2036 Put_message("");
2037 sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME],
2038 info[CON_MODWITH]);
2039 Put_message(buf);
2040 return info[CON_NAME];
2041}
2042
2043static char *PrintContainer(char **info)
2044{
2045 char buf[BUFSIZ];
2046
2047 sprintf(buf, "Container: %s", info[CON_NAME]);
2048 Put_message(buf);
2049}
2050
2051static char *PrintMContMap(char **info)
2052{
2053 char buf[BUFSIZ];
2054 sprintf(buf, "Container: %-30s Machine: %-20s",
2055 info[1], info[0]);
2056 Put_message(buf);
2057 return "";
2058}
2059
2060int AddContainer(int argc, char **argv)
2061{
2062 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
2063 int stat;
2064
2065 if (!ValidName(name))
2066 return DM_NORMAL;
2067
2068 /* Check if this cluster already exists. */
2069 if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL))
2070 == MR_SUCCESS)
2071 {
2072 Put_message("This container already exists.");
2073 return DM_NORMAL;
2074 }
2075 else if (stat != MR_NO_MATCH)
2076 {
2077 com_err(program_name, stat, " in AddContainer.");
2078 return DM_NORMAL;
2079 }
2080 if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE)))
2081 {
2082 Put_message("Aborted.");
2083 FreeInfo(info);
2084 return DM_NORMAL;
2085 }
2086
2087 /* Create the new container. */
2088 if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL)))
2089 com_err(program_name, stat, " in AddContainer.");
2090
2091 FreeInfo(info);
2092 return DM_NORMAL;
2093}
2094
2095int UpdateContainer(int argc, char **argv)
2096{
2097 struct mqelem *top;
2098 top = GetMCInfo(CONTAINER, argv[1], NULL);
2099 QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container");
2100
2101 FreeQueue(top);
2102 return DM_NORMAL;
2103}
2104
2105static void RealUpdateContainer(char **info, Bool junk)
2106{
2107 int stat;
2108 char **args = AskMCDInfo(info, CONTAINER, TRUE);
2109
2110 if (!args)
2111 {
2112 Put_message("Aborted.");
2113 return;
2114 }
2115 if ((stat = do_mr_query("update_container", CountArgs(args), args,
2116 NULL, NULL)))
2117 com_err(program_name, stat, " in UpdateContainer.");
2118 else
2119 Put_message("Container successfully updated.");
2120}
2121
2122int DeleteContainer(int argc, char **argv)
2123{
2124 struct mqelem *top;
2125
2126 top = GetMCInfo(CONTAINER, argv[1], NULL);
2127 QueryLoop(top, PrintClusterInfo, RealDeleteContainer,
2128 "Delete the container");
2129
2130 FreeQueue(top);
2131 return DM_NORMAL;
2132}
2133
2134static void RealDeleteContainer(char **info, Bool one_container)
2135{
2136 int stat;
2137 char temp_buf[BUFSIZ];
2138
2139 sprintf(temp_buf,
2140 "Are you sure you want to delete the container %s (y/n) ?",
2141 info[CON_NAME]);
2142 if (!one_container || Confirm(temp_buf))
2143 {
2144 if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE)
2145 != SUB_ERROR)
2146 {
2147 if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME],
2148 NULL, NULL)))
2149 {
2150 com_err(program_name, stat, " in delete_container.");
2151 sprintf(temp_buf, "Container %s ** NOT ** deleted.",
2152 info[CON_NAME]);
2153 Put_message(temp_buf);
2154 }
2155 else
2156 {
2157 sprintf(temp_buf, "Container %s successfully deleted.",
2158 info[CON_NAME]);
2159 Put_message(temp_buf);
2160 }
2161 }
2162 }
2163}
2164
2165int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first)
2166{
2167 int stat, ret_value;
2168 Bool delete_it;
2169 char *args[10], temp_buf[BUFSIZ], *ptr;
2170 struct mqelem *top, *elem = NULL;
2171
2172 ret_value = SUB_NORMAL;
2173 args[0] = name;
2174 args[1] = "0";
2175 stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo,
2176 &elem);
2177 if (stat && stat != MR_NO_MATCH)
2178 {
2179 com_err(program_name, stat, " in get_machines_of_container");
2180 return DM_NORMAL;
2181 }
2182 if (stat == MR_SUCCESS)
2183 {
2184 elem = top = QueueTop(elem);
2185 if (ask_first)
2186 {
2187 sprintf(temp_buf,
2188 "The container %s has the following machines in it:", name);
2189 Put_message(temp_buf);
2190 while (elem)
2191 {
2192 char **info = elem->q_data;
2193 Print(1, &info[0], (char *) NULL);
2194 elem = elem->q_forw;
2195 }
2196 ptr = "Remove ** ALL ** these machines from this container?";
2197
2198 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
2199 delete_it = TRUE;
2200 else
2201 {
2202 Put_message("Aborting...");
2203 FreeQueue(top);
2204 return SUB_ERROR;
2205 }
2206 }
2207 else
2208 delete_it = TRUE;
2209
2210 if (delete_it)
2211 {
2212 elem = top;
2213 while (elem)
2214 {
2215 char **info = elem->q_data;
2216 if ((stat = do_mr_query("delete_machine_from_container",
2217 2, info, NULL, NULL)))
2218 {
2219 ret_value = SUB_ERROR;
2220 com_err(program_name, stat,
2221 " in delete_machine_from_container.");
2222 sprintf(temp_buf,
2223 "Machine %s ** NOT ** removed from container %s.",
2224 info[0], info[1]);
2225 Put_message(temp_buf);
2226 }
2227 elem = elem->q_forw;
2228 }
2229 }
2230 }
2231 return ret_value;
2232}
2233
2234int GetSubContainers(int argc, char **argv)
2235{
2236 char *args[2];
2237 struct mqelem *elem = NULL, *top = NULL;
2238 int stat;
2239
2240 args[0] = argv[1];
2241
2242 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2243 args[1] = "1";
2244 else
2245 args[1] = "0";
2246
2247 if (stat = do_mr_query("get_subcontainers_of_container", 2, args,
2248 StoreInfo, &elem))
2249 com_err(program_name, stat, " in get_subcontainers_of_container");
2250
2251 top = QueueTop(elem);
2252 Loop(top, ((void (*)(char **)) PrintContainer));
2253 FreeQueue(top);
2254 return DM_NORMAL;
2255}
2256
2257int MachineToContainerMap(int argc, char **argv)
2258{
2259 struct mqelem *elem, *top;
2260 char *tmpname, temp_buf[256];
2261
2262 tmpname = canonicalize_hostname(strdup(argv[1]));
2263 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2264 {
2265 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2266 argv[1], tmpname);
2267 Put_message(temp_buf);
2268 }
2269 top = elem = GetMCInfo(CONTMAP, tmpname, NULL);
2270
2271 Put_message("");
2272 while (elem)
2273 {
2274 char **info = elem->q_data;
2275 PrintMContMap(info);
2276 elem = elem->q_forw;
2277 }
2278
2279 FreeQueue(top);
2280 free(tmpname);
2281 return DM_NORMAL;
2282}
2283
2284int AddMachineToContainer(int argc, char **argv)
2285{
2286 int stat;
2287 char *machine, *container, temp_buf[BUFSIZ], *args[10];
2288 Bool add_it, one_machine, one_container;
2289 struct mqelem *melem, *mtop, *celem, *ctop;
2290
2291 machine = canonicalize_hostname(strdup(argv[1]));
2292 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
2293 {
2294 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2295 argv[1], machine);
2296 Put_message(temp_buf);
2297 }
2298 container = argv[2];
2299
2300 celem = ctop = GetMCInfo(CONTAINER, container, NULL);
2301 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
2302 free(machine);
2303
2304 one_machine = (QueueCount(mtop) == 1);
2305 one_container = (QueueCount(ctop) == 1);
2306
2307 while (melem)
2308 {
2309 char **minfo = melem->q_data;
2310 while (celem)
2311 {
2312 char **cinfo = celem->q_data;
2313 if (one_machine && one_container)
2314 add_it = TRUE;
2315 else
2316 {
2317 sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?",
2318 minfo[M_NAME], cinfo[CON_NAME]);
2319 switch (YesNoQuestion(temp_buf, FALSE))
2320 {
2321 case TRUE:
2322 add_it = TRUE;
2323 break;
2324 case FALSE:
2325 add_it = FALSE;
2326 break;
2327 default:
2328 Put_message("Aborting...");
2329 FreeQueue(ctop);
2330 FreeQueue(mtop);
2331 return DM_NORMAL;
2332 }
2333 }
2334 if (add_it)
2335 {
2336 args[0] = minfo[M_NAME];
2337 args[1] = cinfo[CON_NAME];
2338 stat = do_mr_query("add_machine_to_container", 2, args, NULL,
2339 NULL);
2340 switch (stat)
2341 {
2342 case MR_SUCCESS:
2343 break;
2344 case MR_EXISTS:
2345 sprintf(temp_buf, "%s is already in container %s",
2346 minfo[M_NAME], cinfo[CON_NAME]);
2347 Put_message(temp_buf);
2348 break;
2349 default:
2350 com_err(program_name, stat, " in AddMachineToContainer.");
2351 break;
2352 }
2353 }
2354 celem = celem->q_forw;
2355 }
2356 celem = ctop;
2357 melem = melem->q_forw;
2358 }
2359 FreeQueue(ctop);
2360 FreeQueue(mtop);
2361 return DM_NORMAL;
2362}
2363
2364int RemoveMachineFromContainer(int argc, char **argv)
2365{
2366 struct mqelem *elem = NULL;
2367 char buf[BUFSIZ], *args[10];
2368 int stat;
2369
2370 args[0] = canonicalize_hostname(strdup(argv[1]));
2371 if (strcasecmp(args[0], argv[1]) && *argv[1] != '"')
2372 {
2373 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
2374 argv[1], args[0]);
2375 Put_message(buf);
2376 }
2377 args[1] = argv[2];
2378 args[2] = NULL;
2379
2380 stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo,
2381 &elem);
2382 if (stat == MR_NO_MATCH)
2383 {
2384 sprintf(buf, "The machine %s is not in the container %s.",
2385 args[0], args[1]);
2386 Put_message(buf);
2387 free(args[0]);
2388 return DM_NORMAL;
2389 }
2390 if (stat != MR_SUCCESS)
2391 com_err(program_name, stat, " in deleter_machine_from_container");
2392
2393 elem = QueueTop(elem);
2394 QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer,
2395 "Remove this machine from this container");
2396
2397 FreeQueue(elem);
2398 free(args[0]);
2399 return DM_NORMAL;
2400}
2401
2402static void RealRemoveMachineFromContainer(char **info, Bool one_contmap)
2403{
2404 char temp_buf[BUFSIZ];
2405 int stat;
2406
2407 sprintf(temp_buf, "Remove %s from the container %s",
2408 info[0], info[1]);
2409 if (!one_contmap || Confirm(temp_buf))
2410 {
2411 if ((stat = do_mr_query("delete_machine_from_container", 2,
2412 info, NULL, NULL)))
2413 com_err(program_name, stat, " in delete_machine_from_container");
2414 else
2415 {
2416 sprintf(temp_buf, "%s has been removed from the container %s.",
2417 info[0], info[1]);
2418 Put_message(temp_buf);
2419 }
2420 }
2421 else
2422 Put_message("Machine not removed.");
2423}
2424
2425int GetMachinesOfContainer(int argc, char **argv)
2426{
2427 char *args[2];
2428 struct mqelem *elem = NULL, *top = NULL;
2429 int stat;
2430
2431 args[0] = argv[1];
2432
2433 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2434 args[1] = "1";
2435 else
2436 args[1] = "0";
2437
2438 if (stat = do_mr_query("get_machines_of_container", 2, args,
2439 StoreInfo, &elem))
2440 com_err(program_name, stat, " in get_machines_of_container");
2441
2442 top = QueueTop(elem);
2443 Loop(top, ((void (*)(char **)) PrintMContMap));
2444 FreeQueue(top);
2445 return DM_NORMAL;
2446}
This page took 0.518699 seconds and 5 git commands to generate.