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