4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
23 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #include <sys/types.h>
28 #include <sys/socket.h>
30 #include <netinet/in.h>
40 extern int optind
, optopt
, opterr
;
43 typedef struct hc_export_arg
{
47 /* Maximum columns for printing hc output. */
48 #define SHOW_HC_COLS 80
50 /* OFMT call back to print out a hc server result field. */
51 static boolean_t
print_hc_result(ofmt_arg_t
*, char *, uint_t
);
53 /* ID to indicate which field to be printed. */
55 hc_of_rname
, hc_of_hname
, hc_of_sname
, hc_of_status
, hc_of_fail_cnt
,
56 hc_of_lasttime
, hc_of_nexttime
, hc_of_rtt
,
57 hc_of_name
, hc_of_timeout
, hc_of_count
, hc_of_interval
, hc_of_def_ping
,
62 * Fields of a hc server result. The sum of all fields' width is SHOW_HC_COLS.
64 static ofmt_field_t hc_results
[] = {
65 {"RULENAME", 14, hc_of_rname
, print_hc_result
},
66 {"HCNAME", 14, hc_of_hname
, print_hc_result
},
67 {"SERVERID", 14, hc_of_sname
, print_hc_result
},
68 {"STATUS", 9, hc_of_status
, print_hc_result
},
69 {"FAIL", 5, hc_of_fail_cnt
, print_hc_result
},
70 {"LAST", 9, hc_of_lasttime
, print_hc_result
},
71 {"NEXT", 9, hc_of_nexttime
, print_hc_result
},
72 {"RTT", 6, hc_of_rtt
, print_hc_result
},
76 /* OFMT call back to print out a hc info field. */
77 static boolean_t
print_hc(ofmt_arg_t
*, char *, uint_t
);
80 * Fields of a hc info. The sume of all fields' width is SHOW_HC_COLS.
82 static ofmt_field_t hc_fields
[] = {
83 {"HCNAME", 14, hc_of_name
, print_hc
},
84 {"TIMEOUT", 8, hc_of_timeout
, print_hc
},
85 {"COUNT", 8, hc_of_count
, print_hc
},
86 {"INTERVAL", 9, hc_of_interval
, print_hc
},
87 {"DEF_PING", 9, hc_of_def_ping
, print_hc
},
88 {"TEST", 32, hc_of_test
, print_hc
},
93 print_hc(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
95 enum hc_print_id id
= of_arg
->ofmt_id
;
96 ilb_hc_info_t
*info
= (ilb_hc_info_t
*)of_arg
->ofmt_cbarg
;
100 (void) strlcpy(buf
, info
->hci_name
, bufsize
);
103 (void) snprintf(buf
, bufsize
, "%d", info
->hci_timeout
);
106 (void) snprintf(buf
, bufsize
, "%d", info
->hci_count
);
109 (void) snprintf(buf
, bufsize
, "%d", info
->hci_interval
);
112 (void) snprintf(buf
, bufsize
, "%c",
113 info
->hci_def_ping
? 'Y' : 'N');
116 (void) snprintf(buf
, bufsize
, "%s", info
->hci_test
);
122 /* Call back to ilb_walk_hc(). */
125 ilbadm_print_hc(ilb_handle_t h
, ilb_hc_info_t
*hc_info
, void *arg
)
127 ofmt_handle_t ofmt_h
= arg
;
129 ofmt_print(ofmt_h
, hc_info
);
130 return (ILB_STATUS_OK
);
134 * Print out health check objects given their name.
135 * Or print out all health check objects if no name given.
139 ilbadm_show_hc(int argc
, char *argv
[])
141 ilb_handle_t h
= ILB_INVALID_HANDLE
;
143 ofmt_handle_t ofmt_h
;
144 ofmt_status_t ofmt_ret
;
146 if ((ofmt_ret
= ofmt_open("all", hc_fields
, 0, SHOW_HC_COLS
,
147 &ofmt_h
)) != OFMT_SUCCESS
) {
148 char err_buf
[SHOW_HC_COLS
];
150 ilbadm_err(gettext("ofmt_open failed: %s"),
151 ofmt_strerror(ofmt_h
, ofmt_ret
, err_buf
, SHOW_HC_COLS
));
152 return (ILBADM_LIBERR
);
154 rclib
= ilb_open(&h
);
155 if (rclib
!= ILB_STATUS_OK
)
159 rclib
= ilb_walk_hc(h
, ilbadm_print_hc
, ofmt_h
);
161 ilb_hc_info_t hc_info
;
164 for (i
= 1; i
< argc
; i
++) {
165 rclib
= ilb_get_hc_info(h
, argv
[i
], &hc_info
);
166 if (rclib
== ILB_STATUS_OK
)
167 ofmt_print(ofmt_h
, &hc_info
);
175 if (h
!= ILB_INVALID_HANDLE
)
178 if (rclib
!= ILB_STATUS_OK
) {
179 ilbadm_err(ilb_errstr(rclib
));
180 return (ILBADM_LIBERR
);
187 print_hc_result(ofmt_arg_t
*of_arg
, char *buf
, uint_t bufsize
)
189 enum hc_print_id id
= of_arg
->ofmt_id
;
190 ilb_hc_srv_t
*srv
= (ilb_hc_srv_t
*)of_arg
->ofmt_cbarg
;
195 (void) strlcpy(buf
, srv
->hcs_rule_name
, bufsize
);
198 (void) strlcpy(buf
, srv
->hcs_hc_name
, bufsize
);
201 (void) strlcpy(buf
, srv
->hcs_ID
, bufsize
);
204 switch (srv
->hcs_status
) {
206 (void) strlcpy(buf
, "un-init", bufsize
);
208 case ILB_HCS_UNREACH
:
209 (void) strlcpy(buf
, "unreach", bufsize
);
212 (void) strlcpy(buf
, "alive", bufsize
);
215 (void) strlcpy(buf
, "dead", bufsize
);
217 case ILB_HCS_DISABLED
:
218 (void) strlcpy(buf
, "disabled", bufsize
);
223 (void) snprintf(buf
, bufsize
, "%u", srv
->hcs_fail_cnt
);
226 if (localtime_r(&srv
->hcs_lasttime
, &tv
) == NULL
)
228 (void) snprintf(buf
, bufsize
, "%02d:%02d:%02d", tv
.tm_hour
,
229 tv
.tm_min
, tv
.tm_sec
);
232 if (srv
->hcs_status
== ILB_HCS_DISABLED
)
234 if (localtime_r(&srv
->hcs_nexttime
, &tv
) == NULL
)
236 (void) snprintf(buf
, bufsize
, "%02d:%02d:%02d", tv
.tm_hour
,
237 tv
.tm_min
, tv
.tm_sec
);
240 (void) snprintf(buf
, bufsize
, "%u", srv
->hcs_rtt
);
246 /* Call back to ilbd_walk_hc_srvs(). */
249 ilbadm_print_hc_result(ilb_handle_t h
, ilb_hc_srv_t
*srv
, void *arg
)
251 ofmt_handle_t ofmt_h
= arg
;
253 ofmt_print(ofmt_h
, srv
);
254 return (ILB_STATUS_OK
);
258 * Output hc result of a specified rule or all rules.
261 ilbadm_show_hc_result(int argc
, char *argv
[])
263 ilb_handle_t h
= ILB_INVALID_HANDLE
;
264 ilb_status_t rclib
= ILB_STATUS_OK
;
266 ofmt_handle_t ofmt_h
;
267 ofmt_status_t ofmt_ret
;
269 /* ilbadm show-hc-result [rule-name] */
271 ilbadm_err(gettext("usage: ilbadm show-hc-result"
273 return (ILBADM_LIBERR
);
276 if ((ofmt_ret
= ofmt_open("all", hc_results
, 0, SHOW_HC_COLS
,
277 &ofmt_h
)) != OFMT_SUCCESS
) {
278 char err_buf
[SHOW_HC_COLS
];
280 ilbadm_err(gettext("ofmt_open failed: %s"),
281 ofmt_strerror(ofmt_h
, ofmt_ret
, err_buf
, SHOW_HC_COLS
));
282 return (ILBADM_LIBERR
);
285 rclib
= ilb_open(&h
);
286 if (rclib
!= ILB_STATUS_OK
)
289 /* If no rule name is given, show results for all rules. */
291 rclib
= ilb_walk_hc_srvs(h
, ilbadm_print_hc_result
, NULL
,
294 for (i
= 1; i
< argc
; i
++) {
295 rclib
= ilb_walk_hc_srvs(h
, ilbadm_print_hc_result
,
297 if (rclib
!= ILB_STATUS_OK
)
304 if (h
!= ILB_INVALID_HANDLE
)
307 if (rclib
!= ILB_STATUS_OK
) {
308 ilbadm_err(ilb_errstr(rclib
));
309 return (ILBADM_LIBERR
);
314 #define ILBADM_DEF_HC_COUNT 3
315 #define ILBADM_DEF_HC_INTERVAL 30 /* in sec */
316 #define ILBADM_DEF_HC_TIMEOUT 5 /* in sec */
318 static ilbadm_key_name_t hc_parse_keys
[] = {
319 {ILB_KEY_HC_TEST
, "hc-test", "hc-test"},
320 {ILB_KEY_HC_COUNT
, "hc-count", "hc-count"},
321 {ILB_KEY_HC_TIMEOUT
, "hc-timeout", "hc-tout"},
322 {ILB_KEY_HC_INTERVAL
, "hc-interval", "hc-intl"},
323 {ILB_KEY_BAD
, "", ""}
326 static ilbadm_status_t
327 ilbadm_hc_parse_arg(char *arg
, ilb_hc_info_t
*hc
)
331 /* set default value for count, interval, timeout */
332 hc
->hci_count
= ILBADM_DEF_HC_COUNT
;
333 hc
->hci_interval
= ILBADM_DEF_HC_INTERVAL
;
334 hc
->hci_timeout
= ILBADM_DEF_HC_TIMEOUT
;
335 hc
->hci_test
[0] = '\0';
337 ret
= i_parse_optstring(arg
, hc
, hc_parse_keys
, 0, NULL
);
338 if (ret
!= ILBADM_OK
&& ret
!= ILBADM_LIBERR
) {
339 ilbadm_err(ilbadm_errstr(ret
));
340 return (ILBADM_LIBERR
);
342 if (hc
->hci_test
[0] == '\0' && ret
!= ILBADM_LIBERR
) {
343 ilbadm_err("hc-test: missing");
344 return (ILBADM_LIBERR
);
351 ilbadm_create_hc(int argc
, char *argv
[])
353 ilb_handle_t h
= ILB_INVALID_HANDLE
;
354 ilb_hc_info_t hc_info
;
355 ilbadm_status_t ret
= ILBADM_OK
;
360 hc_info
.hci_def_ping
= B_TRUE
;
361 while ((c
= getopt(argc
, argv
, ":h:n")) != -1) {
363 ret
= ilbadm_hc_parse_arg(optarg
, &hc_info
);
364 if (ret
!= ILBADM_OK
)
366 } else if (c
== 'n') {
367 hc_info
.hci_def_ping
= B_FALSE
;
369 ilbadm_err(gettext("bad argument %c"), c
);
370 return (ILBADM_LIBERR
);
374 if (optind
>= argc
) {
375 ilbadm_err(gettext("usage: ilbadm"
376 " create-healthcheck [-n] -h"
377 " hc-test=val[,hc-timeout=val][,hc-count=va]"
378 "[,hc-interval=val] hc-name"));
379 return (ILBADM_FAIL
);
382 if (strlen(argv
[optind
]) > ILBD_NAMESZ
- 1) {
383 ilbadm_err(gettext("health check object name %s is too long - "
384 "must not exceed %d chars"), argv
[optind
],
386 return (ILBADM_FAIL
);
389 if (((strcasecmp(hc_info
.hci_test
, ILB_HC_STR_UDP
) == 0) ||
390 (strcasecmp(hc_info
.hci_test
, ILB_HC_STR_PING
) == 0)) &&
391 !(hc_info
.hci_def_ping
)) {
392 ilbadm_err(gettext("cannot disable default PING"
394 return (ILBADM_LIBERR
);
397 rclib
= ilb_open(&h
);
398 if (rclib
!= ILB_STATUS_OK
)
401 (void) strlcpy(hc_info
.hci_name
, argv
[optind
],
402 sizeof (hc_info
.hci_name
));
403 rclib
= ilb_create_hc(h
, &hc_info
);
405 if (h
!= ILB_INVALID_HANDLE
)
408 if (rclib
!= ILB_STATUS_OK
) {
409 ilbadm_err(ilb_errstr(rclib
));
416 ilbadm_destroy_hc(int argc
, char *argv
[])
418 ilb_handle_t h
= ILB_INVALID_HANDLE
;
420 ilbadm_status_t ret
= ILBADM_OK
;
424 ilbadm_err(gettext("usage: ilbadm"
425 " delete-healthcheck hc-name ..."));
426 return (ILBADM_LIBERR
);
429 rclib
= ilb_open(&h
);
430 if (rclib
!= ILB_STATUS_OK
)
433 for (i
= 1; i
< argc
; i
++) {
434 rclib
= ilb_destroy_hc(h
, argv
[i
]);
435 if (rclib
!= ILB_STATUS_OK
)
439 if (h
!= ILB_INVALID_HANDLE
)
442 if (rclib
!= ILB_STATUS_OK
) {
443 ilbadm_err(ilb_errstr(rclib
));
450 * Since this function is used by libilb function, it
451 * must return libilb errors
455 ilbadm_export_hcinfo(ilb_handle_t h
, ilb_hc_info_t
*hc_info
, void *arg
)
457 FILE *fp
= ((hc_export_arg_t
*)arg
)->fp
;
462 * a test name "PING" implies "no default ping", so we only
463 * print -n if the test is NOT "PING"
465 if (hc_info
->hci_def_ping
== B_FALSE
&&
466 strncasecmp(hc_info
->hci_test
, "PING", 5) != 0)
467 (void) fprintf(fp
, "create-healthcheck -n -h ");
469 (void) fprintf(fp
, "create-healthcheck -h ");
471 if (*hc_info
->hci_test
!= '\0') {
472 (void) fprintf(fp
, "hc-test=%s", hc_info
->hci_test
);
475 if (hc_info
->hci_timeout
!= 0) {
477 (void) fprintf(fp
, ",");
478 (void) fprintf(fp
, "hc-timeout=%d", hc_info
->hci_timeout
);
480 if (hc_info
->hci_count
!= 0) {
482 (void) fprintf(fp
, ",");
483 (void) fprintf(fp
, "hc-count=%d", hc_info
->hci_count
);
485 if (hc_info
->hci_interval
!= 0) {
487 (void) fprintf(fp
, ",");
488 (void) fprintf(fp
, "hc-interval=%d", hc_info
->hci_interval
);
492 * if any of the above writes fails, then, we assume, so will
493 * this one; so it's sufficient to test once
495 ret
= fprintf(fp
, " %s\n", hc_info
->hci_name
);
502 return (ILB_STATUS_WRITE
);
503 return (ILB_STATUS_OK
);
507 ilbadm_export_hc(ilb_handle_t h
, FILE *fp
)
510 ilbadm_status_t ret
= ILBADM_OK
;
514 rclib
= ilb_walk_hc(h
, ilbadm_export_hcinfo
, (void *)&arg
);
515 if (rclib
!= ILB_STATUS_OK
) {
516 ilbadm_err(ilb_errstr(rclib
));