]> git.sur5r.net Git - bacula/bacula/commitdiff
- Add support for storage daemon.
authorNicolas Boichat <nicolas@boichat.ch>
Sun, 15 Aug 2004 20:00:34 +0000 (20:00 +0000)
committerNicolas Boichat <nicolas@boichat.ch>
Sun, 15 Aug 2004 20:00:34 +0000 (20:00 +0000)
- Add popup menu to select the file/storage daemon which is currently monitored.

git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1534 91ce42f0-d328-0410-95d8-f526ca767f89

bacula/src/tray-monitor/authenticate.c
bacula/src/tray-monitor/eggstatusicon.c
bacula/src/tray-monitor/eggtrayicon.c
bacula/src/tray-monitor/tray-monitor.c
bacula/src/tray-monitor/tray-monitor.conf.in
bacula/src/tray-monitor/tray-monitor.h
bacula/src/tray-monitor/tray_conf.c
bacula/src/tray-monitor/tray_conf.h

index f6afcf4a2106b1e6f610a2273f304ff1cc467b54..dfcb4974e61c108e4809165373afa8311bc5b080 100644 (file)
@@ -40,11 +40,57 @@ void sendit(const char *buf);
  *  from the User Agent */
 static char hello[]    = "Hello Director %s calling\n";
 
+/* Response from SD */
+static char OKhello[]   = "3000 OK Hello\n";
 /* Response from FD */
 static char FDOKhello[] = "2000 OK Hello\n";
 
 /* Forward referenced functions */
 
+/*
+ * Authenticate Storage daemon connection
+ */
+int authenticate_storage_daemon(JCR *jcr, MONITOR *monitor, STORE* store)
+{
+   BSOCK *sd = jcr->store_bsock;
+   char dirname[MAX_NAME_LENGTH];
+   int ssl_need = BNET_SSL_NONE;
+
+   /* 
+    * Send my name to the Storage daemon then do authentication
+    */
+   bstrncpy(dirname, monitor->hdr.name, sizeof(dirname));
+   bash_spaces(dirname);
+   /* Timeout Hello after 5 mins */
+   btimer_t *tid = start_bsock_timer(sd, 60 * 5);
+   if (!bnet_fsend(sd, hello, dirname)) {
+      stop_bsock_timer(tid);
+      Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd));
+      return 0;
+   }
+   if (!cram_md5_get_auth(sd, store->password, ssl_need) || 
+       !cram_md5_auth(sd, store->password, ssl_need)) {
+      stop_bsock_timer(tid);
+      Jmsg0(jcr, M_FATAL, 0, _("Director and Storage daemon passwords or names not the same.\n"   
+       "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n"));
+      return 0;
+   }
+   Dmsg1(116, ">stored: %s", sd->msg);
+   if (bnet_recv(sd) <= 0) {
+      stop_bsock_timer(tid);
+      Jmsg1(jcr, M_FATAL, 0, _("bdird<stored: bad response to Hello command: ERR=%s\n"),
+        bnet_strerror(sd));
+      return 0;
+   }
+   Dmsg1(110, "<stored: %s", sd->msg);
+   stop_bsock_timer(tid);
+   if (strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) {
+      Jmsg0(jcr, M_FATAL, 0, _("Storage daemon rejected Hello command\n"));
+      return 0;
+   }
+   return 1;
+}
+
 /*
  * Authenticate File daemon connection
  */
index dab162b1ee76a06ddf6199af4f8ce5e29942c603..62064f9b46687da3f478bb83575eb519a88fa0e9 100644 (file)
@@ -22,6 +22,8 @@
  *  Nicolas Boichat <nicolas@boichat.ch> (add access to the underlying EggTrayIcon)
  */
 
+extern "C" {
+
 #include <string.h>
 #include <libintl.h>
 
@@ -786,3 +788,5 @@ egg_status_icon_get_tray_icon (EggStatusIcon      *status_icon)
    
    return EGG_TRAY_ICON(status_icon->priv->tray_icon);
 }
+
+} //extern "C"
index 0539cd9bf84f11a6b2c3805169979052fe4a9928..b92f994de12cb4cd673a5f08f8904d780297b7ac 100644 (file)
@@ -18,6 +18,8 @@
  * Boston, MA 02111-1307, USA.
  */
 
