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