From: Michal Rakowski Date: Tue, 8 Jun 2021 10:51:27 +0000 (+0200) Subject: Fix #6631 About bconsole command to show client's config X-Git-Tag: Release-11.3.2~457 X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=41e718c2da71c280f6f407a60ab00ba9e23450b7;p=thirdparty%2Fbacula.git Fix #6631 About bconsole command to show client's config Create '.status client resources' and '.status storage resources' commands to show main config of the Daemons. --- diff --git a/bacula/src/dird/protos.h b/bacula/src/dird/protos.h index 2848f7a40..d78859898 100644 --- a/bacula/src/dird/protos.h +++ b/bacula/src/dird/protos.h @@ -262,6 +262,7 @@ void free_rx(RESTORE_CTX *rx); /* ua_server.c */ void bsendmsg(void *ua_ctx, const char *fmt, ...); void berrormsg(void *ua_ctx, const char *fmt, ...); +void bmsg(UAContext *ua, const char *fmt, va_list arg_ptr); void bwarningmsg(void *ua_ctx, const char *fmt, ...); void binfomsg(void *ua_ctx, const char *fmt, ...); UAContext *new_ua_context(JCR *jcr); diff --git a/bacula/src/dird/ua_output.c b/bacula/src/dird/ua_output.c index 3db0cabb8..980c7b9a8 100644 --- a/bacula/src/dird/ua_output.c +++ b/bacula/src/dird/ua_output.c @@ -1223,95 +1223,6 @@ void prtit(void *ctx, const char *msg) if (ua) ua->send_msg("%s", msg); } -/* - * Format message and send to other end. - - * If the UA_sock is NULL, it means that there is no user - * agent, so we are being called from Bacula core. In - * that case direct the messages to the Job. - */ -#ifdef HAVE_VA_COPY -void bmsg(UAContext *ua, const char *fmt, va_list arg_ptr) -{ - BSOCK *bs = ua->UA_sock; - int maxlen, len; - POOLMEM *msg = NULL; - va_list ap; - - if (bs) { - msg = bs->msg; - } - if (!msg) { - msg = get_pool_memory(PM_EMSG); - } - -again: - maxlen = sizeof_pool_memory(msg) - 1; - va_copy(ap, arg_ptr); - len = bvsnprintf(msg, maxlen, fmt, ap); - va_end(ap); - if (len < 0 || len >= maxlen) { - msg = realloc_pool_memory(msg, maxlen + maxlen/2); - goto again; - } - - if (bs) { - bs->msg = msg; - bs->msglen = len; - bs->send(); - } else { /* No UA, send to Job */ - Jmsg(ua->jcr, M_INFO, 0, "%s", msg); - free_pool_memory(msg); - } - -} - -#else /* no va_copy() -- brain damaged version of variable arguments */ - -void bmsg(UAContext *ua, const char *fmt, va_list arg_ptr) -{ - BSOCK *bs = ua->UA_sock; - int maxlen, len; - POOLMEM *msg = NULL; - - if (bs) { - msg = bs->msg; - } - if (!msg) { - msg = get_memory(5000); - } - - maxlen = sizeof_pool_memory(msg) - 1; - if (maxlen < 4999) { - msg = realloc_pool_memory(msg, 5000); - maxlen = 4999; - } - len = bvsnprintf(msg, maxlen, fmt, arg_ptr); - if (len < 0 || len >= maxlen) { - pm_strcpy(msg, _("Message too long to display.\n")); - len = strlen(msg); - } - - if (bs) { - bs->msg = msg; - bs->msglen = len; - bs->send(); - } else { /* No UA, send to Job */ - Jmsg(ua->jcr, M_INFO, 0, "%s", msg); - free_pool_memory(msg); - } - -} -#endif - -void bsendmsg(void *ctx, const char *fmt, ...) -{ - va_list arg_ptr; - va_start(arg_ptr, fmt); - bmsg((UAContext *)ctx, fmt, arg_ptr); - va_end(arg_ptr); -} - /* * The following UA methods are mainly intended for GUI * programs diff --git a/bacula/src/dird/ua_server.c b/bacula/src/dird/ua_server.c index 17e18488b..aeb01e2ed 100644 --- a/bacula/src/dird/ua_server.c +++ b/bacula/src/dird/ua_server.c @@ -115,6 +115,95 @@ JCR *new_control_jcr(const char *base_name, int job_type) return jcr; } +/* + * Format message and send to other end. + + * If the UA_sock is NULL, it means that there is no user + * agent, so we are being called from Bacula core. In + * that case direct the messages to the Job. + */ +#ifdef HAVE_VA_COPY +void bmsg(UAContext *ua, const char *fmt, va_list arg_ptr) +{ + BSOCK *bs = ua->UA_sock; + int maxlen, len; + POOLMEM *msg = NULL; + va_list ap; + + if (bs) { + msg = bs->msg; + } + if (!msg) { + msg = get_pool_memory(PM_EMSG); + } + +again: + maxlen = sizeof_pool_memory(msg) - 1; + va_copy(ap, arg_ptr); + len = bvsnprintf(msg, maxlen, fmt, ap); + va_end(ap); + if (len < 0 || len >= maxlen) { + msg = realloc_pool_memory(msg, maxlen + maxlen/2); + goto again; + } + + if (bs) { + bs->msg = msg; + bs->msglen = len; + bs->send(); + } else { /* No UA, send to Job */ + Jmsg(ua->jcr, M_INFO, 0, "%s", msg); + free_pool_memory(msg); + } + +} + +#else /* no va_copy() -- brain damaged version of variable arguments */ + +void bmsg(UAContext *ua, const char *fmt, va_list arg_ptr) +{ + BSOCK *bs = ua->UA_sock; + int maxlen, len; + POOLMEM *msg = NULL; + + if (bs) { + msg = bs->msg; + } + if (!msg) { + msg = get_memory(5000); + } + + maxlen = sizeof_pool_memory(msg) - 1; + if (maxlen < 4999) { + msg = realloc_pool_memory(msg, 5000); + maxlen = 4999; + } + len = bvsnprintf(msg, maxlen, fmt, arg_ptr); + if (len < 0 || len >= maxlen) { + pm_strcpy(msg, _("Message too long to display.\n")); + len = strlen(msg); + } + + if (bs) { + bs->msg = msg; + bs->msglen = len; + bs->send(); + } else { /* No UA, send to Job */ + Jmsg(ua->jcr, M_INFO, 0, "%s", msg); + free_pool_memory(msg); + } + +} +#endif + +void bsendmsg(void *ctx, const char *fmt, ...) +{ + va_list arg_ptr; + va_start(arg_ptr, fmt); + bmsg((UAContext *)ctx, fmt, arg_ptr); + va_end(arg_ptr); +} + /* * Handle Director User Agent commands * diff --git a/bacula/src/dird/ua_status.c b/bacula/src/dird/ua_status.c index 96d02b81d..ac351f9bb 100644 --- a/bacula/src/dird/ua_status.c +++ b/bacula/src/dird/ua_status.c @@ -100,10 +100,13 @@ bool dot_status_cmd(UAContext *ua, const char *cmd) } } else if (strcasecmp(ua->argk[1], "client") == 0) { client = get_client_resource(ua, JT_BACKUP_RESTORE); - if (client) { - Dmsg2(200, "Client=%s arg=%s\n", client->name(), NPRT(ua->argk[2])); - do_client_status(ua, client, ua->argk[2]); + if (!client) { + ua->send_msg("1900 Bad 'status client' command, invalid client specified.\n"); + return false; } + + Dmsg2(200, "Client=%s arg=%s\n", client->name(), NPRT(ua->argk[2])); + do_client_status(ua, client, ua->argk[2]); } else if (strcasecmp(ua->argk[1], "storage") == 0) { if (!get_storage_resource(ua, &ustore, false /*no default*/, true/*unique*/)) { ua->send_msg("1900 Bad .status command, wrong argument.\n"); @@ -649,7 +652,10 @@ static void do_client_status(UAContext *ua, CLIENT *client, char *cmd) Dmsg0(20, _("Connected to file daemon\n")); fd = ua->jcr->file_bsock; if (cmd) { - if (strcasecmp(cmd, "collector") == 0 && (i = find_arg_with_value(ua, "collector")) > 0){ + if (strcasecmp(cmd, "resources") == 0) { + Mmsg(buf, ".status resources api=%d api_opts=%s", ua->api, ua->api_opts); + fd->fsend(buf.c_str()); + } else if (strcasecmp(cmd, "collector") == 0 && (i = find_arg_with_value(ua, "collector")) > 0){ Mmsg(buf, "%s", ua->argv[i]); bash_spaces(buf.c_str()); fd->fsend(".status %s=%s api=%d api_opts=%s", cmd, buf.c_str(), ua->api, ua->api_opts); diff --git a/bacula/src/filed/filed_conf.c b/bacula/src/filed/filed_conf.c index 0fd0dcd15..f7a8559a3 100644 --- a/bacula/src/filed/filed_conf.c +++ b/bacula/src/filed/filed_conf.c @@ -41,6 +41,7 @@ #include "bacula.h" #include "filed.h" +#include "lib/status.h" /* Define the first and last resource ID record * types. Note, these should be unique for each @@ -278,14 +279,70 @@ void store_digest_type(LEX *lc, RES_ITEM *item, int index, int pass) set_bit(index, res_all.hdr.item_present); } -/* Dump contents of resource */ +/* Dump Client/FileDaemon resource */ +static void dump_client_resource(CLIENT *client, void sendit(const char *msg, int len, STATUS_PKT *sp), STATUS_PKT *sp) +{ + OutputWriter ow(sp->api_opts); + POOL_MEM tmp; + char *p; + + ow.start_group("resource"); + + ow.get_output(OT_START_OBJ, + OT_STRING, "Name", client->hdr.name, + OT_STRING, "WorkingDirectory", client->working_directory, + OT_STRING, "PidDirectory", client->pid_directory, + OT_STRING, "SubsysDirectory", client->subsys_directory, + OT_STRING, "ScriptsDirectory", client->scripts_directory, + OT_STRING, "PluginDirectory", client->plugin_directory, +#if BEEF + OT_BOOL, "FIPSRequire", client->require_fips, +#endif + OT_INT64, "HeartbeatInterval", client->heartbeat_interval, + OT_INT32, "MaximumConcurrentJobs", client->MaxConcurrentJobs, + OT_INT, "FDPort", get_first_port_host_order(client->FDaddrs), + OT_STRING, "FDAddress", get_first_address(client->FDaddrs, tmp.c_str(), PM_MESSAGE), + OT_INT64, "SDConnectTimeout", client->SDConnectTimeout, + OT_INT32, "MaximumNetworkBufferSize", client->max_network_buffer_size, + OT_INT64, "MaximumBandwidthPerJob", client->max_bandwidth_per_job, + OT_BOOL, "CommCommpression", client->comm_compression, + OT_ALIST_STR, "DisableCommand", client->disable_cmds, + OT_BOOL, "TLSEnable", client->tls_enable, + OT_BOOL, "TLSPSKEnable", client->tls_psk_enable, + OT_BOOL, "TLSRequire", client->tls_require, + OT_BOOL, "TLSAuthenticate", client->tls_authenticate, +#ifdef DATA_ENCRYTION + OT_BOOL, "PKISignatures", client->pki_sign, + OT_BOOL, "PKIEncrytption", client->pki_encrypt, +#endif + OT_END_OBJ, + OT_END); + + p = ow.end_group("resource"); + sendit(p, strlen(p), sp); +} + +/* In order to link with libbaccfg + * Empty method is here just be able to link with libbaccfg (see overload in @parse_conf.h). + * FileDaemon should use overloaded one, see methodb below. + * TODO this should be removed as soon as Director's dump_resource() is updated to work + * with STATUS_PKT. + * */ void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, ...), void *sock) +{ + /**** NOT USED ****/ +} + +/* Dump contents of a resource. */ +void dump_resource(int type, RES *ares, void sendit(const char *msg, int len, STATUS_PKT *sp), STATUS_PKT *sp) { URES *res = (URES *)ares; - int recurse = 1; + int recurse = 1, len; + POOL_MEM msg(PM_MESSAGE); if (res == NULL) { - sendit(sock, "No record for %d %s\n", type, res_to_str(type)); + len = Mmsg (msg, "No record for %d %s\n", type, res_to_str(type)); + sendit(msg.c_str(), len, sp); return; } if (type < 0) { /* no recursion */ @@ -294,40 +351,51 @@ void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, } switch (type) { case R_CONSOLE: - sendit(sock, "Console: name=%s password=%s\n", ares->name, + len = Mmsg(msg, "Console: name=%s password=%s\n", ares->name, res->res_cons.dirinfo.password); + sendit(msg.c_str(), len, sp); break; case R_DIRECTOR: - sendit(sock, "Director: name=%s password=%s\n", ares->name, + len = Mmsg(msg, "Director: name=%s password=%s\n", ares->name, res->res_dir.dirinfo.password); + sendit(msg.c_str(), len, sp); break; case R_CLIENT: - sendit(sock, "Client: name=%s FDport=%d\n", ares->name, - get_first_port_host_order(res->res_client.FDaddrs)); - break; + { + CLIENT *client = (CLIENT *)ares; + dump_client_resource(client, sendit, sp); + break; + } case R_MSGS: - sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name); - if (res->res_msgs.mail_cmd) - sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd); - if (res->res_msgs.operator_cmd) - sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd); + len = Mmsg(msg, "Messages: name=%s\n", res->res_msgs.hdr.name); + sendit(msg.c_str(), len, sp); + if (res->res_msgs.mail_cmd) { + len = Mmsg(msg, " mailcmd=%s\n", res->res_msgs.mail_cmd); + sendit(msg.c_str(), len, sp); + } + if (res->res_msgs.operator_cmd) { + len = Mmsg(msg, " opcmd=%s\n", res->res_msgs.operator_cmd); + sendit(msg.c_str(), len, sp); + } break; case R_COLLECTOR: - dump_collector_resource(res->res_collector, sendit, sock); + dump_collector_resource(res->res_collector, sendit, sp); break; case R_SCHEDULE: if (res->res_sched.run) { int i; RUNRES *run = res->res_sched.run; char buf[1000], num[30]; - sendit(sock, _("Schedule: Name=%s Enabled=%d\n"), - res->res_sched.hdr.name, res->res_sched.is_enabled()); + len = Mmsg(msg, "Schedule: Name=%s Enabled=%d\n", + res->res_sched.hdr.name, res->res_sched.is_enabled()); + sendit(msg.c_str(), len, sp); if (!run) { break; } next_run: if (run->MaxConnectTime) { - sendit(sock, _(" MaxConnectTime=%u\n"), run->MaxConnectTime); + len = Mmsg(msg, " MaxConnectTime=%u\n", run->MaxConnectTime); + sendit(msg.c_str(), len, sp); } bstrncpy(buf, _(" hour="), sizeof(buf)); for (i=0; i<24; i++) { @@ -337,7 +405,7 @@ next_run: } } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(buf, strlen(buf), sp); bstrncpy(buf, _(" mday="), sizeof(buf)); for (i=0; i<32; i++) { if (bit_is_set(i, run->mday)) { @@ -346,7 +414,7 @@ next_run: } } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(buf, strlen(buf), sp); bstrncpy(buf, _(" month="), sizeof(buf)); for (i=0; i<12; i++) { if (bit_is_set(i, run->month)) { @@ -355,7 +423,7 @@ next_run: } } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(buf, strlen(buf), sp); bstrncpy(buf, _(" wday="), sizeof(buf)); for (i=0; i<7; i++) { if (bit_is_set(i, run->wday)) { @@ -364,7 +432,7 @@ next_run: } } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(buf, strlen(buf), sp); bstrncpy(buf, _(" wom="), sizeof(buf)); for (i=0; i<6; i++) { if (bit_is_set(i, run->wom)) { @@ -373,7 +441,7 @@ next_run: } } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); + sendit(buf, strlen(buf), sp); bstrncpy(buf, _(" woy="), sizeof(buf)); for (i=0; i<54; i++) { if (bit_is_set(i, run->woy)) { @@ -382,24 +450,27 @@ next_run: } } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); - sendit(sock, _(" mins=%d\n"), run->minute); + sendit(buf, strlen(buf), sp); + len = Mmsg(msg, " mins=%d\n", run->minute); + sendit(msg.c_str(), len, sp); /* If another Run record is chained in, go print it */ if (run->next) { run = run->next; goto next_run; } } else { - sendit(sock, _("Schedule: name=%s\n"), res->res_sched.hdr.name); + len = Mmsg(msg, "Schedule: name=%s\n", res->res_sched.hdr.name); + sendit(msg.c_str(), len, sp); } break; default: - sendit(sock, "Unknown resource type %d\n", type); + len = Mmsg(msg, "Unknown resource type %d\n", type); + sendit(msg.c_str(), len, sp); } ares = GetNextRes(type, ares); if (recurse && ares) { - dump_resource(type, ares, sendit, sock); + dump_resource(type, ares, sendit, sp); } } diff --git a/bacula/src/filed/status.c b/bacula/src/filed/status.c index 73ca49b6f..b08335487 100644 --- a/bacula/src/filed/status.c +++ b/bacula/src/filed/status.c @@ -34,6 +34,7 @@ extern bool GetWindowsVersionString(char *buf, int maxsiz); static void list_running_jobs(STATUS_PKT *sp); static void list_status_header(STATUS_PKT *sp); static void list_collectors_status(STATUS_PKT *sp, char *collname); +static void show_config(STATUS_PKT *sp); static void api_collectors_status(STATUS_PKT *sp, char *collname); /* Static variables */ @@ -563,6 +564,9 @@ int qstatus_cmd(JCR *jcr) } else if (strcasecmp(cmd, "statistics") == 0) { sp.api = MAX(sp.api, 1); list_collectors_status(&sp, collname); + } else if (strcasecmp(cmd, "resources") == 0) { + sp.api = MAX(sp.api, 1); + show_config(&sp); } else { pm_strcpy(&jcr->errmsg, dir->msg); Jmsg1(jcr, M_FATAL, 0, _("Bad .status command: %s\n"), jcr->errmsg); @@ -577,6 +581,15 @@ int qstatus_cmd(JCR *jcr) return 1; } +static void show_config(STATUS_PKT *sp) +{ + LockRes(); + CLIENT *client = (CLIENT *)GetNextRes(R_CLIENT, NULL); + UnlockRes(); + + dump_resource(R_CLIENT, (RES *)client, sendit, sp); +} + static void list_collectors_status(STATUS_PKT *sp, char *collname) { URES *res; diff --git a/bacula/src/lib/bcollector.c b/bacula/src/lib/bcollector.c index a0d36ad72..a0fa5ef08 100644 --- a/bacula/src/lib/bcollector.c +++ b/bacula/src/lib/bcollector.c @@ -28,6 +28,7 @@ #include "bacula.h" #include "parse_conf.h" #include "jcr.h" +#include "status.h" #include #define SPOOLFNAME "%s/%s.collector.%s.spool" @@ -545,6 +546,45 @@ void dump_collector_resource(COLLECTOR &res_collector, void sendit(void *sock, c } }; +/* common to SD/FD */ +void dump_collector_resource(COLLECTOR &res_collector, void sendit(const char *msg, int len, STATUS_PKT *sp), STATUS_PKT *sp) +{ + char *metric; + OutputWriter ow(sp->api_opts); + char *p; + + ow.start_group("Statistics:"); + ow.get_output(OT_START_OBJ, + OT_STRING, "name", res_collector.hdr.name, + OT_INT, "type", res_collector.type, + OT_INT32, "interval", res_collector.interval, + OT_STRING, "prefix", res_collector.prefix, + OT_END); + switch (res_collector.type){ + case COLLECTOR_BACKEND_CSV: + ow.get_output(OT_STRING, "file", res_collector.file, + OT_END); + break; + case COLLECTOR_BACKEND_Graphite: + ow.get_output(OT_STRING, "host", res_collector.host ? res_collector.host : "localhost", + OT_STRING, "port", res_collector.port, + OT_END); + break; + } + if (res_collector.metrics){ + foreach_alist(metric, res_collector.metrics){ + ow.get_output(OT_STRING, "metric", metric, + OT_END); + }; + } + + ow.get_output(OT_END_OBJ, + OT_END); + p = ow.end_group(); + + sendit(p, strlen(p), sp); +}; + /* * A support function frees a COLLECTOR class resources. */ diff --git a/bacula/src/lib/bcollector.h b/bacula/src/lib/bcollector.h index f0a6c2f92..d7e55875c 100644 --- a/bacula/src/lib/bcollector.h +++ b/bacula/src/lib/bcollector.h @@ -28,6 +28,8 @@ #ifndef __BCOLLECTOR_H_ #define __BCOLLECTOR_H_ +struct STATUS_PKT; /* Forward declaration */ + /* Supported backend types */ enum { COLLECTOR_BACKEND_Undef = 0, @@ -79,6 +81,7 @@ void stop_collector_thread(COLLECTOR *collector); void start_updcollector_thread(UPDATE_COLLECTOR_INIT_t &initdata); void stop_updcollector_thread(); void dump_collector_resource(COLLECTOR &res_collector, void sendit(void *sock, const char *fmt, ...), void *sock); +void dump_collector_resource(COLLECTOR &res_collector, void sendit(const char *msg, int len, STATUS_PKT *sp), STATUS_PKT *sp); void free_collector_resource(COLLECTOR &res_collector); int render_updcollector_status(POOL_MEM &buf); void api_render_updcollector_status(OutputWriter &ow); diff --git a/bacula/src/lib/parse_conf.h b/bacula/src/lib/parse_conf.h index eed3d32e2..a2402aab5 100644 --- a/bacula/src/lib/parse_conf.h +++ b/bacula/src/lib/parse_conf.h @@ -37,10 +37,12 @@ struct s_collt { }; struct RES_ITEM; /* Declare forward referenced structure */ -struct RES_ITEM1; +struct RES_ITEM1; /* Declare forward referenced structure */ struct RES_ITEM2; /* Declare forward referenced structure */ class RES; /* Declare forward referenced structure */ struct HPKT; /* Declare forward referenced structure */ +struct STATUS_PKT; /* Declare forward referenced structure */ + typedef void (RES_HANDLER)(HPKT &hpkt); typedef void (MSG_RES_HANDLER)(LEX *lc, RES_ITEM *item, int index, int pass); /* The INC_RES handler has an extra argument */ @@ -334,6 +336,7 @@ RES *GetNextRes(RES_HEAD **rhead, int rcode, RES *res); void b_LockRes(const char *file, int line); void b_UnlockRes(const char *file, int line); void dump_resource(int type, RES *res, void sendmsg(void *sock, const char *fmt, ...), void *sock); +void dump_resource(int type, RES *ares, void sendit(const char *msg, int len, STATUS_PKT *sp), STATUS_PKT *sp); void dump_each_resource(int type, void sendmsg(void *sock, const char *fmt, ...), void *sock); void free_resource(RES *res, int type); bool init_resource(CONFIG *config, uint32_t type, void *res, int size); diff --git a/bacula/src/stored/status.c b/bacula/src/stored/status.c index 16a1e063f..a8cf658a3 100644 --- a/bacula/src/stored/status.c +++ b/bacula/src/stored/status.c @@ -138,17 +138,13 @@ void output_status(STATUS_PKT *sp) } } -static void list_resources(STATUS_PKT *sp) +static void show_config(STATUS_PKT *sp) { -#ifdef when_working - POOL_MEM msg(PM_MESSAGE); - int len; + LockRes(); + STORES *store = (STORES *)GetNextRes(R_STORAGE, NULL); + UnlockRes(); - len = Mmsg(msg, _("\nSD Resources:\n")); - if (!sp->api) sendit(msg, len, sp); - dump_resource(R_DEVICE, resources[R_DEVICE-r_first], sp); - if (!sp->api) sendit("====\n\n", 6, sp); -#endif + dump_resource(R_STORAGE, (RES *)store, sendit, sp); } #ifdef xxxx @@ -1189,7 +1185,7 @@ bool qstatus_cmd(JCR *jcr) list_terminated_jobs(&sp); /* defined in lib/status.h */ } else if (strcasecmp(cmd, "resources") == 0) { sp.api = api; - list_resources(&sp); + show_config(&sp); /* ***BEEF*** */ } else if (strcasecmp(cmd, "dedupengine") == 0 || strcasecmp(cmd, "dedupengineandzerostats") == 0) { diff --git a/bacula/src/stored/stored_conf.c b/bacula/src/stored/stored_conf.c index 8b2b5842e..bcb8c860d 100644 --- a/bacula/src/stored/stored_conf.c +++ b/bacula/src/stored/stored_conf.c @@ -24,6 +24,7 @@ #include "bacula.h" #include "stored.h" +#include "lib/status.h" /* First and last resource ids */ int32_t r_first = R_FIRST; @@ -47,6 +48,7 @@ int32_t res_all_size = sizeof(res_all); #define dedup_check_storage_resource(a) true #endif +static int const dbglvl = 200; /* Definition of records permitted within each * resource with the routine to process the record @@ -556,75 +558,128 @@ void store_transfer_priority(LEX *lc, RES_ITEM *item, int index, int pass) set_bit(index, res_all.hdr.item_present); } +static void dump_store_resource(STORES *store, + void sendit(const char *msg, int len, STATUS_PKT *sp), STATUS_PKT *sp) +{ + OutputWriter ow(sp->api_opts); + POOL_MEM tmp; + char *p; + + ow.start_group("resource"); + + ow.get_output(OT_START_OBJ, + OT_STRING, "Name", store->hdr.name, + OT_STRING, "Description", store->hdr.desc, + OT_STRING, "WorkingDirectory", store->working_directory, + OT_STRING, "PidDirectory", store->pid_directory, + OT_STRING, "SubsysDirectory", store->subsys_directory, + OT_STRING, "PluginDirectory", store->plugin_directory, + OT_STRING, "ScriptsDirectory", store->scripts_directory, +#if BEEF + OT_BOOL, "FIPSRequire", store->require_fips, + OT_STRING, "SsdDirectory", store->ssd_directory, +#endif + OT_INT, "SDPort", get_first_port_host_order(store->sdaddrs), + OT_STRING, "SDAddress", get_first_address(store->sdaddrs, tmp.c_str(), PM_MESSAGE), + OT_INT64, "HeartbeatInterval", store->heartbeat_interval, + OT_INT32, "MaximumConcurrentJobs", store->max_concurrent_jobs, + OT_INT64, "ClientConnectTimeout", store->ClientConnectTimeout, + OT_BOOL, "TLSEnable", store->tls_enable, + OT_BOOL, "TLSPSKEnable", store->tls_psk_enable, + OT_BOOL, "TLSRequire", store->tls_require, + OT_BOOL, "TLSAuthenticate", store->tls_authenticate, + OT_BOOL, "TLSVerifyPeer", store->tls_verify_peer, + OT_INT64, "ClientConnectWait", store->client_wait, + OT_STRING, "VerId", store->verid, + OT_BOOL, "CommCommpression", store->comm_compression, +#ifdef SD_DEDUP_SUPPORT + OT_STRING, "DedupDirectory", store->dedup_dir, + OT_STRING, "DedupIndexDirectory", store->dedup_index_dir, + OT_BOOL, "DedupCheckHash", store->dedup_check_hash, + OT_INT64, "DedupScrupMaximumBandwidth", store->dedup_scrub_max_bandwidth, + OT_INT64, "MaximumContainerSize", store->max_container_size, +#endif + OT_END_OBJ, + OT_END); + + p = ow.end_group("resource"); + sendit(p, strlen(p), sp); +} + +/* In order to link with libbaccfg + * Empty method is here just be able to link with libbaccfg (see overload in @parse_conf.h). + * FileDaemon should use overloaded one, see methodb below. + * TODO this should be removed as soon as Director's dump_resource() is updated to work + * with STATUS_PKT. + * */ +void dump_resource(int type, RES *ares, void sendit(void *sock, const char *fmt, ...), void *sock) +{ + /**** NOT USED ****/ +} + /* Dump contents of resource */ -void dump_resource(int type, RES *rres, void sendit(void *sock, const char *fmt, ...), void *sock) +void dump_resource(int type, RES *rres, void sendit(const char *msg, int len, STATUS_PKT *sp), STATUS_PKT *sp) { URES *res = (URES *)rres; char buf[1000]; - int recurse = 1; - IPADDR *p; + int recurse = 1, len; + POOL_MEM msg(PM_MESSAGE); + if (res == NULL) { - sendit(sock, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type); + len = Mmsg(msg, _("Warning: no \"%s\" resource (%d) defined.\n"), res_to_str(type), type); + sendit(msg.c_str(), len, sp); return; } - sendit(sock, _("dump_resource type=%d\n"), type); + + Dmsg1(dbglvl, "dump_resource type=%d\n", type); + if (type < 0) { /* no recursion */ type = - type; recurse = 0; } + switch (type) { case R_DIRECTOR: - sendit(sock, "Director: name=%s\n", res->res_dir.hdr.name); + len = Mmsg(msg, "Director: name=%s\n", res->res_dir.hdr.name); + sendit(msg.c_str(), len, sp); break; case R_STORAGE: - sendit(sock, "Storage: name=%s SDaddr=%s SDport=%d SDDport=%d HB=%s\n", - res->res_store.hdr.name, - NPRT(get_first_address(res->res_store.sdaddrs, buf, sizeof(buf))), - get_first_port_host_order(res->res_store.sdaddrs), - get_first_port_host_order(res->res_store.sddaddrs), - edit_utime(res->res_store.heartbeat_interval, buf, sizeof(buf))); - if (res->res_store.sdaddrs) { - foreach_dlist(p, res->res_store.sdaddrs) { - sendit(sock, " SDaddr=%s SDport=%d\n", - p->get_address(buf, sizeof(buf)), p->get_port_host_order()); - } - } - if (res->res_store.sddaddrs) { - foreach_dlist(p, res->res_store.sddaddrs) { - sendit(sock, " SDDaddr=%s SDDport=%d\n", - p->get_address(buf, sizeof(buf)), p->get_port_host_order()); - } - } - if (res->res_store.dedup_dir){ - sendit(sock, " Dedup Directory: %s\n", res->res_store.dedup_dir ); - } - if (res->res_store.dedup_index_dir){ - sendit(sock, " Dedup Index Directory: %s\n", res->res_store.dedup_index_dir ); + { + STORES *store = (STORES *)rres; + dump_store_resource(store, sendit, sp); + break; } - break; case R_DEVICE: - sendit(sock, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n", + len = Mmsg(msg, "Device: name=%s MediaType=%s Device=%s LabelType=%d\n", res->res_dev.hdr.name, res->res_dev.media_type, res->res_dev.device_name, res->res_dev.label_type); - sendit(sock, " rew_wait=%lld min_bs=%d max_bs=%d chgr_wait=%lld\n", + sendit(msg.c_str(), len, sp); + len = Mmsg(msg, " rew_wait=%lld min_bs=%d max_bs=%d chgr_wait=%lld\n", res->res_dev.max_rewind_wait, res->res_dev.min_block_size, res->res_dev.max_block_size, res->res_dev.max_changer_wait); - sendit(sock, " max_jobs=%d max_files=%lld max_size=%lld\n", + sendit(msg.c_str(), len, sp); + len = Mmsg(msg, " max_jobs=%d max_files=%lld max_size=%lld\n", res->res_dev.max_volume_jobs, res->res_dev.max_volume_files, res->res_dev.max_volume_size); - sendit(sock, " min_block_size=%lld max_block_size=%lld\n", + len = Mmsg(msg, " min_block_size=%lld max_block_size=%lld\n", res->res_dev.min_block_size, res->res_dev.max_block_size); - sendit(sock, " max_file_size=%lld capacity=%lld\n", + sendit(msg.c_str(), len, sp); + len = Mmsg(msg, " max_file_size=%lld capacity=%lld\n", res->res_dev.max_file_size, res->res_dev.volume_capacity); - sendit(sock, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory)); - sendit(sock, " max_spool_size=%lld max_job_spool_size=%lld\n", + sendit(msg.c_str(), len, sp); + len = Mmsg(msg, " spool_directory=%s\n", NPRT(res->res_dev.spool_directory)); + sendit(msg.c_str(), len, sp); + len = Mmsg(msg, " max_spool_size=%lld max_job_spool_size=%lld\n", res->res_dev.max_spool_size, res->res_dev.max_job_spool_size); + sendit(msg.c_str(), len, sp); if (res->res_dev.worm_command) { - sendit(sock, " worm command=%s\n", res->res_dev.worm_command); + len = Mmsg(msg, " worm command=%s\n", res->res_dev.worm_command); + sendit(msg.c_str(), len, sp); } if (res->res_dev.changer_res) { - sendit(sock, " changer=%p\n", res->res_dev.changer_res); + len = Mmsg(msg, " changer=%p\n", res->res_dev.changer_res); + sendit(msg.c_str(), len, sp); } bstrncpy(buf, " ", sizeof(buf)); if (res->res_dev.cap_bits & CAP_EOF) { @@ -673,13 +728,14 @@ void dump_resource(int type, RES *rres, void sendit(void *sock, const char *fmt, bstrncat(buf, "CAP_OFFLINEUNMOUNT ", sizeof(buf)); } bstrncat(buf, "\n", sizeof(buf)); - sendit(sock, buf); /* Send caps string */ + sendit(buf, strlen(buf), sp); /* Send caps string */ if (res->res_dev.cloud) { - sendit(sock, " --->Cloud: name=%s\n", res->res_dev.cloud->hdr.name); + len = Mmsg(msg, " --->Cloud: name=%s\n", res->res_dev.cloud->hdr.name); + sendit(msg.c_str(), len, sp); } break; case R_CLOUD: - sendit(sock, "Cloud: name=%s Driver=%d\n" + len = Mmsg(msg, "Cloud: name=%s Driver=%d\n" " HostName=%s\n" " BucketName=%s\n" " AccessKey=%s SecretKey=%s\n" @@ -691,39 +747,49 @@ void dump_resource(int type, RES *rres, void sendit(void *sock, const char *fmt, res->res_cloud.access_key, res->res_cloud.secret_key, res->res_cloud.region, res->res_cloud.protocol, res->res_cloud.uri_style); + sendit(msg.c_str(), len, sp); break; case R_DEDUP: - sendit(sock, "Dedup: name=%s Driver=%d\n" + len = Mmsg(msg, "Dedup: name=%s Driver=%d\n" " DedupDirectory=%s\n", res->res_dedup.hdr.name, res->res_dedup.driver_type, res->res_dedup.dedup_dir); + sendit(msg.c_str(), len, sp); break; case R_AUTOCHANGER: DEVRES *dev; - sendit(sock, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n", + len = Mmsg(msg, "Changer: name=%s Changer_devname=%s\n Changer_cmd=%s\n", res->res_changer.hdr.name, res->res_changer.changer_name, res->res_changer.changer_command); + sendit(msg.c_str(), len, sp); foreach_alist(dev, res->res_changer.device) { - sendit(sock, " --->Device: name=%s\n", dev->hdr.name); + len = Mmsg(msg, " --->Device: name=%s\n", dev->hdr.name); + sendit(msg.c_str(), len, sp); } break; case R_MSGS: - sendit(sock, "Messages: name=%s\n", res->res_msgs.hdr.name); - if (res->res_msgs.mail_cmd) - sendit(sock, " mailcmd=%s\n", res->res_msgs.mail_cmd); - if (res->res_msgs.operator_cmd) - sendit(sock, " opcmd=%s\n", res->res_msgs.operator_cmd); + len = Mmsg(msg, "Messages: name=%s\n", res->res_msgs.hdr.name); + sendit(msg.c_str(), len, sp); + if (res->res_msgs.mail_cmd) { + len = Mmsg(msg, " mailcmd=%s\n", res->res_msgs.mail_cmd); + sendit(msg.c_str(), len, sp); + } + if (res->res_msgs.operator_cmd) { + len = Mmsg(msg, " opcmd=%s\n", res->res_msgs.operator_cmd); + sendit(msg.c_str(), len, sp); + } break; case R_COLLECTOR: - dump_collector_resource(res->res_collector, sendit, sock); + dump_collector_resource(res->res_collector, sendit, sp); break; default: - sendit(sock, _("Warning: unknown resource type %d\n"), type); + len = Mmsg(msg, _("Warning: unknown resource type %d\n"), type); + sendit(msg.c_str(), len, sp); break; } rres = GetNextRes(type, rres); if (recurse && rres) - dump_resource(type, rres, sendit, sock); + dump_resource(type, rres, sendit, sp); } /*