]>
Commit | Line | Data |
---|---|---|
80e8aa14 | 1 | /* |
2 | * Command line oriented Moira host tool. | |
3 | * | |
4 | * kolya@MIT.EDU, January 2000 | |
5 | * | |
6 | * Somewhat based on blanche | |
7 | * | |
8d138b83 | 8 | * Copyright (C) 2000, 2001 by the Massachusetts Institute of Technology. |
80e8aa14 | 9 | * For copying and distribution information, please see the file |
10 | * <mit-copyright.h>. | |
11 | */ | |
12 | ||
13 | #include <mit-copyright.h> | |
14 | #include <moira.h> | |
15 | #include <moira_site.h> | |
16 | #include <mrclient.h> | |
17 | ||
18 | #include <ctype.h> | |
19 | #include <errno.h> | |
20 | #include <stdio.h> | |
21 | #include <stdlib.h> | |
22 | #include <string.h> | |
23 | ||
0aebabe7 | 24 | #ifdef _WIN32 |
25 | typedef unsigned long in_addr_t; | |
26 | #else | |
27 | #include <sys/types.h> | |
28 | #include <sys/socket.h> | |
29 | ||
30 | #include <netinet/in.h> | |
31 | #include <arpa/inet.h> | |
32 | #endif | |
33 | ||
80e8aa14 | 34 | RCSID("$Header$"); |
35 | ||
36 | struct owner_type { | |
37 | int type; | |
38 | char *name; | |
39 | }; | |
40 | ||
41 | struct mqelem { | |
42 | struct mqelem *q_forw; | |
43 | struct mqelem *q_back; | |
44 | void *q_data; | |
45 | }; | |
46 | ||
47 | struct string_list { | |
48 | char *string; | |
49 | struct string_list *next; | |
50 | }; | |
51 | ||
80e8aa14 | 52 | #define M_ANY 0 |
53 | #define M_USER 1 | |
54 | #define M_LIST 2 | |
a547d259 | 55 | #define M_KERBEROS 3 |
56 | #define M_NONE 4 | |
80e8aa14 | 57 | |
58 | /* argument parsing macro */ | |
59 | #define argis(a, b) (!strcmp(*arg + 1, a) || !strcmp(*arg + 1, b)) | |
60 | ||
61 | /* flags from command line */ | |
62 | int info_flag, update_flag, create_flag, delete_flag, list_map_flag; | |
7e689fac | 63 | int update_alias_flag, update_map_flag, verbose, noauth; |
7b6a099a | 64 | int list_container_flag, update_container_flag, unformatted_flag; |
80e8aa14 | 65 | |
66 | struct string_list *alias_add_queue, *alias_remove_queue; | |
67 | struct string_list *map_add_queue, *map_remove_queue; | |
9cd2d193 | 68 | struct string_list *container_add_queue, *container_remove_queue; |
80e8aa14 | 69 | |
70 | char *hostname, *whoami; | |
71 | ||
72 | char *newname, *address, *network, *h_status, *vendor, *model; | |
4f6b1a05 | 73 | char *os, *location, *contact, *billing_contact, *account_number; |
74 | char *adm_cmt, *op_cmt; | |
80e8aa14 | 75 | |
8d138b83 | 76 | in_addr_t ipaddress; |
80e8aa14 | 77 | struct owner_type *owner; |
78 | ||
79 | void usage(char **argv); | |
80 | int store_host_info(int argc, char **argv, void *hint); | |
81 | void show_host_info(char **argv); | |
7b6a099a | 82 | void show_host_info_unformatted(char **argv); |
80e8aa14 | 83 | int show_machine_in_cluster(int argc, char **argv, void *hint); |
9cd2d193 | 84 | int show_machine_in_container(int argc, char **argv, void *hint); |
80e8aa14 | 85 | struct owner_type *parse_member(char *s); |
86 | struct string_list *add_to_string_list(struct string_list *old_list, char *s); | |
87 | int wrap_mr_query(char *handle, int argc, char **argv, | |
88 | int (*callback)(int, char **, void *), void *callarg); | |
89 | void print_query(char *query_name, int argc, char **argv); | |
90 | ||
91 | int main(int argc, char **argv) | |
92 | { | |
93 | int status, success; | |
94 | char **arg = argv; | |
533bacb3 | 95 | char *server = NULL; |
80e8aa14 | 96 | |
97 | /* clear all flags & lists */ | |
98 | info_flag = update_flag = create_flag = list_map_flag = update_map_flag = 0; | |
7e689fac | 99 | update_alias_flag = verbose = noauth = 0; |
9cd2d193 | 100 | list_container_flag = update_container_flag = 0; |
80e8aa14 | 101 | newname = address = network = h_status = vendor = model = NULL; |
4f6b1a05 | 102 | os = location = contact = billing_contact = account_number = adm_cmt = NULL; |
103 | op_cmt = NULL; | |
80e8aa14 | 104 | owner = NULL; |
105 | alias_add_queue = alias_remove_queue = NULL; | |
106 | map_add_queue = map_remove_queue = NULL; | |
9cd2d193 | 107 | container_add_queue = container_remove_queue = NULL; |
80e8aa14 | 108 | whoami = argv[0]; |
109 | ||
110 | success = 1; | |
111 | ||
112 | /* parse args, building addlist, dellist, & synclist */ | |
113 | while (++arg - argv < argc) | |
114 | { | |
115 | if (**arg == '-') | |
116 | { | |
117 | if (argis("i", "info")) | |
118 | info_flag++; | |
119 | else if (argis("C", "create")) | |
120 | create_flag++; | |
121 | else if (argis("D", "delete")) | |
122 | delete_flag++; | |
123 | else if (argis("R", "rename")) { | |
124 | if (arg - argv < argc - 1) { | |
125 | arg++; | |
126 | update_flag++; | |
127 | newname = *arg; | |
128 | } else | |
129 | usage(argv); | |
130 | } | |
131 | else if (argis("A", "address")) { | |
132 | if (arg - argv < argc - 1) { | |
133 | arg++; | |
134 | update_flag++; | |
135 | address = *arg; | |
136 | } else | |
137 | usage(argv); | |
138 | } | |
139 | else if (argis("O", "owner")) { | |
140 | if (arg - argv < argc - 1) { | |
141 | arg++; | |
142 | update_flag++; | |
143 | owner = parse_member(*arg); | |
144 | } else | |
145 | usage(argv); | |
146 | } | |
147 | else if (argis("N", "network")) { | |
148 | if (arg - argv < argc - 1) { | |
149 | arg++; | |
150 | update_flag++; | |
151 | network = *arg; | |
152 | } else | |
153 | usage(argv); | |
154 | } | |
155 | else if (argis("S", "status")) { | |
156 | if (arg - argv < argc - 1) { | |
157 | int i; | |
533bacb3 | 158 | int len; |
80e8aa14 | 159 | |
160 | arg++; | |
161 | update_flag++; | |
162 | h_status = *arg; | |
163 | ||
533bacb3 | 164 | len = strlen(h_status); |
165 | for(i = 0; i < len; i++) { | |
80e8aa14 | 166 | if(!isdigit(h_status[i])) { |
167 | printf("Error: status code %s is not numeric.\n", h_status); | |
168 | exit(1); | |
169 | } | |
170 | } | |
171 | } else | |
172 | usage(argv); | |
173 | } | |
174 | else if (argis("V", "vendor")) { | |
175 | if (arg - argv < argc - 1) { | |
176 | arg++; | |
177 | update_flag++; | |
178 | vendor = *arg; | |
179 | } else | |
180 | usage(argv); | |
181 | } | |
182 | else if (argis("M", "model")) { | |
183 | if (arg - argv < argc - 1) { | |
184 | arg++; | |
185 | update_flag++; | |
186 | model = *arg; | |
187 | } else | |
188 | usage(argv); | |
189 | } | |
190 | else if (argis("o", "os")) { | |
191 | if (arg - argv < argc - 1) { | |
192 | arg++; | |
193 | update_flag++; | |
194 | os = *arg; | |
195 | } else | |
196 | usage(argv); | |
197 | } | |
198 | else if (argis("L", "location")) { | |
199 | if (arg - argv < argc - 1) { | |
200 | arg++; | |
201 | update_flag++; | |
202 | location = *arg; | |
203 | } else | |
204 | usage(argv); | |
205 | } | |
206 | else if (argis("c", "contact")) { | |
207 | if (arg - argv < argc - 1) { | |
208 | arg++; | |
209 | update_flag++; | |
210 | contact = *arg; | |
211 | } else | |
212 | usage(argv); | |
213 | } | |
080e5e2c | 214 | else if (argis("bc", "billingcontact")) { |
215 | if (arg - argv < argc - 1) { | |
216 | arg++; | |
217 | update_flag++; | |
218 | billing_contact = *arg; | |
219 | } else | |
220 | usage(argv); | |
221 | } | |
4f6b1a05 | 222 | else if (argis("an", "accountnumber")) { |
223 | if (arg - argv < argc - 1) { | |
224 | arg++; | |
225 | update_flag++; | |
226 | account_number = *arg; | |
227 | } else | |
228 | usage(argv); | |
229 | } | |
80e8aa14 | 230 | else if (argis("ac", "admcmt")) { |
231 | if (arg - argv < argc - 1) { | |
232 | arg++; | |
233 | update_flag++; | |
234 | adm_cmt = *arg; | |
235 | } else | |
236 | usage(argv); | |
237 | } | |
238 | else if (argis("oc", "opcmt")) { | |
239 | if (arg - argv < argc - 1) { | |
240 | arg++; | |
241 | update_flag++; | |
242 | op_cmt = *arg; | |
243 | } else | |
244 | usage(argv); | |
245 | } | |
88cced27 | 246 | else if (argis("a", "addalias")) { |
80e8aa14 | 247 | if (arg - argv < argc - 1) { |
248 | arg++; | |
249 | alias_add_queue=add_to_string_list(alias_add_queue, *arg); | |
250 | } else | |
251 | usage(argv); | |
7e689fac | 252 | update_alias_flag++; |
80e8aa14 | 253 | } |
88cced27 | 254 | else if (argis("d", "deletealias")) { |
80e8aa14 | 255 | if (arg - argv < argc - 1) { |
256 | arg++; | |
257 | alias_remove_queue=add_to_string_list(alias_remove_queue, *arg); | |
258 | } else | |
259 | usage(argv); | |
7e689fac | 260 | update_alias_flag++; |
80e8aa14 | 261 | } |
262 | else if (argis("am", "addmap")) { | |
263 | if (arg - argv < argc - 1) { | |
264 | arg++; | |
265 | map_add_queue=add_to_string_list(map_add_queue, *arg); | |
266 | } else | |
267 | usage(argv); | |
268 | update_map_flag++; | |
269 | } | |
270 | else if (argis("dm", "deletemap")) { | |
271 | if (arg - argv < argc - 1) { | |
272 | arg++; | |
273 | map_remove_queue=add_to_string_list(map_remove_queue, *arg); | |
274 | } else | |
275 | usage(argv); | |
276 | update_map_flag++; | |
277 | } | |
278 | else if (argis("lm", "listmap")) | |
279 | list_map_flag++; | |
9cd2d193 | 280 | else if (argis("acn", "addcontainer")) { |
281 | if (arg - argv < argc - 1) { | |
282 | arg++; | |
283 | container_add_queue = | |
284 | add_to_string_list(container_add_queue, *arg); | |
285 | } else | |
286 | usage(argv); | |
287 | update_container_flag++; | |
288 | } | |
289 | else if (argis("dcn", "deletecontainer")) { | |
290 | if (arg - argv < argc - 1) { | |
291 | arg++; | |
292 | container_remove_queue = | |
293 | add_to_string_list(container_remove_queue, *arg); | |
294 | } else | |
295 | usage(argv); | |
296 | update_container_flag++; | |
297 | } | |
298 | else if (argis("lcn", "listcontainer")) | |
299 | list_container_flag++; | |
7b6a099a | 300 | else if (argis("u", "unformatted")) |
301 | unformatted_flag++; | |
80e8aa14 | 302 | else if (argis("n", "noauth")) |
303 | noauth++; | |
304 | else if (argis("v", "verbose")) | |
305 | verbose++; | |
306 | else if (argis("db", "database")) | |
307 | { | |
308 | if (arg - argv < argc - 1) | |
309 | { | |
310 | ++arg; | |
311 | server = *arg; | |
312 | } | |
313 | else | |
314 | usage(argv); | |
315 | } | |
316 | else | |
317 | usage(argv); | |
318 | } | |
319 | else if (hostname == NULL) | |
320 | hostname = *arg; | |
321 | else | |
322 | usage(argv); | |
323 | } | |
324 | if (hostname == NULL) | |
325 | usage(argv); | |
326 | ||
327 | /* default to info_flag if nothing else was specified */ | |
328 | if(!(info_flag || update_flag || create_flag || \ | |
7e689fac | 329 | delete_flag || list_map_flag || update_map_flag || \ |
9cd2d193 | 330 | update_alias_flag || update_container_flag || \ |
331 | list_container_flag)) { | |
80e8aa14 | 332 | info_flag++; |
333 | } | |
334 | ||
335 | /* fire up Moira */ | |
4f6b1a05 | 336 | status = mrcl_connect(server, "stella", 8, !noauth); |
80e8aa14 | 337 | if (status == MRCL_AUTH_ERROR) |
338 | { | |
339 | com_err(whoami, 0, "Try the -noauth flag if you don't " | |
340 | "need authentication."); | |
341 | } | |
342 | if (status) | |
343 | exit(2); | |
344 | ||
8d138b83 | 345 | /* Perform the lookup by IP address if that's what we've been handed */ |
346 | if ((ipaddress=inet_addr(hostname)) != -1) { | |
347 | char *args[5]; | |
348 | char *argv[30]; | |
349 | ||
350 | args[1] = strdup(hostname); | |
351 | args[0] = args[2] = args[3] = "*"; | |
352 | status = wrap_mr_query("get_host", 4, args, store_host_info, argv); | |
353 | ||
354 | if (status) { | |
355 | com_err(whoami, status, "while looking up IP address."); | |
356 | } else { | |
357 | hostname = argv[0]; | |
358 | } | |
359 | } | |
360 | ||
80e8aa14 | 361 | /* create if needed */ |
362 | if (create_flag) | |
363 | { | |
364 | char *argv[30]; | |
365 | int cnt; | |
366 | ||
4f6b1a05 | 367 | for (cnt = 0; cnt < 17; cnt++) { |
80e8aa14 | 368 | argv[cnt] = ""; |
369 | } | |
370 | ||
371 | argv[0] = canonicalize_hostname(strdup(hostname)); | |
372 | ||
373 | if (vendor) | |
374 | argv[1] = vendor; | |
375 | if (model) | |
376 | argv[2] = model; | |
377 | if (os) | |
378 | argv[3] = os; | |
379 | if (location) | |
380 | argv[4] = location; | |
381 | if (contact) | |
382 | argv[5] = contact; | |
080e5e2c | 383 | if (billing_contact) |
384 | argv[6] = billing_contact; | |
4f6b1a05 | 385 | if (account_number) |
386 | argv[7] = account_number; | |
80e8aa14 | 387 | /* The use field always gets set to "0" */ |
4f6b1a05 | 388 | argv[8] = "0"; |
80e8aa14 | 389 | if (h_status) |
4f6b1a05 | 390 | argv[9] = h_status; |
80e8aa14 | 391 | else |
4f6b1a05 | 392 | argv[9] = "1"; |
80e8aa14 | 393 | if (network) |
4f6b1a05 | 394 | argv[10] = network; |
80e8aa14 | 395 | if (address) |
4f6b1a05 | 396 | argv[11] = address; |
d55f933a | 397 | else |
4f6b1a05 | 398 | argv[11] = "unique"; |
80e8aa14 | 399 | if (adm_cmt) |
4f6b1a05 | 400 | argv[14] = adm_cmt; |
80e8aa14 | 401 | if (op_cmt) |
4f6b1a05 | 402 | argv[15] = op_cmt; |
80e8aa14 | 403 | |
404 | if (owner) | |
405 | { | |
4f6b1a05 | 406 | argv[13] = owner->name; |
80e8aa14 | 407 | switch (owner->type) |
408 | { | |
409 | case M_ANY: | |
410 | case M_USER: | |
4f6b1a05 | 411 | argv[12] = "USER"; |
412 | status = wrap_mr_query("add_host", 16, argv, NULL, NULL); | |
80e8aa14 | 413 | if (owner->type != M_ANY || status != MR_USER) |
414 | break; | |
415 | ||
416 | case M_LIST: | |
4f6b1a05 | 417 | argv[12] = "LIST"; |
418 | status = wrap_mr_query("add_host", 16, argv, NULL, NULL); | |
80e8aa14 | 419 | break; |
420 | ||
421 | case M_KERBEROS: | |
4f6b1a05 | 422 | argv[12] = "KERBEROS"; |
423 | status = mrcl_validate_kerberos_member(argv[13], &argv[13]); | |
df183ce8 | 424 | if (mrcl_get_message()) |
425 | mrcl_com_err(whoami); | |
138b81d7 | 426 | if (status == MRCL_REJECT) |
427 | exit(1); | |
4f6b1a05 | 428 | status = wrap_mr_query("add_host", 16, argv, NULL, NULL); |
80e8aa14 | 429 | break; |
430 | ||
431 | case M_NONE: | |
4f6b1a05 | 432 | argv[12] = "NONE"; |
433 | status = wrap_mr_query("add_host", 16, argv, NULL, NULL); | |
80e8aa14 | 434 | break; |
435 | } | |
436 | } | |
437 | else | |
438 | { | |
080e5e2c | 439 | argv[12] = "NONE"; |
4f6b1a05 | 440 | argv[13] = "NONE"; |
80e8aa14 | 441 | |
4f6b1a05 | 442 | status = wrap_mr_query("add_host", 16, argv, NULL, NULL); |
80e8aa14 | 443 | } |
444 | ||
445 | if (status) | |
446 | { | |
447 | com_err(whoami, status, "while creating host."); | |
448 | exit(1); | |
449 | } | |
450 | ||
451 | } | |
452 | else if (update_flag) | |
453 | { | |
454 | char *old_argv[30]; | |
4f6b1a05 | 455 | char *argv[17]; |
80e8aa14 | 456 | char *args[5]; |
80e8aa14 | 457 | |
458 | args[0] = canonicalize_hostname(strdup(hostname)); | |
459 | args[1] = args[2] = args[3] = "*"; | |
460 | ||
461 | status = wrap_mr_query("get_host", 4, args, store_host_info, old_argv); | |
462 | if (status) | |
463 | { | |
464 | com_err(whoami, status, "while getting list information"); | |
465 | exit(1); | |
466 | } | |
467 | ||
468 | argv[1] = old_argv[0]; | |
469 | argv[2] = old_argv[1]; | |
470 | argv[3] = old_argv[2]; | |
471 | argv[4] = old_argv[3]; | |
472 | argv[5] = old_argv[4]; | |
473 | argv[6] = old_argv[5]; | |
474 | argv[7] = old_argv[6]; | |
475 | argv[8] = old_argv[7]; | |
080e5e2c | 476 | argv[9] = old_argv[8]; |
4f6b1a05 | 477 | argv[10] = old_argv[9]; |
80e8aa14 | 478 | argv[11] = old_argv[11]; |
479 | argv[12] = old_argv[12]; | |
480 | argv[13] = old_argv[13]; | |
481 | argv[14] = old_argv[14]; | |
080e5e2c | 482 | argv[15] = old_argv[15]; |
4f6b1a05 | 483 | argv[16] = old_argv[16]; |
80e8aa14 | 484 | |
485 | argv[0] = canonicalize_hostname(strdup(hostname)); | |
486 | if (newname) | |
6c114a34 | 487 | argv[1] = canonicalize_hostname(strdup(newname)); |
80e8aa14 | 488 | if (vendor) |
489 | argv[2] = vendor; | |
490 | if (model) | |
491 | argv[3] = model; | |
492 | if (os) | |
493 | argv[4] = os; | |
494 | if (location) | |
495 | argv[5] = location; | |
496 | if (contact) | |
497 | argv[6] = contact; | |
080e5e2c | 498 | if (billing_contact) |
499 | argv[7] = billing_contact; | |
4f6b1a05 | 500 | if (account_number) |
501 | argv[8] = account_number; | |
80e8aa14 | 502 | if (h_status) |
4f6b1a05 | 503 | argv[10] = h_status; |
80e8aa14 | 504 | if (network) |
4f6b1a05 | 505 | argv[11] = network; |
80e8aa14 | 506 | if (address) |
4f6b1a05 | 507 | argv[12] = address; |
80e8aa14 | 508 | if (adm_cmt) |
4f6b1a05 | 509 | argv[15] = adm_cmt; |
80e8aa14 | 510 | if (op_cmt) |
4f6b1a05 | 511 | argv[16] = op_cmt; |
80e8aa14 | 512 | |
513 | if (owner) | |
514 | { | |
4f6b1a05 | 515 | argv[14] = owner->name; |
80e8aa14 | 516 | switch (owner->type) |
517 | { | |
518 | case M_ANY: | |
519 | case M_USER: | |
4f6b1a05 | 520 | argv[13] = "USER"; |
521 | status = wrap_mr_query("update_host", 17, argv, NULL, NULL); | |
80e8aa14 | 522 | if (owner->type != M_ANY || status != MR_USER) |
523 | break; | |
524 | ||
525 | case M_LIST: | |
4f6b1a05 | 526 | argv[13] = "LIST"; |
527 | status = wrap_mr_query("update_host", 17, argv, NULL, NULL); | |
80e8aa14 | 528 | break; |
529 | ||
530 | case M_KERBEROS: | |
4f6b1a05 | 531 | argv[13] = "KERBEROS"; |
532 | status = mrcl_validate_kerberos_member(argv[14], &argv[14]); | |
df183ce8 | 533 | if (mrcl_get_message()) |
534 | mrcl_com_err(whoami); | |
138b81d7 | 535 | if (status == MRCL_REJECT) |
536 | exit(1); | |
4f6b1a05 | 537 | status = wrap_mr_query("update_host", 17, argv, NULL, NULL); |
80e8aa14 | 538 | break; |
539 | ||
540 | case M_NONE: | |
4f6b1a05 | 541 | argv[13] = "NONE"; |
542 | status = wrap_mr_query("update_host", 17, argv, NULL, NULL); | |
80e8aa14 | 543 | break; |
544 | } | |
545 | } | |
546 | else | |
4f6b1a05 | 547 | status = wrap_mr_query("update_host", 17, argv, NULL, NULL); |
80e8aa14 | 548 | |
549 | if (status) | |
550 | com_err(whoami, status, "while updating host."); | |
551 | else if (newname) | |
552 | hostname = newname; | |
553 | } | |
554 | ||
555 | /* create aliases if necessary */ | |
556 | if (alias_add_queue) { | |
557 | struct string_list *q = alias_add_queue; | |
558 | ||
559 | while(q) { | |
560 | char *alias = q->string; | |
561 | char *args[2]; | |
562 | ||
5aa7fdfd | 563 | args[0] = partial_canonicalize_hostname(strdup(alias)); |
80e8aa14 | 564 | args[1] = canonicalize_hostname(strdup(hostname)); |
565 | status = wrap_mr_query("add_hostalias", 2, args, NULL, NULL); | |
566 | if (status) { | |
567 | com_err(whoami, status, "while adding host alias"); | |
568 | exit(1); | |
569 | } | |
570 | ||
571 | q = q->next; | |
572 | } | |
573 | } | |
574 | ||
575 | /* delete aliases if necessary */ | |
576 | if (alias_remove_queue) { | |
577 | struct string_list *q = alias_remove_queue; | |
578 | ||
579 | while(q) { | |
580 | char *alias = q->string; | |
581 | char *args[2]; | |
582 | ||
5aa7fdfd | 583 | args[0] = partial_canonicalize_hostname(strdup(alias)); |
80e8aa14 | 584 | args[1] = canonicalize_hostname(strdup(hostname)); |
585 | status = wrap_mr_query("delete_hostalias", 2, args, NULL, NULL); | |
586 | if (status) { | |
587 | com_err(whoami, status, "while deleting host alias"); | |
588 | exit(1); | |
589 | } | |
590 | ||
591 | q = q->next; | |
592 | } | |
593 | } | |
594 | ||
595 | /* create cluster mappings */ | |
596 | if (map_add_queue) { | |
597 | struct string_list *q = map_add_queue; | |
598 | ||
599 | while(q) { | |
600 | char *clustername = q->string; | |
601 | char *args[2]; | |
602 | ||
603 | args[0] = canonicalize_hostname(strdup(hostname)); | |
604 | args[1] = clustername; | |
605 | status = wrap_mr_query("add_machine_to_cluster", 2, args, NULL, NULL); | |
606 | if (status) { | |
607 | com_err(whoami, status, "while adding cluster mapping"); | |
608 | exit(1); | |
609 | } | |
610 | ||
611 | q = q->next; | |
612 | } | |
613 | } | |
614 | ||
615 | /* delete cluster mappings */ | |
616 | if (map_remove_queue) { | |
617 | struct string_list *q = map_remove_queue; | |
618 | ||
619 | while(q) { | |
620 | char *clustername = q->string; | |
621 | char *args[2]; | |
622 | ||
623 | args[0] = canonicalize_hostname(strdup(hostname)); | |
624 | args[1] = clustername; | |
625 | status = wrap_mr_query("delete_machine_from_cluster", 2, args, | |
626 | NULL, NULL); | |
627 | if (status) { | |
628 | com_err(whoami, status, "while deleting cluster mapping"); | |
629 | exit(1); | |
630 | } | |
631 | ||
632 | q = q->next; | |
633 | } | |
634 | } | |
635 | ||
9cd2d193 | 636 | /* add container mappings */ |
637 | if (container_add_queue) { | |
638 | struct string_list *q = container_add_queue; | |
639 | ||
640 | while (q) { | |
641 | char *containername = q->string; | |
642 | char *args[2]; | |
643 | ||
644 | args[0] = canonicalize_hostname(strdup(hostname)); | |
645 | args[1] = containername; | |
646 | status = wrap_mr_query("add_machine_to_container", 2, args, | |
647 | NULL, NULL); | |
648 | ||
649 | if (status) { | |
650 | com_err(whoami, status, "while adding container mapping"); | |
651 | exit(1); | |
652 | } | |
653 | ||
654 | q = q->next; | |
655 | } | |
656 | } | |
657 | ||
658 | /* delete container mappings */ | |
659 | if (container_remove_queue) { | |
660 | struct string_list *q = container_remove_queue; | |
661 | ||
662 | while (q) { | |
663 | char *containername = q->string; | |
664 | char *args[2]; | |
665 | ||
666 | args[0] = canonicalize_hostname(strdup(hostname)); | |
667 | args[1] = containername; | |
668 | status = wrap_mr_query("delete_machine_from_container", 2, args, | |
669 | NULL, NULL); | |
670 | ||
671 | if (status) { | |
672 | com_err(whoami, status, "while deleting container mapping"); | |
673 | exit(1); | |
674 | } | |
675 | ||
676 | q = q->next; | |
677 | } | |
678 | } | |
679 | ||
80e8aa14 | 680 | /* display list info if requested to */ |
681 | if (info_flag) { | |
682 | struct mqelem *elem = NULL; | |
683 | char *args[5]; | |
684 | char *argv[30]; | |
685 | ||
686 | args[0] = canonicalize_hostname(strdup(hostname)); | |
687 | args[1] = args[2] = args[3] = "*"; | |
688 | status = wrap_mr_query("get_host", 4, args, store_host_info, argv); | |
76ad7dd9 | 689 | |
690 | /* We might be looking for an alias of a deleted host. */ | |
691 | if (status && status == MR_NO_MATCH) { | |
692 | status = wrap_mr_query("get_hostalias", 2, args, store_host_info, argv); | |
693 | if (!status) { | |
694 | args[0] = strdup(argv[1]); | |
695 | status = wrap_mr_query("get_host", 4, args, store_host_info, argv); | |
696 | } | |
697 | } | |
698 | ||
80e8aa14 | 699 | if (status) { |
700 | com_err(whoami, status, "while getting host information"); | |
701 | exit(1); | |
702 | } | |
76ad7dd9 | 703 | |
7b6a099a | 704 | if (unformatted_flag) |
705 | show_host_info_unformatted(argv); | |
706 | else | |
707 | show_host_info(argv); | |
4f6b1a05 | 708 | args[0] = argv[M_SUBNET]; |
709 | status = wrap_mr_query("get_subnet", 1, args, store_host_info, argv); | |
710 | if (status) | |
711 | com_err(whoami, status, "while getting subnet information"); | |
79f30489 | 712 | if (atoi(argv[SN_STATUS]) == SNET_STATUS_PRIVATE_10MBPS || |
4425deab | 713 | atoi(argv[SN_STATUS]) == SNET_STATUS_PRIVATE_100MBPS || |
714 | atoi(argv[SN_STATUS]) == SNET_STATUS_PRIVATE_1000MBPS) | |
4f6b1a05 | 715 | { |
716 | fprintf(stderr, "\nWarning: This host is on a private subnet.\n"); | |
9632ee31 | 717 | fprintf(stderr, "Billing information shown is superseded by billing information for the subnet.\n"); |
4f6b1a05 | 718 | } |
80e8aa14 | 719 | } |
720 | ||
721 | /* list cluster mappings if needed */ | |
722 | if (list_map_flag) { | |
723 | char *args[3]; | |
724 | ||
725 | args[0] = canonicalize_hostname(strdup(hostname)); | |
726 | args[1] = "*"; | |
727 | status = wrap_mr_query("get_machine_to_cluster_map", 2, args, | |
728 | show_machine_in_cluster, NULL); | |
729 | if (status) | |
730 | if (status != MR_NO_MATCH) { | |
731 | com_err(whoami, status, "while getting cluster mappings"); | |
732 | exit(1); | |
733 | } | |
734 | } | |
735 | ||
9cd2d193 | 736 | /* list container mappings if needed */ |
737 | if (list_container_flag) { | |
738 | char *argv[1]; | |
739 | ||
740 | argv[0] = canonicalize_hostname(strdup(hostname)); | |
741 | status = wrap_mr_query("get_machine_to_container_map", 1, argv, | |
742 | show_machine_in_container, NULL); | |
743 | ||
744 | if (status) | |
745 | if (status != MR_NO_MATCH) { | |
746 | com_err(whoami, status, "while getting container mappings"); | |
747 | exit(1); | |
748 | } | |
749 | } | |
750 | ||
80e8aa14 | 751 | if (delete_flag) { |
752 | char *argv[1]; | |
753 | ||
754 | argv[0] = canonicalize_hostname(strdup(hostname)); | |
755 | status = wrap_mr_query("delete_host", 1, argv, NULL, NULL); | |
756 | if (status) { | |
757 | com_err(whoami, status, "while deleting host"); | |
758 | exit(1); | |
759 | } | |
760 | } | |
761 | ||
762 | /* We're done! */ | |
763 | mr_disconnect(); | |
764 | exit(success ? 0 : 1); | |
765 | } | |
766 | ||
767 | void usage(char **argv) | |
768 | { | |
533bacb3 | 769 | #define USAGE_OPTIONS_FORMAT " %-39s%s\n" |
80e8aa14 | 770 | fprintf(stderr, "Usage: %s hostname [options]\n", argv[0]); |
771 | fprintf(stderr, "Options are\n"); | |
533bacb3 | 772 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-C | -create", |
80e8aa14 | 773 | "-O | -owner owner"); |
533bacb3 | 774 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-D | -delete", |
80e8aa14 | 775 | "-S | -status status"); |
533bacb3 | 776 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-R | -rename newname", |
80e8aa14 | 777 | "-V | -vendor vendor"); |
533bacb3 | 778 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-a | -addalias alias", |
80e8aa14 | 779 | "-M | -model model"); |
533bacb3 | 780 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-d | -deletealias alias", |
80e8aa14 | 781 | "-L | -location location"); |
533bacb3 | 782 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-i | -info", |
80e8aa14 | 783 | "-o | -os os"); |
533bacb3 | 784 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-oc | -opcmt op_cmt", |
80e8aa14 | 785 | "-c | -contact contact"); |
533bacb3 | 786 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-ac | -admcmt adm_cmt", |
080e5e2c | 787 | "-bc | -billingcontact billing_contact"); |
4f6b1a05 | 788 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-an | -accountnumber account_number", "-A | -address address"); |
789 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-N | -network network", | |
790 | "-am | -addmap cluster"); | |
791 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dm | deletemap cluster", | |
792 | "-acn | -addcontainer container"); | |
793 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-dcn | -deletecontainer container", | |
794 | "-lm | -listmap"); | |
795 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-lcn | -listcontainer", | |
796 | "-u | -unformatted"); | |
797 | fprintf(stderr, USAGE_OPTIONS_FORMAT, "-v | -verbose", | |
798 | "-n | -noauth"); | |
799 | fprintf(stderr, " %-39s\n" , "-db | -database host[:port]"); | |
80e8aa14 | 800 | exit(1); |
801 | } | |
802 | ||
803 | /* Show alias information */ | |
804 | ||
805 | static int show_has_aliases; | |
806 | ||
807 | int show_alias_info(int argc, char **argv, void *hint) | |
808 | { | |
809 | if(!show_has_aliases++) | |
810 | printf("Aliases: %s", argv[0]); | |
811 | else | |
812 | printf(", %s", argv[0]); | |
813 | ||
814 | return MR_CONT; | |
815 | } | |
816 | ||
7b6a099a | 817 | int show_alias_info_unformatted(int argc, char **argv, void *hint) |
818 | { | |
819 | if(!show_has_aliases++) | |
820 | printf("Alias: %s", argv[0]); | |
821 | else | |
822 | printf(", %s", argv[0]); | |
823 | ||
824 | return MR_CONT; | |
825 | } | |
826 | ||
80e8aa14 | 827 | static char *states[] = { |
828 | "Reserved (0)", | |
829 | "Active (1)", | |
830 | "None (2)", | |
831 | "Deleted (3)" | |
832 | }; | |
833 | ||
834 | static char *MacState(int state) | |
835 | { | |
836 | static char buf[BUFSIZ]; | |
837 | ||
838 | if (state < 0 || state > 3) | |
839 | { | |
840 | sprintf(buf, "Unknown (%d)", state); | |
841 | return buf; | |
842 | } | |
843 | return states[state]; | |
844 | } | |
845 | ||
846 | /* Retrieve information about a host */ | |
847 | ||
848 | int store_host_info(int argc, char **argv, void *hint) | |
849 | { | |
850 | int i; | |
851 | char **nargv = hint; | |
852 | ||
853 | for(i=0; i<argc; i++) | |
854 | nargv[i] = strdup(argv[i]); | |
855 | ||
856 | return MR_CONT; | |
857 | } | |
858 | ||
859 | void show_host_info(char **argv) | |
860 | { | |
861 | char tbuf[256]; | |
862 | char *args[3]; | |
863 | struct mqelem *elem = NULL; | |
864 | int stat; | |
865 | ||
866 | printf("Machine: %s\n", argv[M_NAME]); | |
867 | args[0] = "*"; | |
868 | args[1] = argv[M_NAME]; | |
869 | show_has_aliases = 0; | |
870 | stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info, &elem); | |
871 | printf("\n"); | |
872 | if (stat) { | |
873 | if (stat != MR_NO_MATCH) | |
874 | com_err(whoami, stat, "while getting aliases"); | |
875 | } else { | |
876 | printf("\n"); | |
877 | } | |
878 | sprintf(tbuf, "%s %s", argv[M_OWNER_TYPE], | |
879 | strcmp(argv[M_OWNER_TYPE], "NONE") ? argv[M_OWNER_NAME] : ""); | |
880 | printf("Address: %-16s Network: %-16s\n", | |
881 | argv[M_ADDR], argv[M_SUBNET]); | |
882 | printf("Owner: %-16s Use data: %s\n", tbuf, argv[M_INUSE]); | |
883 | printf("Status: %-16s Changed: %s\n", | |
884 | MacState(atoi(argv[M_STAT])), argv[M_STAT_CHNG]); | |
885 | printf("\n"); | |
080e5e2c | 886 | printf("Vendor: %-16s Location: %s\n", argv[M_VENDOR], |
887 | argv[M_LOC]); | |
888 | printf("Model: %-16s Contact: %s\n", argv[M_MODEL], | |
889 | argv[M_CONTACT]); | |
890 | printf("OS: %-16s Billing Contact: %s\n", argv[M_OS], | |
891 | argv[M_BILL_CONTACT]); | |
4f6b1a05 | 892 | printf("Opt: %-16s Account Number: %s\n", argv[M_USE], |
893 | argv[M_ACCT_NUMBER]); | |
80e8aa14 | 894 | printf("\nAdm cmt: %s\n", argv[M_ACOMMENT]); |
895 | printf("Op cmt: %s\n", argv[M_OCOMMENT]); | |
896 | printf("\n"); | |
897 | printf("Created by %s on %s\n", argv[M_CREATOR], argv[M_CREATED]); | |
898 | printf("Last mod by %s at %s with %s.\n", argv[M_MODBY], argv[M_MODTIME], argv[M_MODWITH]); | |
899 | } | |
900 | ||
7b6a099a | 901 | void show_host_info_unformatted(char **argv) |
902 | { | |
7b6a099a | 903 | char *args[3]; |
904 | struct mqelem *elem = NULL; | |
905 | int stat; | |
906 | ||
907 | printf("Machine: %s\n", argv[M_NAME]); | |
908 | args[0] = "*"; | |
909 | args[1] = argv[M_NAME]; | |
910 | show_has_aliases = 0; | |
911 | stat = wrap_mr_query("get_hostalias", 2, args, show_alias_info_unformatted, | |
912 | &elem); | |
913 | if (stat && stat != MR_NO_MATCH) | |
914 | com_err(whoami, stat, "while getting aliases"); | |
915 | else | |
916 | printf("\n"); | |
917 | printf("Address: %s\n", argv[M_ADDR]); | |
918 | printf("Network: %s\n", argv[M_SUBNET]); | |
919 | printf("Owner Type: %s\n", argv[M_OWNER_TYPE]); | |
920 | printf("Owner: %s\n", argv[M_OWNER_NAME]); | |
921 | printf("Status: %s\n", MacState(atoi(argv[M_STAT]))); | |
922 | printf("Changed: %s\n", argv[M_STAT_CHNG]); | |
923 | printf("Use data: %s\n", argv[M_INUSE]); | |
924 | printf("Vendor: %s\n", argv[M_VENDOR]); | |
925 | printf("Model: %s\n", argv[M_MODEL]); | |
926 | printf("OS: %s\n", argv[M_OS]); | |
927 | printf("Location: %s\n", argv[M_LOC]); | |
928 | printf("Contact: %s\n", argv[M_CONTACT]); | |
929 | printf("Billing Contact: %s\n", argv[M_BILL_CONTACT]); | |
a86f57e2 | 930 | printf("Account Number: %s\n", argv[M_ACCT_NUMBER]); |
7b6a099a | 931 | printf("Opt: %s\n", argv[M_USE]); |
932 | printf("Adm cmt: %s\n", argv[M_ACOMMENT]); | |
933 | printf("Op cmt: %s\n", argv[M_OCOMMENT]); | |
934 | printf("Created by: %s\n", argv[M_CREATOR]); | |
935 | printf("Created on: %s\n", argv[M_CREATED]); | |
936 | printf("Last mod by: %s\n", argv[M_MODBY]); | |
937 | printf("Last mod on: %s\n", argv[M_MODTIME]); | |
938 | printf("Last mod with: %s\n", argv[M_MODWITH]); | |
939 | } | |
940 | ||
80e8aa14 | 941 | int show_machine_in_cluster(int argc, char **argv, void *hint) |
942 | { | |
943 | printf("Machine: %-30s Cluster: %-30s\n", argv[0], argv[1]); | |
944 | ||
945 | return MR_CONT; | |
946 | } | |
947 | ||
9cd2d193 | 948 | int show_machine_in_container(int argc, char **argv, void *hint) |
949 | { | |
950 | printf("Machine: %-30s Container: %-25s\n", argv[0], argv[1]); | |
951 | ||
952 | return MR_CONT; | |
953 | } | |
954 | ||
80e8aa14 | 955 | /* Parse a line of input, fetching a member. NULL is returned if a member |
956 | * is not found. ';' is a comment character. | |
957 | */ | |
958 | ||
959 | struct owner_type *parse_member(char *s) | |
960 | { | |
961 | struct owner_type *m; | |
962 | char *p, *lastchar; | |
963 | ||
964 | while (*s && isspace(*s)) | |
965 | s++; | |
966 | lastchar = p = s; | |
967 | while (*p && *p != '\n' && *p != ';') | |
968 | { | |
969 | if (isprint(*p) && !isspace(*p)) | |
970 | lastchar = p++; | |
971 | else | |
972 | p++; | |
973 | } | |
974 | lastchar++; | |
975 | *lastchar = '\0'; | |
976 | if (p == s || strlen(s) == 0) | |
977 | return NULL; | |
978 | ||
979 | if (!(m = malloc(sizeof(struct owner_type)))) | |
980 | return NULL; | |
981 | ||
982 | if ((p = strchr(s, ':'))) | |
983 | { | |
984 | *p = '\0'; | |
985 | m->name = ++p; | |
986 | if (!strcasecmp("user", s)) | |
987 | m->type = M_USER; | |
988 | else if (!strcasecmp("list", s)) | |
989 | m->type = M_LIST; | |
80e8aa14 | 990 | else if (!strcasecmp("kerberos", s)) |
991 | m->type = M_KERBEROS; | |
992 | else if (!strcasecmp("none", s)) | |
993 | m->type = M_NONE; | |
994 | else | |
995 | { | |
996 | m->type = M_ANY; | |
997 | *(--p) = ':'; | |
998 | m->name = s; | |
999 | } | |
1000 | m->name = strdup(m->name); | |
1001 | } | |
1002 | else | |
1003 | { | |
1004 | m->name = strdup(s); | |
1005 | m->type = strcasecmp(s, "none") ? M_ANY : M_NONE; | |
1006 | } | |
1007 | return m; | |
1008 | } | |
1009 | ||
1010 | struct string_list *add_to_string_list(struct string_list *old_list, char *s) { | |
1011 | struct string_list *new_list; | |
1012 | ||
1013 | new_list = (struct string_list *)malloc(sizeof(struct string_list *)); | |
1014 | new_list->next = old_list; | |
1015 | new_list->string = s; | |
1016 | ||
1017 | return new_list; | |
1018 | } | |
1019 | ||
1020 | int wrap_mr_query(char *handle, int argc, char **argv, | |
1021 | int (*callback)(int, char **, void *), void *callarg) { | |
1022 | if (verbose) | |
1023 | print_query(handle, argc, argv); | |
1024 | ||
1025 | return mr_query(handle, argc, argv, callback, callarg); | |
1026 | } | |
1027 | ||
1028 | void print_query(char *query_name, int argc, char **argv) { | |
1029 | int cnt; | |
1030 | ||
1031 | printf("qy %s", query_name); | |
1032 | for(cnt=0; cnt<argc; cnt++) | |
1033 | printf(" <%s>", argv[cnt]); | |
1034 | printf("\n"); | |
1035 | } |