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