]> andersk Git - moira.git/blame - clients/moira/cluster.c
Non void function should actually return something. Thank you, Irix cc.
[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{
7b07cdab 1851 int stat, i;
5eaef520 1852
7b07cdab 1853 for (i = 1; i < 4; i++)
1854 {
1855 if (IS_EMPTY(argv[i]))
1856 {
1857 Put_message("Cluster data cannot be an empty string.");
1858 return DM_NORMAL;
1859 }
1860 }
7ac48069 1861 if ((stat = do_mr_query("add_cluster_data", 3, argv + 1, NULL, NULL)))
5eaef520 1862 com_err(program_name, stat, " in AddClusterData.");
1863 return DM_NORMAL;
08345b74 1864}
1865
402461ad 1866/* Function Name: RealRemoveClusterData
1867 * Description: actually removes the cluster data.
1868 * Arguments: info - all info necessary to remove the cluster, in an array
1869 * of strings.
1870 * one_item - if true then the queue has only one elem and we
1871 * should confirm.
1872 * Returns: none.
1873 */
1874
5eaef520 1875static void RealRemoveClusterData(char **info, Bool one_item)
402461ad 1876{
44d12d58 1877 int stat;
5eaef520 1878 char *temp_ptr;
1879
1880 Put_message(" ");
1881 temp_ptr = "Are you sure that you want to remove this cluster data (y/n) ?";
1882 PrintClusterData(info);
1883 if (!one_item || Confirm(temp_ptr))
1884 {
7ac48069 1885 if ((stat = do_mr_query("delete_cluster_data", 3, info, NULL, NULL)))
5eaef520 1886 {
1887 com_err(program_name, stat, " in DeleteClusterData.");
1888 Put_message("Data not removed.");
402461ad 1889 }
5eaef520 1890 else
1891 Put_message("Removal successful.");
402461ad 1892 }
1893}
1894
461c03b6 1895/* Function Name: RemoveClusterData
1896 * Description: This function removes data on a given cluster.
08345b74 1897 * Arguments: argv, argc: argv[1] - the name of the cluster.
1898 * argv[2] - the label of the data.
1899 * argv[3] - the data.
1900 * Returns: DM_NORMAL.
1901 */
1902
5eaef520 1903int RemoveClusterData(int argc, char **argv)
08345b74 1904{
600b459e 1905 struct mqelem *top;
08345b74 1906
5eaef520 1907 top = GetMCInfo(DATA, argv[1], argv[2]);
1908 QueryLoop(top, PrintClusterData, RealRemoveClusterData,
1909 "Remove data from cluster");
08345b74 1910
5eaef520 1911 FreeQueue(top);
1912 return DM_NORMAL;
08345b74 1913}
1914
08345b74 1915/* Function Name: MachineToClusterMap
1916 * Description: This Retrieves the mapping between machine and cluster
1917 * Arguments: argc, argv - argv[1] -> machine name or wildcard.
1918 * argv[2] -> cluster name or wildcard.
1919 * Returns: none.
1920 */
1921
5eaef520 1922int MachineToClusterMap(int argc, char **argv)
08345b74 1923{
600b459e 1924 struct mqelem *elem, *top;
5eaef520 1925 char *tmpname, temp_buf[256];
1926
7ac48069 1927 tmpname = canonicalize_hostname(strdup(argv[1]));
5eaef520 1928 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
1929 {
1930 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
1931 argv[1], tmpname);
1932 Put_message(temp_buf);
576ba5e7 1933 }
5eaef520 1934 top = elem = GetMCInfo(MAP, tmpname, argv[2]);
1935
1936 Put_message(""); /* blank line on screen */
1937 while (elem)
1938 {
7ac48069 1939 char **info = elem->q_data;
5eaef520 1940 PrintMCMap(info);
1941 elem = elem->q_forw;
461c03b6 1942 }
1943
5eaef520 1944 FreeQueue(top);
1945 free(tmpname);
1946 return DM_NORMAL;
461c03b6 1947}
7399b4b2 1948
1949/* Function Name: MachineByOwner
1950 * Description: This function prints all machines which are owned by
1951 * a given user or group.
1952 * Arguments: none.
1953 * Returns: DM_NORMAL.
1954 */
1955
1956int MachineByOwner(int argc, char **argv)
1957{
1958 char buf[BUFSIZ], temp_buf[BUFSIZ], *type, *name;
1959 struct mqelem *top;
1960
1961 type = strdup("USER");
1962 if (GetTypeFromUser("Type of owner", "ace_type", &type) == SUB_ERROR)
1963 return DM_NORMAL;
1964
1965 sprintf(buf, "Name of %s", type);
1966 name = strdup(user);
1967 if (GetValueFromUser(buf, &name) == SUB_ERROR)
1968 return DM_NORMAL;
1969
1970 switch (YesNoQuestion("Do you want a recursive search (y/n)", FALSE))
1971 {
1972 case TRUE:
1973 sprintf(temp_buf, "R%s", type); /* "USER to "RUSER", etc. */
1974 free(type);
1975 type = strdup(temp_buf);
1976 break;
1977 case FALSE:
1978 break;
1979 default:
1980 return DM_NORMAL;
1981 }
1982
1983 top = GetMachineByOwner(type, name);
1984 Loop(top, PrintMachine);
1985
1986 FreeQueue(top);
1987 return DM_NORMAL;
1988}
1989
1990/* Function Name: GetMachineByOwner
1991 * Description: This function stores information retrieved by
1992 * the get_host_by_owner query
1993 * Arguments: type - an ace_type, argv[0] for the query
1994 * name - name of machine, argv[1] for the query
1995 * Returns: the top element of a queue returning the data, or NULL.
1996 */
1997
1998struct mqelem *GetMachineByOwner(char *type, char *name)
1999{
2000 char *args[2];
2001 struct mqelem *elem = NULL;
2002 int status;
2003
2004 args[0] = type;
2005 args[1] = name;
2006 if ((status = do_mr_query("get_host_by_owner", 2, args, StoreInfo, &elem)))
2007 {
2008 com_err(program_name, status, " in get_host_by_owner");
2009 return NULL;
2010 }
2011 return QueueTop(elem);
2012}
9cd2d193 2013
2014int ShowContainerInfo(int argc, char **argv)
2015{
2016 struct mqelem *top;
2017
2018 top = GetMCInfo(CONTAINER, argv[1], NULL);
2019 Loop(top, (void (*)(char **)) PrintContainerInfo);
2020 FreeQueue(top);
2021 return DM_NORMAL;
2022}
2023
2024static char *PrintContainerInfo(char **info)
2025{
2026 char buf[BUFSIZ], tbuf[256];
2027
2028 Put_message("");
2029 sprintf(buf, "Container: %-16s", info[CON_NAME]);
2030 Put_message(buf);
2031 sprintf(buf, "Description: %-16s", info[CON_DESCRIPT]);
2032 Put_message(buf);
2033 sprintf(buf, "Location: %-16s Contact: %s", info[CON_LOCATION],
2034 info[CON_CONTACT]);
2035 Put_message(buf);
2036 sprintf(tbuf, "%s %s", info[CON_OWNER_TYPE],
2037 strcmp(info[CON_OWNER_TYPE], "NONE") ? info[CON_OWNER_NAME] : "");
2038 sprintf(buf, "Owner: %-16s", tbuf);
2039 Put_message(buf);
2040 sprintf(tbuf, "%s %s", info[CON_MEMACE_TYPE],
2041 strcmp(info[CON_MEMACE_TYPE], "NONE") ? info[CON_MEMACE_NAME] : "");
2042 sprintf(buf, "Membership ACL: %-16s", tbuf);
2043 Put_message(buf);
2044 Put_message("");
2045 sprintf(buf, MOD_FORMAT, info[CON_MODBY], info[CON_MODTIME],
2046 info[CON_MODWITH]);
2047 Put_message(buf);
2048 return info[CON_NAME];
2049}
2050
2051static char *PrintContainer(char **info)
2052{
2053 char buf[BUFSIZ];
2054
2055 sprintf(buf, "Container: %s", info[CON_NAME]);
2056 Put_message(buf);
84dc1928 2057 return "";
9cd2d193 2058}
2059
2060static char *PrintMContMap(char **info)
2061{
2062 char buf[BUFSIZ];
2063 sprintf(buf, "Container: %-30s Machine: %-20s",
2064 info[1], info[0]);
2065 Put_message(buf);
2066 return "";
2067}
2068
2069int AddContainer(int argc, char **argv)
2070{
2071 char **args, *info[MAX_ARGS_SIZE], *name = argv[1];
2072 int stat;
2073
bb52f279 2074 /* Can't use ValidName() because spaces are allowed in container names */
2075 if (IS_EMPTY(name))
2076 {
2077 Put_message("Please use a non-empty name.");
2078 return DM_NORMAL;
2079 }
2080
2081 if (strchr(name, '*') || strchr(name, '?'))
2082 {
2083 Put_message("Wildcards not accepted here.");
2084 return DM_NORMAL;
2085 }
9cd2d193 2086
2087 /* Check if this cluster already exists. */
2088 if ((stat = do_mr_query("get_container", 1, &name, NULL, NULL))
2089 == MR_SUCCESS)
2090 {
2091 Put_message("This container already exists.");
2092 return DM_NORMAL;
2093 }
2094 else if (stat != MR_NO_MATCH)
2095 {
2096 com_err(program_name, stat, " in AddContainer.");
2097 return DM_NORMAL;
2098 }
2099 if (!(args = AskMCDInfo(SetContainerDefaults(info, name), CONTAINER, FALSE)))
2100 {
2101 Put_message("Aborted.");
2102 FreeInfo(info);
2103 return DM_NORMAL;
2104 }
2105
2106 /* Create the new container. */
2107 if ((stat = do_mr_query("add_container", CountArgs(args), args, NULL, NULL)))
2108 com_err(program_name, stat, " in AddContainer.");
2109
2110 FreeInfo(info);
2111 return DM_NORMAL;
2112}
2113
2114int UpdateContainer(int argc, char **argv)
2115{
2116 struct mqelem *top;
2117 top = GetMCInfo(CONTAINER, argv[1], NULL);
2118 QueryLoop(top, NullPrint, RealUpdateContainer, "Update the container");
2119
2120 FreeQueue(top);
2121 return DM_NORMAL;
2122}
2123
2124static void RealUpdateContainer(char **info, Bool junk)
2125{
2126 int stat;
2127 char **args = AskMCDInfo(info, CONTAINER, TRUE);
2128
2129 if (!args)
2130 {
2131 Put_message("Aborted.");
2132 return;
2133 }
2134 if ((stat = do_mr_query("update_container", CountArgs(args), args,
2135 NULL, NULL)))
2136 com_err(program_name, stat, " in UpdateContainer.");
2137 else
2138 Put_message("Container successfully updated.");
2139}
2140
2141int DeleteContainer(int argc, char **argv)
2142{
2143 struct mqelem *top;
2144
2145 top = GetMCInfo(CONTAINER, argv[1], NULL);
2146 QueryLoop(top, PrintClusterInfo, RealDeleteContainer,
2147 "Delete the container");
2148
2149 FreeQueue(top);
2150 return DM_NORMAL;
2151}
2152
2153static void RealDeleteContainer(char **info, Bool one_container)
2154{
2155 int stat;
2156 char temp_buf[BUFSIZ];
2157
2158 sprintf(temp_buf,
2159 "Are you sure you want to delete the container %s (y/n) ?",
2160 info[CON_NAME]);
2161 if (!one_container || Confirm(temp_buf))
2162 {
2163 if (CheckAndRemoveMachinesFromContainer(info[CON_NAME], TRUE)
2164 != SUB_ERROR)
2165 {
2166 if ((stat = do_mr_query("delete_container", 1, &info[CON_NAME],
2167 NULL, NULL)))
2168 {
2169 com_err(program_name, stat, " in delete_container.");
2170 sprintf(temp_buf, "Container %s ** NOT ** deleted.",
2171 info[CON_NAME]);
2172 Put_message(temp_buf);
2173 }
2174 else
2175 {
2176 sprintf(temp_buf, "Container %s successfully deleted.",
2177 info[CON_NAME]);
2178 Put_message(temp_buf);
2179 }
2180 }
2181 }
2182}
2183
2184int CheckAndRemoveMachinesFromContainer(char *name, Bool ask_first)
2185{
2186 int stat, ret_value;
2187 Bool delete_it;
2188 char *args[10], temp_buf[BUFSIZ], *ptr;
2189 struct mqelem *top, *elem = NULL;
2190
2191 ret_value = SUB_NORMAL;
2192 args[0] = name;
2193 args[1] = "0";
2194 stat = do_mr_query("get_machines_of_container", 2, args, StoreInfo,
2195 &elem);
2196 if (stat && stat != MR_NO_MATCH)
2197 {
2198 com_err(program_name, stat, " in get_machines_of_container");
2199 return DM_NORMAL;
2200 }
2201 if (stat == MR_SUCCESS)
2202 {
2203 elem = top = QueueTop(elem);
2204 if (ask_first)
2205 {
2206 sprintf(temp_buf,
2207 "The container %s has the following machines in it:", name);
2208 Put_message(temp_buf);
2209 while (elem)
2210 {
2211 char **info = elem->q_data;
2212 Print(1, &info[0], (char *) NULL);
2213 elem = elem->q_forw;
2214 }
2215 ptr = "Remove ** ALL ** these machines from this container?";
2216
2217 if (YesNoQuestion(ptr, FALSE) == TRUE) /* may return -1. */
2218 delete_it = TRUE;
2219 else
2220 {
2221 Put_message("Aborting...");
2222 FreeQueue(top);
2223 return SUB_ERROR;
2224 }
2225 }
2226 else
2227 delete_it = TRUE;
2228
2229 if (delete_it)
2230 {
2231 elem = top;
2232 while (elem)
2233 {
2234 char **info = elem->q_data;
2235 if ((stat = do_mr_query("delete_machine_from_container",
2236 2, info, NULL, NULL)))
2237 {
2238 ret_value = SUB_ERROR;
2239 com_err(program_name, stat,
2240 " in delete_machine_from_container.");
2241 sprintf(temp_buf,
2242 "Machine %s ** NOT ** removed from container %s.",
2243 info[0], info[1]);
2244 Put_message(temp_buf);
2245 }
2246 elem = elem->q_forw;
2247 }
2248 }
2249 }
2250 return ret_value;
2251}
2252
2253int GetSubContainers(int argc, char **argv)
2254{
2255 char *args[2];
2256 struct mqelem *elem = NULL, *top = NULL;
2257 int stat;
2258
2259 args[0] = argv[1];
2260
2261 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2262 args[1] = "1";
2263 else
2264 args[1] = "0";
2265
2266 if (stat = do_mr_query("get_subcontainers_of_container", 2, args,
2267 StoreInfo, &elem))
2268 com_err(program_name, stat, " in get_subcontainers_of_container");
2269
2270 top = QueueTop(elem);
2271 Loop(top, ((void (*)(char **)) PrintContainer));
2272 FreeQueue(top);
2273 return DM_NORMAL;
2274}
2275
2276int MachineToContainerMap(int argc, char **argv)
2277{
2278 struct mqelem *elem, *top;
2279 char *tmpname, temp_buf[256];
2280
2281 tmpname = canonicalize_hostname(strdup(argv[1]));
2282 if (strcasecmp(tmpname, argv[1]) && *argv[1] != '"')
2283 {
2284 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2285 argv[1], tmpname);
2286 Put_message(temp_buf);
2287 }
2288 top = elem = GetMCInfo(CONTMAP, tmpname, NULL);
2289
2290 Put_message("");
2291 while (elem)
2292 {
2293 char **info = elem->q_data;
2294 PrintMContMap(info);
2295 elem = elem->q_forw;
2296 }
2297
2298 FreeQueue(top);
2299 free(tmpname);
2300 return DM_NORMAL;
2301}
2302
2303int AddMachineToContainer(int argc, char **argv)
2304{
2305 int stat;
2306 char *machine, *container, temp_buf[BUFSIZ], *args[10];
2307 Bool add_it, one_machine, one_container;
2308 struct mqelem *melem, *mtop, *celem, *ctop;
2309
2310 machine = canonicalize_hostname(strdup(argv[1]));
2311 if (strcasecmp(machine, argv[1]) && *argv[1] != '"')
2312 {
2313 sprintf(temp_buf, "Warning: '%s' canonicalized to '%s'.",
2314 argv[1], machine);
2315 Put_message(temp_buf);
2316 }
2317 container = argv[2];
2318
2319 celem = ctop = GetMCInfo(CONTAINER, container, NULL);
2320 melem = mtop = GetMCInfo(MACHINE, machine, NULL);
2321 free(machine);
2322
2323 one_machine = (QueueCount(mtop) == 1);
2324 one_container = (QueueCount(ctop) == 1);
2325
2326 while (melem)
2327 {
2328 char **minfo = melem->q_data;
2329 while (celem)
2330 {
2331 char **cinfo = celem->q_data;
2332 if (one_machine && one_container)
2333 add_it = TRUE;
2334 else
2335 {
2336 sprintf(temp_buf, "Add machine %s to container %s (y/n/q) ?",
2337 minfo[M_NAME], cinfo[CON_NAME]);
2338 switch (YesNoQuestion(temp_buf, FALSE))
2339 {
2340 case TRUE:
2341 add_it = TRUE;
2342 break;
2343 case FALSE:
2344 add_it = FALSE;
2345 break;
2346 default:
2347 Put_message("Aborting...");
2348 FreeQueue(ctop);
2349 FreeQueue(mtop);
2350 return DM_NORMAL;
2351 }
2352 }
2353 if (add_it)
2354 {
2355 args[0] = minfo[M_NAME];
2356 args[1] = cinfo[CON_NAME];
2357 stat = do_mr_query("add_machine_to_container", 2, args, NULL,
2358 NULL);
2359 switch (stat)
2360 {
2361 case MR_SUCCESS:
2362 break;
2363 case MR_EXISTS:
2364 sprintf(temp_buf, "%s is already in container %s",
2365 minfo[M_NAME], cinfo[CON_NAME]);
2366 Put_message(temp_buf);
2367 break;
2368 default:
2369 com_err(program_name, stat, " in AddMachineToContainer.");
2370 break;
2371 }
2372 }
2373 celem = celem->q_forw;
2374 }
2375 celem = ctop;
2376 melem = melem->q_forw;
2377 }
2378 FreeQueue(ctop);
2379 FreeQueue(mtop);
2380 return DM_NORMAL;
2381}
2382
2383int RemoveMachineFromContainer(int argc, char **argv)
2384{
2385 struct mqelem *elem = NULL;
2386 char buf[BUFSIZ], *args[10];
2387 int stat;
2388
2389 args[0] = canonicalize_hostname(strdup(argv[1]));
2390 if (strcasecmp(args[0], argv[1]) && *argv[1] != '"')
2391 {
2392 sprintf(buf, "Warning: '%s' canonicalized to '%s'.",
2393 argv[1], args[0]);
2394 Put_message(buf);
2395 }
2396 args[1] = argv[2];
2397 args[2] = NULL;
2398
2399 stat = do_mr_query("get_machine_to_container_map", 1, args, StoreInfo,
2400 &elem);
2401 if (stat == MR_NO_MATCH)
2402 {
2403 sprintf(buf, "The machine %s is not in the container %s.",
2404 args[0], args[1]);
2405 Put_message(buf);
2406 free(args[0]);
2407 return DM_NORMAL;
2408 }
2409 if (stat != MR_SUCCESS)
2410 com_err(program_name, stat, " in deleter_machine_from_container");
2411
2412 elem = QueueTop(elem);
2413 QueryLoop(elem, PrintMContMap, RealRemoveMachineFromContainer,
2414 "Remove this machine from this container");
2415
2416 FreeQueue(elem);
2417 free(args[0]);
2418 return DM_NORMAL;
2419}
2420
2421static void RealRemoveMachineFromContainer(char **info, Bool one_contmap)
2422{
2423 char temp_buf[BUFSIZ];
2424 int stat;
2425
2426 sprintf(temp_buf, "Remove %s from the container %s",
2427 info[0], info[1]);
2428 if (!one_contmap || Confirm(temp_buf))
2429 {
2430 if ((stat = do_mr_query("delete_machine_from_container", 2,
2431 info, NULL, NULL)))
2432 com_err(program_name, stat, " in delete_machine_from_container");
2433 else
2434 {
2435 sprintf(temp_buf, "%s has been removed from the container %s.",
2436 info[0], info[1]);
2437 Put_message(temp_buf);
2438 }
2439 }
2440 else
2441 Put_message("Machine not removed.");
2442}
2443
2444int GetMachinesOfContainer(int argc, char **argv)
2445{
2446 char *args[2];
2447 struct mqelem *elem = NULL, *top = NULL;
2448 int stat;
2449
2450 args[0] = argv[1];
2451
2452 if (YesNoQuestion("Do you want a recursive search?", TRUE) == TRUE)
2453 args[1] = "1";
2454 else
2455 args[1] = "0";
2456
2457 if (stat = do_mr_query("get_machines_of_container", 2, args,
2458 StoreInfo, &elem))
2459 com_err(program_name, stat, " in get_machines_of_container");
2460
2461 top = QueueTop(elem);
2462 Loop(top, ((void (*)(char **)) PrintMContMap));
2463 FreeQueue(top);
2464 return DM_NORMAL;
2465}
86ad14f9 2466
2467int GetTopLevelCont(int argc, char **argv)
2468{
2469 int status;
2470 struct mqelem *elem = NULL;
2471 if (status = do_mr_query("get_toplevel_containers", 0, NULL, StoreInfo,
2472 &elem))
2473 {
2474 com_err(program_name, status, " in get_toplevel_containers");
2475 return DM_NORMAL;
2476 }
2477 Loop(QueueTop(elem), (void(*)(char **)) PrintContainer);
2478 FreeQueue(elem);
2479 return DM_NORMAL;
2480}
This page took 0.523044 seconds and 5 git commands to generate.