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