+extern "C" {
 #include <string.h>
 #include <libintl.h>
 
@@ -477,3 +479,5 @@ egg_tray_icon_get_orientation (EggTrayIcon *icon)
 
   return icon->orientation;
 }
+
+} //extern "C"
index ffdcbe3ea22a42352bf8bc133f6a649a3e760628..b6526960e77017397b718946bcfa86edd483c064 100644 (file)
 
 /* Imported functions */
 int authenticate_file_daemon(JCR *jcr, MONITOR *monitor, CLIENT* client);
+int authenticate_storage_daemon(JCR *jcr, MONITOR *monitor, STORE* store);
 
 /* Forward referenced functions */
 void writecmd(const char* command);
 
 /* Static variables */
 static char *configfile = NULL;
-static BSOCK *FD_sock = NULL;
+static BSOCK *D_sock = NULL;
 static MONITOR *monitor;
 static POOLMEM *args;
 static JCR jcr;
-static CLIENT* filed;
+static int nitems = 0;
+static monitoritem items[32];
+static monitoritem* currentitem;
 
 /* UI variables and functions */
 enum stateenum {
@@ -70,14 +73,18 @@ void changeIcon(stateenum status);
 void writeToTextBuffer(GtkTextBuffer *buffer, const char *fmt,...);
 
 /* Callbacks */
+static void TrayIconDaemonChanged(GtkWidget *widget, monitoritem* data);
 static void TrayIconActivate(GtkWidget *widget, gpointer data);
+static void TrayIconExit(unsigned int activateTime, unsigned int button);
+static void TrayIconPopupMenu(unsigned int button, unsigned int activateTime);
 static gboolean delete_event(GtkWidget *widget, GdkEvent  *event, gpointer   data);
 
 static gint timerTag;
-static EggStatusIcon* mTrayIcon;
-GtkWidget *window;
-GtkWidget *textview;
-GtkTextBuffer *buffer;
+static EggStatusIcon *mTrayIcon;
+static GtkWidget *mTrayMenu;
+static GtkWidget *window;
+static GtkWidget *textview;
+static GtkTextBuffer *buffer;
 
 #define CONFIG_FILE "./tray-monitor.conf"   /* default configuration file */
 
@@ -102,8 +109,10 @@ static void usage()
  */
 int main(int argc, char *argv[])
 {
-   int ch, nfiled;
+   int ch;
    bool test_config = false;
+   CLIENT* filed;
+   STORE* stored;
 
    init_stack_dump();
    my_name_is(argc, argv, "tray-monitor");
@@ -153,15 +162,25 @@ int main(int argc, char *argv[])
    parse_config(configfile);
 
    LockRes();
-   nfiled = 0;
+   nitems = 0;
    foreach_res(filed, R_CLIENT) {
-      nfiled++;
+      items[nitems].type = R_CLIENT;
+      items[nitems].resource = filed;
+      nitems++;
+   }
+   foreach_res(stored, R_STORAGE) {
+      items[nitems].type = R_STORAGE;
+      items[nitems].resource = stored;
+      nitems++;
    }
    UnlockRes();
-   if (nfiled != 1) {
-      Emsg1(M_ERROR_TERM, 0, _("No Client resource defined in %s (or more than one)\n\
-Without that I don't how to get status from the Client :-(\n"), configfile);
+   
+   if (nitems == 0) {
+      Emsg1(M_ERROR_TERM, 0, _("No Client nor Storage resource defined in %s\n\
+Without that I don't how to get status from the File or Storage Daemon :-(\n"), configfile);
    }
+   
+   currentitem = &(items[0]);
 
    if (test_config) {
       exit(0);
@@ -179,9 +198,57 @@ Without that I don't how to get status from the Client :-(\n"), configfile);
    // This should be ideally replaced by a completely libpr0n-based icon rendering.
    mTrayIcon = egg_status_icon_new_from_pixbuf(pixbuf);
    g_signal_connect(G_OBJECT(mTrayIcon), "activate", G_CALLBACK(TrayIconActivate), NULL);
-/*   g_signal_connect(G_OBJECT(mTrayIcon), "popup-menu", G_CALLBACK(TrayIconPopupMenu), this);*/
+   g_signal_connect(G_OBJECT(mTrayIcon), "popup-menu", G_CALLBACK(TrayIconPopupMenu), NULL);
    g_object_unref(G_OBJECT(pixbuf));
 
+   mTrayMenu = gtk_menu_new();
+   
+   GtkWidget *entry;
+   
+   entry = gtk_menu_item_new_with_label("Open status window...");
+   g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(TrayIconActivate), NULL);
+   gtk_menu_shell_append(GTK_MENU_SHELL(mTrayMenu), entry);
+   
+   GtkWidget *submenu = gtk_menu_new();
+   
+   entry = gtk_menu_item_new_with_label("Set monitored daemon");
+   gtk_menu_item_set_submenu(GTK_MENU_ITEM(entry), submenu);
+   gtk_menu_shell_append(GTK_MENU_SHELL(mTrayMenu), entry);
+      
+   GSList *group = NULL;
+   
+   GString *str;   
+   for (int i = 0; i < nitems; i++) {
+      switch (items[i].type) {
+      case R_CLIENT:
+         str = g_string_new(((CLIENT*)(items[i].resource))->hdr.name);
+         g_string_append(str, " (FD)");
+         break;
+      case R_STORAGE:
+         str = g_string_new(((STORE*)(items[i].resource))->hdr.name);
+         g_string_append(str, " (SD)");
+         break;
+      default:
+         continue;
+      }
+      entry = gtk_radio_menu_item_new_with_label(group, str->str);
+      g_string_free(str, TRUE);
+      
+      group = gtk_radio_menu_item_get_group(GTK_RADIO_MENU_ITEM(entry));
+      if (i == 0) {
+         gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(entry), TRUE);
+      }
+      
+      g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(TrayIconDaemonChanged), &(items[i]));
+      gtk_menu_shell_append(GTK_MENU_SHELL(submenu), entry);         
+   }
+   
+   entry = gtk_menu_item_new_with_label("Exit");
+   g_signal_connect(G_OBJECT(entry), "activate", G_CALLBACK(TrayIconExit), NULL);
+   gtk_menu_shell_append(GTK_MENU_SHELL(mTrayMenu), entry);
+   
+   gtk_widget_show_all(mTrayMenu);
+   
    timerTag = g_timeout_add( 5000, fd_read, NULL );
         
    window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
@@ -192,7 +259,7 @@ Without that I don't how to get status from the Client :-(\n"), configfile);
    //g_signal_connect (G_OBJECT (window), "destroy", G_CALLBACK (destroy), NULL);
    
    gtk_container_set_border_width(GTK_CONTAINER(window), 10);
-      
+   
    textview = gtk_text_view_new();
 
    buffer = gtk_text_buffer_new(NULL);
@@ -203,6 +270,9 @@ Without that I don't how to get status from the Client :-(\n"), configfile);
    gtk_widget_modify_font(textview, font_desc);
    pango_font_description_free (font_desc);
    
+   gtk_text_view_set_left_margin(GTK_TEXT_VIEW(textview), 20);
+   gtk_text_view_set_right_margin(GTK_TEXT_VIEW(textview), 20);
+   
    gtk_text_view_set_editable(GTK_TEXT_VIEW(textview), FALSE);
    
    gtk_text_view_set_buffer(GTK_TEXT_VIEW(textview), buffer);
@@ -215,10 +285,10 @@ Without that I don't how to get status from the Client :-(\n"), configfile);
    
    gtk_main();
       
-   if (FD_sock) {
-      writecmd("status");
-      bnet_sig(FD_sock, BNET_TERMINATE); /* send EOF */
-      bnet_close(FD_sock);
+   if (D_sock) {
+      writecmd("quit");
+      bnet_sig(D_sock, BNET_TERMINATE); /* send EOF */
+      bnet_close(D_sock);
    }
 
    free_pool_memory(args);
@@ -233,10 +303,48 @@ static gboolean delete_event( GtkWidget *widget,
    return TRUE; /* do not destroy the window */
 }
 
+static void TrayIconDaemonChanged(GtkWidget *widget, monitoritem* data) {
+   if (gtk_check_menu_item_get_active(GTK_CHECK_MENU_ITEM(widget))) { // && (data != currentitem)
+      printf("!!%s\n", ((STORE*)data->resource)->hdr.name);
+      if (D_sock) {
+         writecmd("quit");
+         bnet_sig(D_sock, BNET_TERMINATE); /* send EOF */
+         bnet_close(D_sock);
+         D_sock = NULL;
+      }
+      currentitem = data;
+      fd_read(NULL);
+   }
+}
+
 static void TrayIconActivate(GtkWidget *widget, gpointer data) {
     gtk_widget_show(window);
 }
 
+static void TrayIconPopupMenu(unsigned int activateTime, unsigned int button) {
+  gtk_menu_popup(GTK_MENU(mTrayMenu), NULL, NULL, NULL, NULL, 1, 0);
+  gtk_widget_show_all(mTrayMenu);
+}
+
+static void TrayIconExit(unsigned int activateTime, unsigned int button) {
+   gtk_main_quit();
+}
+
+static int authenticate_daemon(JCR *jcr) {
+   switch (currentitem->type) {
+   case R_CLIENT:
+      return authenticate_file_daemon(jcr, monitor, (CLIENT*)currentitem->resource);
+      break;
+   case R_STORAGE:
+      return authenticate_storage_daemon(jcr, monitor, (STORE*)currentitem->resource);
+      break;
+   default:
+      printf("Error, currentitem is not a Client or a Storage..\n");
+      gtk_main_quit();
+      return FALSE;
+   }
+}
+
 static gboolean fd_read(gpointer data) {
    int stat;
    int statuschanged = 0;
@@ -245,71 +353,86 @@ static gboolean fd_read(gpointer data) {
    
    gtk_text_buffer_set_text (newbuffer, "", -1);
       
-   if (!FD_sock) {
-      LockRes();
-      filed = (CLIENT*)GetNextRes(R_CLIENT, NULL);
-      UnlockRes();
-   
+   if (!D_sock) {
       memset(&jcr, 0, sizeof(jcr));
-            
-      writeToTextBuffer(newbuffer, "Connecting to Client %s:%d\n", filed->address, filed->FDport);
-      FD_sock = bnet_connect(NULL, 3, 3, "File daemon", filed->address, 
-               NULL, filed->FDport, 0);
-      if (FD_sock == NULL) {
+      
+      CLIENT* filed;
+      STORE* stored;
+      
+      switch (currentitem->type) {
+      case R_CLIENT:
+         filed = (CLIENT*)currentitem->resource;      
+         writeToTextBuffer(newbuffer, "Connecting to Client %s:%d\n", filed->address, filed->FDport);
+         D_sock = bnet_connect(NULL, 3, 3, "File daemon", filed->address, NULL, filed->FDport, 0);
+         jcr.file_bsock = D_sock;
+         break;
+      case R_STORAGE:
+         stored = (STORE*)currentitem->resource;      
+         writeToTextBuffer(newbuffer, "Connecting to Storage %s:%d\n", stored->address, stored->SDport);
+         D_sock = bnet_connect(NULL, 3, 3, "Storage daemon", stored->address, NULL, stored->SDport, 0);
+         jcr.store_bsock = D_sock;
+         break;
+      default:
+         printf("Error, currentitem is not a Client or a Storage..\n");
+         gtk_main_quit();
+         return FALSE;
+      }
+      
+      if (D_sock == NULL) {
+         writeToTextBuffer(newbuffer, "Cannot connect to daemon.\n");
          changeIcon(error);
          return 1;
       }
-      jcr.file_bsock = FD_sock;
       
-      if (!authenticate_file_daemon(&jcr, monitor, filed)) {
-         writeToTextBuffer(newbuffer, "ERR=%s", FD_sock->msg);
-         FD_sock = NULL;
+      if (!authenticate_daemon(&jcr)) {
+         writeToTextBuffer(newbuffer, "ERR=%s\n", D_sock->msg);
+         D_sock = NULL;
          changeIcon(error);
          return 0;
       }
    
-      trayMessage("Opened connection with File daemon");
+      writeToTextBuffer(newbuffer, "Opened connection with File daemon.\n");
    }
       
    writecmd("status");
    
    while(1) {
-      if ((stat = bnet_recv(FD_sock)) >= 0) {
-         writeToTextBuffer(newbuffer, FD_sock->msg);
-         if (strstr(FD_sock->msg, " is running.") != NULL) {
+      if ((stat = bnet_recv(D_sock)) >= 0) {
+         writeToTextBuffer(newbuffer, D_sock->msg);
+         if (strstr(D_sock->msg, " is running.") != NULL) {
             changeIcon(running);
             statuschanged = 1;
          }
-         else if (strstr(FD_sock->msg, "No Jobs running.") != NULL) {
+         else if (strstr(D_sock->msg, "No Jobs running.") != NULL) {
             changeIcon(idle);
             statuschanged = 1;
          }
       }
       else if (stat == BNET_SIGNAL) {
-         if (FD_sock->msglen == BNET_EOD) {
+         if (D_sock->msglen == BNET_EOD) {
             if (statuschanged == 0) {
                changeIcon(warn);
             }
             break;
          }
-         else if (FD_sock->msglen == BNET_HEARTBEAT) {
-            bnet_sig(FD_sock, BNET_HB_RESPONSE);
+         else if (D_sock->msglen == BNET_HEARTBEAT) {
+            bnet_sig(D_sock, BNET_HB_RESPONSE);
             writeToTextBuffer(newbuffer, "<< Heartbeat signal received, answered. >>");
          }
          else {
-            writeToTextBuffer(newbuffer, "<< Unexpected signal received : %s >>", bnet_sig_to_ascii(FD_sock));
+            writeToTextBuffer(newbuffer, "<< Unexpected signal received : %s >>", bnet_sig_to_ascii(D_sock));
          }
       }
       else { /* BNET_HARDEOF || BNET_ERROR */
          writeToTextBuffer(newbuffer, "<ERROR>\n");
-         FD_sock = NULL;
+         D_sock = NULL;
          changeIcon(error);
          break;
       }
            
-      if (is_bnet_stop(FD_sock)) {
+      if (is_bnet_stop(D_sock)) {
          writeToTextBuffer(newbuffer, "<STOP>\n");
-         FD_sock = NULL;
+         D_sock = NULL;
          changeIcon(error);
          break;            /* error or term */
       }
@@ -322,6 +445,8 @@ static gboolean fd_read(gpointer data) {
       gtk_text_buffer_select_range(newbuffer, &nstart, &nstop);
    }
 
+   g_object_unref(buffer);
+   
    buffer = newbuffer;
    gtk_text_view_set_buffer(GTK_TEXT_VIEW(textview), buffer);
       
@@ -329,10 +454,10 @@ static gboolean fd_read(gpointer data) {
 }
 
 void writecmd(const char* command) {
-   if (FD_sock) {
-      FD_sock->msglen = strlen(command);
-      pm_strcpy(&FD_sock->msg, command);
-      bnet_send(FD_sock);
+   if (D_sock) {
+      D_sock->msglen = strlen(command);
+      pm_strcpy(&D_sock->msg, command);
+      bnet_send(D_sock);
    }
 }
 
index 3038b725ccb1c586df96eb958b98314d7356f3c4..bbeccaf3c3291644b19da142df510556d87ffb5c 100644 (file)
@@ -11,4 +11,11 @@ Client {
   Address = @hostname@
   FDPort = @fd_port@
   Password = "@fd_password@"          # password for FileDaemon
+}
+
+Storage {
+  Name = @hostname@-sd
+  Address = @hostname@
+  SDPort = @sd_port@
+  Password = "@sd_password@"          # password for StorageDaemon
 }
\ No newline at end of file
index e62d7b12492cc7501e445262460aecc01ec1038e..7891e86ad8d429ddde663c581fedfde305b6f798 100644 (file)
@@ -30,3 +30,9 @@
 #define TRAY_MONITOR 1
 
 #include "jcr.h"
+
+struct monitoritem {
+   rescode type; /* R_CLIENT or R_STORAGE */
+   void* resource; /* CLIENT* or STORE* */
+};
+
index 4e3955c9e5785735b67f1fc2e891aecf5d4c757d..2015f7c88ad913d59f2fcb38d5b87d41f97c25d3 100644 (file)
@@ -179,7 +179,6 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm
 */
 void free_resource(RES *sres, int type)
 {
-   int num;
    RES *nres;                        /* next resource if linked */
    URES *res = (URES *)sres;
 
index bc16b311cca671c81e8b6e1bf10f16aa3a2827cc..89a975ee5861d0eeb934209a031ed17a02497e86 100644 (file)
@@ -32,7 +32,7 @@
 /*
  * Resource codes -- they must be sequential for indexing   
  */
-enum {
+enum rescode {
    R_MONITOR = 1001,
    R_CLIENT,
    R_STORAGE,