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