]> git.ipfire.org Git - thirdparty/bacula.git/commitdiff
Fix #6631 About bconsole command to show client's config
authorMichal Rakowski <michal.rakowski@baculasystems.com>
Tue, 8 Jun 2021 10:51:27 +0000 (12:51 +0200)
committerEric Bollengier <eric@baculasystems.com>
Thu, 24 Mar 2022 08:03:02 +0000 (09:03 +0100)
Create '.status client resources' and '.status storage resources'
commands to show main config of the Daemons.

bacula/src/dird/protos.h
bacula/src/dird/ua_output.c
bacula/src/dird/ua_server.c
bacula/src/dird/ua_status.c
bacula/src/filed/filed_conf.c
bacula/src/filed/status.c
bacula/src/lib/bcollector.c
bacula/src/lib/bcollector.h
bacula/src/lib/parse_conf.h
bacula/src/stored/status.c
bacula/src/stored/stored_conf.c

index 2848f7a40cc61580b910f9d15c33747de52c2528..d78859898eefeab540a2195b4f3ad7ab9962b89d 100644 (file)
@@ -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);
index 3db0cabb8bb866617febe202e79ed53a1372fc23..980c7b9a84e3a6fb8646b16262f89ec77c79794b 100644 (file)
@@ -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
index 17e18488bacdd0144609707060e59558cfba2d11..aeb01e2edee069010ef2bcb1ae5d54dae0cf3731 100644 (file)
@@ -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
  *
index 96d02b81dcdd42476c2fde0677a152481f980a43..ac351f9bbcfb942e7428ec1450913b9e1d4d5f46 100644 (file)
@@ -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);
index 0fd0dcd1579c2e168f348fbcb819f2d477152650..f7a8559a3daddae03bbcb53c9a4a26af28558da9 100644 (file)
@@ -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);
    }
 }
 
index 73ca49b6f34d58249294cf66586f93c98f417e30..b083354874fd06afedc07a05774548b65dfa6c6f 100644 (file)
@@ -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;
index a0d36ad72b8d3669bc624d23b5b6b5ddcb1a5f23..a0fa5ef08774d22826d93980c3e8fdeb3ab8009f 100644 (file)
@@ -28,6 +28,7 @@
 #include "bacula.h"
 #include "parse_conf.h"
 #include "jcr.h"
+#include "status.h"
 #include <time.h>
 
 #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.
  */
index f0a6c2f924782352202478a78f1be8432ef42b3c..d7e55875cbbac63a5bc658dbb3888af3a1a6e7c6 100644 (file)
@@ -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);
index eed3d32e2772690a2e6ca2faf21ec62ba51eea4f..a2402aab593eff974a4e5d4f664edb57481e7d99 100644 (file)
@@ -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);
index 16a1e063f5c93d8482d45871d60faabc3eb47f76..a8cf658a35201ea7fbf0c1a7b17b1a5b4d9a3bf9 100644 (file)
@@ -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) {
index 8b2b5842e1b2a2abc449b98b87e2949c5c2175dc..bcb8c860d0025f945a47e0aa844fe94f26d83b8e 100644 (file)
@@ -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);
 }
 
 /*