Volume Retention = 365 days # one year
Accept Any Volume = yes # write on any volume in the pool
}
+
+#
+# Restricted console used by tray-monitor to get the status of the director
+#
+Console {
+ Name = Monitor
+ Password = "@mon_dir_password@"
+ CommandACL = status, .status
+ ClientACL =
+ StorageACL =
+}
\ No newline at end of file
extern int qmessagescmd(UAContext *ua, const char *cmd);
extern int quit_cmd(UAContext *ua, const char *cmd);
extern int qhelp_cmd(UAContext *ua, const char *cmd);
+extern int qstatus_cmd(UAContext *ua, const char *cmd);
/* Forward referenced functions */
static int diecmd(UAContext *ua, const char *cmd);
{ N_(".types"), typescmd, NULL},
{ N_(".backups"), backupscmd, NULL},
{ N_(".levels"), levelscmd, NULL},
+ { N_(".status"), qstatus_cmd, NULL},
{ N_(".storage"), storagecmd, NULL},
{ N_(".defaults"), defaultscmd, NULL},
{ N_(".messages"), qmessagescmd, NULL},
static void do_director_status(UAContext *ua);
static void do_all_status(UAContext *ua);
+static char OKqstatus[] = "2000 OK .status\n";
+static char DotStatusJob[] = "JobId=%d JobStatus=%c JobErrors=%d\n";
+
+/*
+ * .status command
+ */
+int qstatus_cmd(UAContext *ua, const char *cmd)
+{
+ JCR* njcr;
+ s_last_job* job;
+
+ if (!open_db(ua)) {
+ return 1;
+ }
+ Dmsg1(20, "status:%s:\n", cmd);
+
+ if ((ua->argc != 3) || (strcasecmp(ua->argk[1], "dir"))) {
+ bsendmsg(ua, "2900 Bad .status command, missing arguments.\n");
+ return 1;
+ }
+
+ if (strcasecmp(ua->argk[2], "current") == 0) {
+ bsendmsg(ua, OKqstatus, ua->argk[2]);
+ lock_jcr_chain();
+ foreach_jcr(njcr) {
+ if (njcr->JobId != 0) {
+ bsendmsg(ua, DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors);
+ }
+ free_locked_jcr(njcr);
+ }
+ unlock_jcr_chain();
+ }
+ else if (strcasecmp(ua->argk[2], "last") == 0) {
+ bsendmsg(ua, OKqstatus, ua->argk[2]);
+ if ((last_jobs) && (last_jobs->size() > 0)) {
+ job = (s_last_job*)last_jobs->last();
+ bsendmsg(ua, DotStatusJob, job->JobId, job->JobStatus, job->Errors);
+ }
+ }
+ else {
+ bsendmsg(ua, "2900 Bad .status command, wrong argument.\n");
+ return 1;
+ }
+
+ return 1;
+}
+
/*
* status command
*/
/*********************************************************************
*
*/
-static int authenticate(int rcode, BSOCK *bs)
+static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
{
POOLMEM *dirname;
DIRRES *director;
}
stop_bsock_timer(tid);
free_pool_memory(dirname);
+ jcr->director = director;
return (director != NULL);
}
{
BSOCK *dir = jcr->dir_bsock;
- if (!authenticate(R_DIRECTOR, dir)) {
+ if (!authenticate(R_DIRECTOR, dir, jcr)) {
bnet_fsend(dir, "%s", Dir_sorry);
Emsg0(M_FATAL, 0, _("Unable to authenticate Director\n"));
bmicrosleep(5, 0);
Password = "@fd_password@"
}
+#
+# Restricted Director, used by tray-monitor to get the
+# status of the file daemon
+#
+Director {
+ Name = @hostname@-mon
+ Password = "@mon_fd_password@"
+ Monitor = yes
+}
+
#
# "Global" File daemon configuration specifications
#
*/
#define FILE_DAEMON 1
+#include "filed_conf.h"
#include "findlib/find.h"
#include "jcr.h"
#include "protos.h" /* file daemon prototypes */
-#include "filed_conf.h"
#ifdef HAVE_LIBZ
#include <zlib.h> /* compression headers */
#else
{"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
{"address", store_str, ITEM(res_dir.address), 0, 0, 0},
{"enablessl", store_yesno, ITEM(res_dir.enable_ssl),1, ITEM_DEFAULT, 0},
+ {"monitor", store_yesno, ITEM(res_dir.monitor), 1, ITEM_DEFAULT, 0},
{NULL, NULL, NULL, 0, 0, 0}
};
char *password; /* Director password */
char *address; /* Director address or zero */
int enable_ssl; /* Use SSL for this Director */
+ int monitor; /* Have only access to status and .status functions */
};
struct CLIENT {
struct s_cmds {
const char *cmd;
int (*func)(JCR *);
+ int monitoraccess; /* specify if monitors have access to this function */
};
/*
* The following are the recognized commands from the Director.
*/
static struct s_cmds cmds[] = {
- {"backup", backup_cmd},
- {"cancel", cancel_cmd},
- {"setdebug=", setdebug_cmd},
- {"estimate", estimate_cmd},
- {"exclude", exclude_cmd},
- {"Hello", hello_cmd},
- {"include", include_cmd},
- {"fileset", fileset_cmd},
- {"JobId=", job_cmd},
- {"level = ", level_cmd},
- {"restore", restore_cmd},
- {"session", session_cmd},
- {"status", status_cmd},
- {".status", qstatus_cmd},
- {"storage ", storage_cmd},
- {"verify", verify_cmd},
- {"bootstrap", bootstrap_cmd},
- {"RunBeforeJob", runbefore_cmd},
- {"RunAfterJob", runafter_cmd},
+ {"backup", backup_cmd, 0},
+ {"cancel", cancel_cmd, 0},
+ {"setdebug=", setdebug_cmd, 0},
+ {"estimate", estimate_cmd, 0},
+ {"exclude", exclude_cmd, 0},
+ {"Hello", hello_cmd, 1},
+ {"include", include_cmd, 0},
+ {"fileset", fileset_cmd, 0},
+ {"JobId=", job_cmd, 0},
+ {"level = ", level_cmd, 0},
+ {"restore", restore_cmd, 0},
+ {"session", session_cmd, 0},
+ {"status", status_cmd, 1},
+ {".status", qstatus_cmd, 1},
+ {"storage ", storage_cmd, 0},
+ {"verify", verify_cmd, 0},
+ {"bootstrap", bootstrap_cmd, 0},
+ {"RunBeforeJob", runbefore_cmd, 0},
+ {"RunAfterJob", runafter_cmd, 0},
{NULL, NULL} /* list terminator */
};
/* Responses sent to Director */
static char errmsg[] = "2999 Invalid command\n";
static char no_auth[] = "2998 No Authorization\n";
+static char illegal_cmd[] = "2997 Illegal command for a Director with Monitor directive enabled\n";
static char OKinc[] = "2000 OK include\n";
static char OKest[] = "2000 OK estimate files=%u bytes=%s\n";
static char OKexc[] = "2000 OK exclude\n";
/* Read command */
if (bnet_recv(dir) < 0) {
- break; /* connection terminated */
+ break; /* connection terminated */
}
dir->msg[dir->msglen] = 0;
Dmsg1(100, "<dird: %s", dir->msg);
found = false;
for (i=0; cmds[i].cmd; i++) {
- if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
- if (!jcr->authenticated && cmds[i].func != hello_cmd) {
- bnet_fsend(dir, no_auth);
- break;
- }
- found = true; /* indicate command found */
+ if (strncmp(cmds[i].cmd, dir->msg, strlen(cmds[i].cmd)) == 0) {
+ found = true; /* indicate command found */
+ if (!jcr->authenticated && cmds[i].func != hello_cmd) {
+ bnet_fsend(dir, no_auth);
+ bnet_sig(dir, BNET_EOD);
+ break;
+ }
+ if ((jcr->authenticated) && (!cmds[i].monitoraccess) && (jcr->director->monitor)) {
+ Dmsg1(100, "Command %s illegal.\n", cmds[i].cmd);
+ bnet_fsend(dir, illegal_cmd);
+ bnet_sig(dir, BNET_EOD);
+ break;
+ }
Dmsg1(100, "Executing %s command.\n", cmds[i].cmd);
- if (!cmds[i].func(jcr)) { /* do command */
- quit = true; /* error or fully terminated, get out */
+ if (!cmds[i].func(jcr)) { /* do command */
+ quit = true; /* error or fully terminated, get out */
Dmsg0(20, "Quit command loop due to command error or Job done.\n");
- }
- break;
- }
+ }
+ break;
+ }
}
- if (!found) { /* command not found */
- bnet_fsend(dir, errmsg);
- quit = true;
- break;
+ if (!found) { /* command not found */
+ bnet_fsend(dir, errmsg);
+ quit = true;
+ break;
}
}
pthread_t heartbeat_id; /* id of heartbeat thread */
volatile BSOCK *hb_bsock; /* duped SD socket */
POOLMEM *RunAfterJob; /* Command to run after job */
+ DIRRES* director; /* Director resource */
#endif /* FILE_DAEMON */
bool no_attributes; /* set if no attributes wanted */
bool spool_data; /* set to spool data */
int CurVol; /* Current Volume count */
-
+ DIRRES* director; /* Director resource */
+
uint32_t FileId; /* Last file id inserted */
/* Parmaters for Open Read Session */
*
*
*/
-static int authenticate(int rcode, BSOCK *bs)
+static int authenticate(int rcode, BSOCK *bs, JCR* jcr)
{
POOLMEM *dirname;
DIRRES *director = NULL;
}
stop_bsock_timer(tid);
free_pool_memory(dirname);
+ jcr->director = director;
return 1;
}
{
BSOCK *dir = jcr->dir_bsock;
- if (!authenticate(R_DIRECTOR, dir)) {
+ if (!authenticate(R_DIRECTOR, dir, jcr)) {
bnet_fsend(dir, "%s", Dir_sorry);
Emsg1(M_ERROR, 0, _("Unable to authenticate Director at %s.\n"), dir->who);
bmicrosleep(5, 0);
Password = "@sd_password@"
}
+#
+# Restricted Director, used by tray-monitor to get the
+# status of the storage daemon
+#
+Director {
+ Name = @hostname@-mon
+ Password = "@mon_sd_password@"
+ Monitor = yes
+}
+
#
# Devices supported by this Storage daemon
# To connect, the Director's bacula-dir.conf must have the
/* Static variables */
static char derrmsg[] = "3900 Invalid command\n";
static char OKsetdebug[] = "3000 OK setdebug=%d\n";
-
+static char illegal_cmd[] = "3997 Illegal command for a Director with Monitor directive enabled\n";
/* Imported functions */
extern void terminate_child();
struct s_cmds {
const char *cmd;
int (*func)(JCR *jcr);
+ int monitoraccess; /* specify if monitors have access to this function */
};
/*
* The following are the recognized commands from the Director.
*/
static struct s_cmds cmds[] = {
- {"JobId=", job_cmd}, /* start Job */
- {"setdebug=", setdebug_cmd}, /* set debug level */
- {"cancel", cancel_cmd},
- {"label", label_cmd}, /* label a tape */
- {"relabel", relabel_cmd}, /* relabel a tape */
- {"mount", mount_cmd},
- {"unmount", unmount_cmd},
- {"status", status_cmd},
- {".status", qstatus_cmd},
- {"autochanger", autochanger_cmd},
- {"release", release_cmd},
- {"readlabel", readlabel_cmd},
- {NULL, NULL} /* list terminator */
+ {"JobId=", job_cmd, 0}, /* start Job */
+ {"setdebug=", setdebug_cmd, 0}, /* set debug level */
+ {"cancel", cancel_cmd, 0},
+ {"label", label_cmd, 0}, /* label a tape */
+ {"relabel", relabel_cmd, 0}, /* relabel a tape */
+ {"mount", mount_cmd, 0},
+ {"unmount", unmount_cmd, 0},
+ {"status", status_cmd, 1},
+ {".status", qstatus_cmd, 1},
+ {"autochanger", autochanger_cmd, 0},
+ {"release", release_cmd, 0},
+ {"readlabel", readlabel_cmd, 0},
+ {NULL, NULL} /* list terminator */
};
for (quit=0; !quit;) {
/* Read command */
if ((bnet_stat = bnet_recv(bs)) <= 0) {
- break; /* connection terminated */
+ break; /* connection terminated */
}
Dmsg1(9, "<dird: %s\n", bs->msg);
found = false;
for (i=0; cmds[i].cmd; i++) {
- if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
- if (!cmds[i].func(jcr)) { /* do command */
- quit = true; /* error, get out */
- Dmsg1(90, "Command %s requsts quit\n", cmds[i].cmd);
- }
- found = true; /* indicate command found */
- break;
- }
+ if (strncmp(cmds[i].cmd, bs->msg, strlen(cmds[i].cmd)) == 0) {
+ if ((!cmds[i].monitoraccess) && (jcr->director->monitor)) {
+ Dmsg1(100, "Command %s illegal.\n", cmds[i].cmd);
+ bnet_fsend(bs, illegal_cmd);
+ bnet_sig(bs, BNET_EOD);
+ break;
+ }
+ if (!cmds[i].func(jcr)) { /* do command */
+ quit = true; /* error, get out */
+ Dmsg1(90, "Command %s requsts quit\n", cmds[i].cmd);
+ }
+ found = true; /* indicate command found */
+ break;
+ }
}
if (!found) { /* command not found */
- bnet_fsend(bs, derrmsg);
- quit = true;
- break;
+ bnet_fsend(bs, derrmsg);
+ quit = true;
+ break;
}
}
bnet_sig(bs, BNET_TERMINATE);
{"description", store_str, ITEM(res_dir.hdr.desc), 0, 0, 0},
{"password", store_password, ITEM(res_dir.password), 0, ITEM_REQUIRED, 0},
{"enablessl", store_yesno, ITEM(res_dir.enable_ssl), 1, ITEM_DEFAULT, 0},
+ {"monitor", store_yesno, ITEM(res_dir.monitor), 1, ITEM_DEFAULT, 0},
{NULL, NULL, 0, 0, 0, 0}
};
struct DIRRES {
RES hdr;
- char *password; /* Director password */
- char *address; /* Director IP address or zero */
- int enable_ssl; /* Use SSL with this Director */
+ char *password; /* Director password */
+ char *address; /* Director IP address or zero */
+ int enable_ssl; /* Use SSL with this Director */
+ int monitor; /* Have only access to status and .status functions */
};
void changeStatusMessage(monitoritem* item, 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);
str = g_string_sized_new(64);
g_string_printf(str, "ERR=%s\n", item->D_sock->msg);
g_slist_append(*list, str);
- item->D_sock = NULL;
changeStatus(NULL, error);
changeStatusMessage(item, "Authentication error : %s", item->D_sock->msg);
+ item->D_sock = NULL;
return 0;
}
#
Monitor {
- Name = @hostname@-dir
+ Name = @hostname@-mon
}
Client {
Name = @hostname@-fd
Address = @hostname@
FDPort = @fd_port@
- Password = "@fd_password@" # password for FileDaemon
+ Password = "@mon_fd_password@" # password for FileDaemon
}
Storage {
Name = @hostname@-sd
Address = @hostname@
SDPort = @sd_port@
- Password = "@sd_password@" # password for StorageDaemon
+ Password = "@mon_sd_password@" # password for StorageDaemon
+}
+
+Director {
+ ConsoleName = Monitor
+ Name = @hostname@-dir
+ DIRport = @dir_port@
+ address = @hostname@
+ Password = "@mon_dir_password@" # password for Director
}
\ No newline at end of file