From 88d35442fe83e7f7378be53ec5cfb52e618603b8 Mon Sep 17 00:00:00 2001 From: Nicolas Boichat Date: Sun, 22 Aug 2004 22:02:45 +0000 Subject: [PATCH] Add support for director monitoring. git-svn-id: https://bacula.svn.sourceforge.net/svnroot/bacula/trunk@1551 91ce42f0-d328-0410-95d8-f526ca767f89 --- bacula/src/dird/bacula-dir.conf.in | 2 +- bacula/src/tray-monitor/authenticate.c | 61 +++++++++++++++-- bacula/src/tray-monitor/tray-monitor.c | 72 +++++++++++++++++--- bacula/src/tray-monitor/tray-monitor.conf.in | 3 +- bacula/src/tray-monitor/tray-monitor.h | 4 +- bacula/src/tray-monitor/tray_conf.c | 34 +++++++-- bacula/src/tray-monitor/tray_conf.h | 11 +++ bacula/src/wx-console/TODO | 10 +++ 8 files changed, 169 insertions(+), 28 deletions(-) diff --git a/bacula/src/dird/bacula-dir.conf.in b/bacula/src/dird/bacula-dir.conf.in index ed9b17082b..9d2cf76d49 100644 --- a/bacula/src/dird/bacula-dir.conf.in +++ b/bacula/src/dird/bacula-dir.conf.in @@ -224,7 +224,7 @@ Pool { # Restricted console used by tray-monitor to get the status of the director # Console { - Name = Monitor + Name = @hostname@-mon Password = "@mon_dir_password@" CommandACL = status, .status ClientACL = diff --git a/bacula/src/tray-monitor/authenticate.c b/bacula/src/tray-monitor/authenticate.c index acec72f556..44f5a6f82a 100644 --- a/bacula/src/tray-monitor/authenticate.c +++ b/bacula/src/tray-monitor/authenticate.c @@ -36,17 +36,68 @@ void senditf(const char *fmt, ...); void sendit(const char *buf); +/* Commands sent to Director */ +static char DIRhello[] = "Hello %s calling\n"; + +/* Response from Director */ +static char DIROKhello[] = "1000 OK:"; + /* Commands sent to Storage daemon and File daemon and received * from the User Agent */ -static char hello[] = "Hello Director %s calling\n"; +static char SDFDhello[] = "Hello Director %s calling\n"; /* Response from SD */ -static char OKhello[] = "3000 OK Hello\n"; +static char SDOKhello[] = "3000 OK Hello\n"; /* Response from FD */ static char FDOKhello[] = "2000 OK Hello\n"; /* Forward referenced functions */ +/* + * Authenticate Director + */ +int authenticate_director(JCR *jcr, MONITOR *mon, DIRRES *director) +{ + BSOCK *dir = jcr->dir_bsock; + int ssl_need = BNET_SSL_NONE; + char bashed_name[MAX_NAME_LENGTH]; + char *password; + + bstrncpy(bashed_name, mon->hdr.name, sizeof(bashed_name)); + bash_spaces(bashed_name); + password = mon->password; + + /* Timeout Hello after 5 mins */ + btimer_t *tid = start_bsock_timer(dir, 60 * 5); + bnet_fsend(dir, DIRhello, bashed_name); + + if (!cram_md5_get_auth(dir, password, ssl_need) || + !cram_md5_auth(dir, password, ssl_need)) { + stop_bsock_timer(tid); + Jmsg0(jcr, M_FATAL, 0, _("Director authorization problem.\n" + "Most likely the passwords do not agree.\n" + "Please see http://www.bacula.org/html-manual/faq.html#AuthorizationErrors for help.\n")); + return 0; + } + + Dmsg1(6, ">dird: %s", dir->msg); + if (bnet_recv(dir) <= 0) { + stop_bsock_timer(tid); + Jmsg1(jcr, M_FATAL, 0, _("Bad response to Hello command: ERR=%s\n"), + bnet_strerror(dir)); + return 0; + } + Dmsg1(10, "msg); + stop_bsock_timer(tid); + if (strncmp(dir->msg, DIROKhello, sizeof(DIROKhello)-1) != 0) { + Jmsg0(jcr, M_FATAL, 0, _("Director rejected Hello command\n")); + return 0; + } else { + Jmsg0(jcr, M_FATAL, 0, dir->msg); + } + return 1; +} + /* * Authenticate Storage daemon connection */ @@ -63,7 +114,7 @@ int authenticate_storage_daemon(JCR *jcr, MONITOR *monitor, STORE* store) bash_spaces(dirname); /* Timeout Hello after 5 mins */ btimer_t *tid = start_bsock_timer(sd, 60 * 5); - if (!bnet_fsend(sd, hello, dirname)) { + if (!bnet_fsend(sd, SDFDhello, dirname)) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to Storage daemon. ERR=%s\n"), bnet_strerror(sd)); return 0; @@ -84,7 +135,7 @@ int authenticate_storage_daemon(JCR *jcr, MONITOR *monitor, STORE* store) } Dmsg1(110, "msg); stop_bsock_timer(tid); - if (strncmp(sd->msg, OKhello, sizeof(OKhello)) != 0) { + if (strncmp(sd->msg, SDOKhello, sizeof(SDOKhello)) != 0) { Jmsg0(jcr, M_FATAL, 0, _("Storage daemon rejected Hello command\n")); return 0; } @@ -107,7 +158,7 @@ int authenticate_file_daemon(JCR *jcr, MONITOR *monitor, CLIENT* client) bash_spaces(dirname); /* Timeout Hello after 5 mins */ btimer_t *tid = start_bsock_timer(fd, 60 * 5); - if (!bnet_fsend(fd, hello, dirname)) { + if (!bnet_fsend(fd, SDFDhello, dirname)) { stop_bsock_timer(tid); Jmsg(jcr, M_FATAL, 0, _("Error sending Hello to File daemon. ERR=%s\n"), bnet_strerror(fd)); return 0; diff --git a/bacula/src/tray-monitor/tray-monitor.c b/bacula/src/tray-monitor/tray-monitor.c index 6241ebe760..a405504cbe 100644 --- a/bacula/src/tray-monitor/tray-monitor.c +++ b/bacula/src/tray-monitor/tray-monitor.c @@ -39,6 +39,7 @@ #include "warn.xpm" /* Imported functions */ +int authenticate_director(JCR *jcr, MONITOR *monitor, DIRRES *director); int authenticate_file_daemon(JCR *jcr, MONITOR *monitor, CLIENT* client); int authenticate_storage_daemon(JCR *jcr, MONITOR *monitor, STORE* store); @@ -57,8 +58,8 @@ static int fullitem = -1; //Item to be display in detailled status window static int lastupdated = -1; //Last item updated static monitoritem items[32]; -/* Data received from FD/SD */ -static char OKqstatus[] = "2000 OK .status\n"; +/* Data received from DIR/FD/SD */ +static char OKqstatus[] = "%c000 OK .status\n"; static char DotStatusJob[] = "JobId=%d JobStatus=%c JobErrors=%d\n"; /* UI variables and functions */ @@ -136,6 +137,7 @@ int main(int argc, char *argv[]) { int ch, i; bool test_config = false; + DIRRES* dird; CLIENT* filed; STORE* stored; @@ -189,6 +191,13 @@ int main(int argc, char *argv[]) LockRes(); nitems = 0; + foreach_res(dird, R_DIRECTOR) { + items[nitems].type = R_DIRECTOR; + items[nitems].resource = dird; + items[nitems].D_sock = NULL; + items[nitems].state = warn; + nitems++; + } foreach_res(filed, R_CLIENT) { items[nitems].type = R_CLIENT; items[nitems].resource = filed; @@ -287,6 +296,10 @@ Without that I don't how to get status from the File or Storage Daemon :-(\n"), GString *str; for (int i = 0; i < nitems; i++) { switch (items[i].type) { + case R_DIRECTOR: + str = g_string_new(((DIRRES*)(items[i].resource))->hdr.name); + g_string_append(str, _(" (DIR)")); + break; case R_CLIENT: str = g_string_new(((CLIENT*)(items[i].resource))->hdr.name); g_string_append(str, _(" (FD)")); @@ -304,10 +317,12 @@ Without that I don't how to get status from the File or Storage Daemon :-(\n"), items[i].image = gtk_image_new_from_pixbuf(pixbuf); items[i].label = gtk_label_new(_("Unknown status.")); - + GtkWidget* align = gtk_alignment_new(0.0, 0.5, 0.0, 1.0); + gtk_container_add(GTK_CONTAINER(align), items[i].label); + gtk_table_attach_defaults(GTK_TABLE(daemon_table), label, 0, 1, (i*2)+1, (i*2)+2); gtk_table_attach_defaults(GTK_TABLE(daemon_table), items[i].image, 1, 2, (i*2)+1, (i*2)+2); - gtk_table_attach_defaults(GTK_TABLE(daemon_table), items[i].label, 2, 3, (i*2)+1, (i*2)+2); + gtk_table_attach_defaults(GTK_TABLE(daemon_table), align, 2, 3, (i*2)+1, (i*2)+2); GtkWidget* separator = gtk_hseparator_new(); gtk_table_attach_defaults(GTK_TABLE(daemon_table), separator, 0, 3, (i*2)+2, (i*2)+3); @@ -390,6 +405,9 @@ static void TrayIconExit(unsigned int activateTime, unsigned int button) { static int authenticate_daemon(monitoritem* item, JCR *jcr) { switch (item->type) { + case R_DIRECTOR: + return authenticate_director(jcr, monitor, (DIRRES*)item->resource); + break; case R_CLIENT: return authenticate_file_daemon(jcr, monitor, (CLIENT*)item->resource); break; @@ -465,19 +483,26 @@ stateenum getstatus(monitoritem* item, int current, GString** str) { stateenum ret = error; int jobid = 0, joberrors = 0; char jobstatus = JS_ErrorTerminated; + char num; int k; *str = g_string_sized_new(128); if (current) { - docmd(&items[lastupdated], ".status current", &list); + if (item->type == R_DIRECTOR) + docmd(&items[lastupdated], ".status dir current", &list); + else + docmd(&items[lastupdated], ".status current", &list); } else { - docmd(&items[lastupdated], ".status last", &list); + if (item->type == R_DIRECTOR) + docmd(&items[lastupdated], ".status dir last", &list); + else + docmd(&items[lastupdated], ".status last", &list); } it = list->next; - if ((it == NULL) || (strcmp(((GString*)it->data)->str, OKqstatus) != 0)) { + if ((it == NULL) || (sscanf(((GString*)it->data)->str, OKqstatus, &num) != 1)) { g_string_append_printf(*str, ".status error : %s", (it == NULL) ? "" : ((GString*)it->data)->str); ret = error; } @@ -556,10 +581,18 @@ int docmd(monitoritem* item, const char* command, GSList** list) { if (!item->D_sock) { memset(&jcr, 0, sizeof(jcr)); + DIRRES* dird; CLIENT* filed; STORE* stored; switch (item->type) { + case R_DIRECTOR: + dird = (DIRRES*)item->resource; + trayMessage("Connecting to Director %s:%d\n", dird->address, dird->DIRport); + changeStatusMessage(item, "Connecting to Director %s:%d", dird->address, dird->DIRport); + item->D_sock = bnet_connect(NULL, 0, 0, "Director daemon", dird->address, NULL, dird->DIRport, 0); + jcr.dir_bsock = item->D_sock; + break; case R_CLIENT: filed = (CLIENT*)item->resource; trayMessage("Connecting to Client %s:%d\n", filed->address, filed->FDport); @@ -575,7 +608,7 @@ int docmd(monitoritem* item, const char* command, GSList** list) { jcr.store_bsock = item->D_sock; break; default: - printf("Error, currentitem is not a Client or a Storage..\n"); + printf("Error, currentitem is not a Client, a Storage or a Director..\n"); gtk_main_quit(); return 0; } @@ -596,9 +629,26 @@ int docmd(monitoritem* item, const char* command, GSList** list) { item->D_sock = NULL; return 0; } - - trayMessage("Opened connection with File daemon.\n"); - changeStatusMessage(item, "Opened connection with File daemon."); + + switch (item->type) { + case R_DIRECTOR: + trayMessage("Opened connection with Director daemon.\n"); + changeStatusMessage(item, "Opened connection with Director daemon."); + break; + case R_CLIENT: + trayMessage("Opened connection with File daemon.\n"); + changeStatusMessage(item, "Opened connection with File daemon."); + break; + case R_STORAGE: + trayMessage("Opened connection with Storage daemon.\n"); + changeStatusMessage(item, "Opened connection with Storage daemon."); + break; + default: + printf("Error, currentitem is not a Client, a Storage or a Director..\n"); + gtk_main_quit(); + return 0; + break; + } } writecmd(item, command); diff --git a/bacula/src/tray-monitor/tray-monitor.conf.in b/bacula/src/tray-monitor/tray-monitor.conf.in index 3c451666f2..bdf17307e9 100644 --- a/bacula/src/tray-monitor/tray-monitor.conf.in +++ b/bacula/src/tray-monitor/tray-monitor.conf.in @@ -4,6 +4,7 @@ Monitor { Name = @hostname@-mon + Password = "@mon_dir_password@" # password for the Directors } Client { @@ -21,9 +22,7 @@ Storage { } Director { - ConsoleName = Monitor Name = @hostname@-dir DIRport = @dir_port@ address = @hostname@ - Password = "@mon_dir_password@" # password for Director } \ 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 8a7c27f9dd..10bc312afa 100644 --- a/bacula/src/tray-monitor/tray-monitor.h +++ b/bacula/src/tray-monitor/tray-monitor.h @@ -39,8 +39,8 @@ enum stateenum { }; struct monitoritem { - rescode type; /* R_CLIENT or R_STORAGE */ - void* resource; /* CLIENT* or STORE* */ + rescode type; /* R_DIRECTOR, R_CLIENT or R_STORAGE */ + void* resource; /* DIRRES*, CLIENT* or STORE* */ BSOCK *D_sock; stateenum state; GtkWidget* image; diff --git a/bacula/src/tray-monitor/tray_conf.c b/bacula/src/tray-monitor/tray_conf.c index 8d63a66856..81e04c8c7a 100644 --- a/bacula/src/tray-monitor/tray_conf.c +++ b/bacula/src/tray-monitor/tray_conf.c @@ -71,15 +71,26 @@ int res_all_size = sizeof(res_all); * * name handler value code flags default_value */ -static RES_ITEM dir_items[] = { +static RES_ITEM mon_items[] = { {"name", store_name, ITEM(res_monitor.hdr.name), 0, ITEM_REQUIRED, 0}, {"description", store_str, ITEM(res_monitor.hdr.desc), 0, 0, 0}, {"requiressl", store_yesno, ITEM(res_monitor.require_ssl), 1, ITEM_DEFAULT, 0}, + {"password", store_password, ITEM(res_monitor.password), 0, ITEM_REQUIRED, 0}, {"fdconnecttimeout", store_time,ITEM(res_monitor.FDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30}, {"sdconnecttimeout", store_time,ITEM(res_monitor.SDConnectTimeout), 0, ITEM_DEFAULT, 60 * 30}, {NULL, NULL, NULL, 0, 0, 0} }; +/* Director's that we can contact */ +static RES_ITEM dir_items[] = { + {"name", store_name, ITEM(res_dir.hdr.name), 0, ITEM_REQUIRED, 0}, + {"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0}, + {"dirport", store_int, ITEM(res_dir.DIRport), 0, ITEM_DEFAULT, 9101}, + {"address", store_str, ITEM(res_dir.address), 0, 0, 0}, + {"enablessl", store_yesno, ITEM(res_dir.enable_ssl), 1, ITEM_DEFAULT, 0}, + {NULL, NULL, NULL, 0, 0, 0} +}; + /* * Client or File daemon resource * @@ -124,10 +135,11 @@ static RES_ITEM store_items[] = { * name items rcode res_head */ RES_TABLE resources[] = { - {"monitor", dir_items, R_MONITOR}, - {"client", cli_items, R_CLIENT}, - {"storage", store_items, R_STORAGE}, - {NULL, NULL, 0} + {"monitor", mon_items, R_MONITOR}, + {"director", dir_items, R_DIRECTOR}, + {"client", cli_items, R_CLIENT}, + {"storage", store_items, R_STORAGE}, + {NULL, NULL, 0} }; /* Dump contents of resource */ @@ -147,11 +159,15 @@ void dump_resource(int type, RES *reshdr, void sendit(void *sock, const char *fm } switch (type) { case R_MONITOR: - sendit(sock, "Director: name=%s FDtimeout=%s SDtimeout=%s\n", + sendit(sock, "Monitor: name=%s FDtimeout=%s SDtimeout=%s\n", reshdr->name, edit_uint64(res->res_monitor.FDConnectTimeout, ed1), edit_uint64(res->res_monitor.SDConnectTimeout, ed2)); break; + case R_DIRECTOR: + sendit(sock, "Director: name=%s address=%s FDport=%d\n", + res->res_dir.hdr.name, res->res_dir.address, res->res_dir.DIRport); + break; case R_CLIENT: sendit(sock, "Client: name=%s address=%s FDport=%d\n", res->res_client.hdr.name, res->res_client.address, res->res_client.FDport); @@ -266,6 +282,7 @@ void save_resource(int type, RES_ITEM *items, int pass) case R_MONITOR: case R_CLIENT: case R_STORAGE: + case R_DIRECTOR: break; default: Emsg1(M_ERROR, 0, "Unknown resource type %d in save_resource.\n", type); @@ -293,8 +310,11 @@ void save_resource(int type, RES_ITEM *items, int pass) case R_MONITOR: size = sizeof(MONITOR); break; + case R_DIRECTOR: + size = sizeof(DIRRES); + break; case R_CLIENT: - size =sizeof(CLIENT); + size = sizeof(CLIENT); break; case R_STORAGE: size = sizeof(STORE); diff --git a/bacula/src/tray-monitor/tray_conf.h b/bacula/src/tray-monitor/tray_conf.h index a4ff45d5e7..6e57878216 100644 --- a/bacula/src/tray-monitor/tray_conf.h +++ b/bacula/src/tray-monitor/tray_conf.h @@ -34,6 +34,7 @@ */ enum rescode { R_MONITOR = 1001, + R_DIRECTOR, R_CLIENT, R_STORAGE, R_FIRST = R_MONITOR, @@ -52,6 +53,14 @@ enum { R_BACKUP }; +/* Director */ +struct DIRRES { + RES hdr; + int DIRport; /* UA server port */ + char *address; /* UA server address */ + int enable_ssl; /* Use SSL */ +}; + /* * Tray Monitor Resource * @@ -60,6 +69,7 @@ struct MONITOR { RES hdr; int require_ssl; /* Require SSL for all connections */ MSGS *messages; /* Daemon message handler */ + char *password; /* UA server password */ utime_t FDConnectTimeout; /* timeout for connect in seconds */ utime_t SDConnectTimeout; /* timeout in seconds */ }; @@ -98,6 +108,7 @@ struct STORE { */ union URES { MONITOR res_monitor; + DIRRES res_dir; CLIENT res_client; STORE res_store; RES hdr; diff --git a/bacula/src/wx-console/TODO b/bacula/src/wx-console/TODO index cce06f422a..8839f14d80 100644 --- a/bacula/src/wx-console/TODO +++ b/bacula/src/wx-console/TODO @@ -1,4 +1,14 @@ general : Show nice messages boxes when errors occurs. + +general : Bug reported by Kern: + I tried loading my current backup into the restore window. It + consisted of something like 10 jobs and was pretty big. It was all + loaded, I double clicked on a directory, which was then marked, then + I opened it and clicked on subdirectory to unmark it, and I saw the + X appear on the top directory with a small check, then I'm not sure if I + clicked again, but my whole OS froze -- at first I could still move the + mouse a bit (very slowly) then after 30 seconds *everything* was dead. + I had to do a power off to get my system back. wxbRestorePanel : list jobs and list jobid=# will probably crash if there is nothing to show (db error or empty table) -- 2.39.5