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