# 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 =
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, "<dird: %s", dir->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
*/
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;
}
Dmsg1(110, "<stored: %s", sd->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;
}
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;
#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);
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 */
{
int ch, i;
bool test_config = false;
+ DIRRES* dird;
CLIENT* filed;
STORE* stored;
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;
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)"));
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);
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;
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;
}
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);
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;
}
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);
Monitor {
Name = @hostname@-mon
+ Password = "@mon_dir_password@" # password for the Directors
}
Client {
}
Director {
- ConsoleName = Monitor
Name = @hostname@-dir
DIRport = @dir_port@
address = @hostname@
- Password = "@mon_dir_password@" # password for Director
}
\ No newline at end of file
};
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;
*
* 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
*
* 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 */
}
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);
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);
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);
*/
enum rescode {
R_MONITOR = 1001,
+ R_DIRECTOR,
R_CLIENT,
R_STORAGE,
R_FIRST = R_MONITOR,
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
*
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 */
};
*/
union URES {
MONITOR res_monitor;
+ DIRRES res_dir;
CLIENT res_client;
STORE res_store;
RES hdr;
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)