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