From: Nicolas Boichat Date: Sun, 15 Aug 2004 20:00:34 +0000 (+0000) Subject: - Add support for storage daemon. X-Git-Tag: Release-1.35.1~3 X-Git-Url: https://git.sur5r.net/?a=commitdiff_plain;h=fb9f1397b437fbd228562748b99ec7947f084d3f;p=bacula%2Fbacula - Add support for storage daemon. - 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 --- diff --git a/bacula/src/tray-monitor/authenticate.c b/bacula/src/tray-monitor/authenticate.c index f6afcf4a21..dfcb4974e6 100644 --- a/bacula/src/tray-monitor/authenticate.c +++ b/bacula/src/tray-monitor/authenticate.c @@ -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, _("bdirdmsg); + 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 */ diff --git a/bacula/src/tray-monitor/eggstatusicon.c b/bacula/src/tray-monitor/eggstatusicon.c index dab162b1ee..62064f9b46 100644 --- a/bacula/src/tray-monitor/eggstatusicon.c +++ b/bacula/src/tray-monitor/eggstatusicon.c @@ -22,6 +22,8 @@ * Nicolas Boichat (add access to the underlying EggTrayIcon) */ +extern "C" { + #include #include @@ -786,3 +788,5 @@ egg_status_icon_get_tray_icon (EggStatusIcon *status_icon) return EGG_TRAY_ICON(status_icon->priv->tray_icon); } + +} //extern "C" diff --git a/bacula/src/tray-monitor/eggtrayicon.c b/bacula/src/tray-monitor/eggtrayicon.c index 0539cd9bf8..b92f994de1 100644 --- a/bacula/src/tray-monitor/eggtrayicon.c +++ b/bacula/src/tray-monitor/eggtrayicon.c @@ -18,6 +18,8 @@ * Boston, MA 02111-1307, USA. */ +extern "C" { + #include #include @@ -477,3 +479,5 @@ egg_tray_icon_get_orientation (EggTrayIcon *icon) return icon->orientation; } + +} //extern "C" diff --git a/bacula/src/tray-monitor/tray-monitor.c b/bacula/src/tray-monitor/tray-monitor.c index ffdcbe3ea2..b6526960e7 100644 --- a/bacula/src/tray-monitor/tray-monitor.c +++ b/bacula/src/tray-monitor/tray-monitor.c @@ -41,17 +41,20 @@ /* 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, "\n"); - FD_sock = NULL; + D_sock = NULL; changeIcon(error); break; } - if (is_bnet_stop(FD_sock)) { + if (is_bnet_stop(D_sock)) { writeToTextBuffer(newbuffer, "\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); } } diff --git a/bacula/src/tray-monitor/tray-monitor.conf.in b/bacula/src/tray-monitor/tray-monitor.conf.in index 3038b725cc..bbeccaf3c3 100644 --- a/bacula/src/tray-monitor/tray-monitor.conf.in +++ b/bacula/src/tray-monitor/tray-monitor.conf.in @@ -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 diff --git a/bacula/src/tray-monitor/tray-monitor.h b/bacula/src/tray-monitor/tray-monitor.h index e62d7b1249..7891e86ad8 100644 --- a/bacula/src/tray-monitor/tray-monitor.h +++ b/bacula/src/tray-monitor/tray-monitor.h @@ -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* */ +}; + diff --git a/bacula/src/tray-monitor/tray_conf.c b/bacula/src/tray-monitor/tray_conf.c index 4e3955c9e5..2015f7c88a 100644 --- a/bacula/src/tray-monitor/tray_conf.c +++ b/bacula/src/tray-monitor/tray_conf.c @@ -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; diff --git a/bacula/src/tray-monitor/tray_conf.h b/bacula/src/tray-monitor/tray_conf.h index bc16b311cc..89a975ee58 100644 --- a/bacula/src/tray-monitor/tray_conf.h +++ b/bacula/src/tray-monitor/tray_conf.h @@ -32,7 +32,7 @@ /* * Resource codes -- they must be sequential for indexing */ -enum { +enum rescode { R_MONITOR = 1001, R_CLIENT, R_STORAGE,