Skip to content

Commit

Permalink
Added scheduler preview
Browse files Browse the repository at this point in the history
The new command "status scheduler" shows the status
of the bareos scheduler.
The output first shows what schedule triggers what
jobs, then the scheduler executions of the next
14 days are displayed including the overrides.

By giving the param "schedule=" the display can
be limited to a certain schedule and by giving
"days=" the timeframe for the preview can be
set.

Also, the dotcmd schedule was added, so that the
tab-completion works for giving schedules.

Fixes #14: Implement a scheduler preview for up to one year.
  • Loading branch information
pstorz authored and Marco van Wieringen committed May 5, 2013
1 parent a797f6c commit ccd4f31
Show file tree
Hide file tree
Showing 8 changed files with 201 additions and 24 deletions.
36 changes: 18 additions & 18 deletions src/console/console.c
Expand Up @@ -586,24 +586,24 @@ struct cpl_keywords_t {
};

static struct cpl_keywords_t cpl_keywords[] = {
{"pool=", ".pool" },
{"fileset=", ".fileset" },
{"client=", ".client" },
{"job=", ".jobs" },
{"restore_job=",".jobs type=R" },
{"level=", ".level" },
{"storage=", ".storage" },
{"schedule=", ".schedule" },
{"volume=", ".media" },
{"oldvolume=", ".media" },
{"volstatus=", ".volstatus" },
{"ls", ".ls" },
{"cd", ".lsdir" },
{"mark", ".ls" },
{"m", ".ls" },
{"unmark", ".lsmark" },
{"catalog=", ".catalogs" },
{"actiononpurge=", ".actiononpurge" }
{ "pool=", ".pool" },
{ "fileset=", ".fileset" },
{ "client=", ".client" },
{ "job=", ".jobs" },
{ "restore_job=",".jobs type=R" },
{ "level=", ".level" },
{ "storage=", ".storage" },
{ "schedule=", ".schedule" },
{ "volume=", ".media" },
{ "oldvolume=", ".media" },
{ "volstatus=", ".volstatus" },
{ "ls", ".ls" },
{ "cd", ".lsdir" },
{ "mark", ".ls" },
{ "m", ".ls" },
{ "unmark", ".lsmark" },
{ "catalog=", ".catalogs" },
{ "actiononpurge=", ".actiononpurge" }
};
#define key_size ((int)(sizeof(cpl_keywords)/sizeof(struct cpl_keywords_t)))

Expand Down
1 change: 1 addition & 0 deletions src/dird/protos.h
Expand Up @@ -216,6 +216,7 @@ bool do_autochanger_volume_operation(UAContext *ua, STORERES *store,

/* scheduler.c */
JCR *wait_for_next_job(char *one_shot_job_to_run);
bool is_doy_in_last_week(int year, int doy);
void term_scheduler();

/* ua_acl.c */
Expand Down
2 changes: 1 addition & 1 deletion src/dird/scheduler.c
Expand Up @@ -255,7 +255,7 @@ void term_scheduler()
* depending if the year is leap year or not, the doy of the last day of the month
* is varying one day.
*/
static bool is_doy_in_last_week(int year, int doy)
bool is_doy_in_last_week(int year, int doy)
{
int i;
int *last_dom;
Expand Down
3 changes: 2 additions & 1 deletion src/dird/ua_cmds.c
Expand Up @@ -187,7 +187,8 @@ static struct cmdstruct commands[] = {
"\twhen=<universal-time-specification>\n"
"\tcomment=<text> yes"), false },
{ NT_("status"), status_cmd, _("Report status"),
NT_("all | dir=<dir-name> | director | client=<client-name> | storage=<storage-name> slots | days=nnn"), true },
NT_("all | dir=<dir-name> | director | client=<client-name> | storage=<storage-name> slots |\n"
"\tdays=nnn | scheduler | schedule=<schedule-name>"), true },
{ NT_("setbandwidth"), setbwlimit_cmd, _("Sets bandwidth"),
NT_("limit=<nn-kbs> client=<client-name> jobid=<number> job=<job-name> ujobid=<unique-jobid>"), true },
{ NT_("setdebug"), setdebug_cmd, _("Sets debug level"),
Expand Down
15 changes: 15 additions & 0 deletions src/dird/ua_dotcmds.c
Expand Up @@ -67,6 +67,7 @@ static bool locationscmd(UAContext *ua, const char *cmd);
static bool mediacmd(UAContext *ua, const char *cmd);
static bool aopcmd(UAContext *ua, const char *cmd);
static bool catalogscmd(UAContext *ua, const char *cmd);
static bool schedulecmd(UAContext *ua, const char *cmd);

static bool dot_bvfs_lsdirs(UAContext *ua, const char *cmd);
static bool dot_bvfs_lsfiles(UAContext *ua, const char *cmd);
Expand Down Expand Up @@ -107,6 +108,7 @@ static struct cmdstruct commands[] = {
{ NT_(".pools"), poolscmd, NULL, true },
{ NT_(".quit"), dot_quit_cmd, NULL, false },
{ NT_(".sql"), sql_cmd, NULL, false },
{ NT_(".schedule"), schedulecmd, NULL, false },
{ NT_(".status"), dot_status_cmd, NULL, false },
{ NT_(".storage"), storagecmd, NULL, true },
{ NT_(".volstatus"), volstatuscmd, NULL, true },
Expand Down Expand Up @@ -1052,6 +1054,19 @@ static bool mediacmd(UAContext *ua, const char *cmd)
return true;
}

static bool schedulecmd(UAContext *ua, const char *cmd)
{
SCHEDRES *sched;

LockRes();
foreach_res(sched, R_SCHEDULE) {
ua->send_msg("%s\n", sched->hdr.name);
}
UnlockRes();
return true;
}


static bool locationscmd(UAContext *ua, const char *cmd)
{
if (!open_client_db(ua)) {
Expand Down
156 changes: 152 additions & 4 deletions src/dird/ua_status.c
Expand Up @@ -35,6 +35,7 @@ static void list_scheduled_jobs(UAContext *ua);
static void list_running_jobs(UAContext *ua);
static void list_terminated_jobs(UAContext *ua);
static void do_director_status(UAContext *ua);
static void do_scheduler_status(UAContext *ua);
static void do_all_status(UAContext *ua);
static void status_slots(UAContext *ua, STORERES *store);
static void status_content(UAContext *ua, STORERES *store);
Expand Down Expand Up @@ -148,12 +149,11 @@ int status_cmd(UAContext *ua, const char *cmd)

Dmsg1(20, "status:%s:\n", cmd);

for (i=1; i<ua->argc; i++) {
for (i = 1; i < ua->argc; i++) {
if (bstrcasecmp(ua->argk[i], NT_("all"))) {
do_all_status(ua);
return 1;
} else if (bstrcasecmp(ua->argk[i], NT_("dir")) ||
bstrcasecmp(ua->argk[i], NT_("director"))) {
} else if (bstrncasecmp(ua->argk[i], NT_("dir"), 3)) {
do_director_status(ua);
return 1;
} else if (bstrcasecmp(ua->argk[i], NT_("client"))) {
Expand All @@ -171,6 +171,9 @@ int status_cmd(UAContext *ua, const char *cmd)
}
}
return 1;
} else if (bstrncasecmp(ua->argk[i], NT_("sched"), 5)) {
do_scheduler_status(ua);
return 1;
} else {
store = get_storage_resource(ua, false/*no default*/);
if (store) {
Expand Down Expand Up @@ -202,7 +205,7 @@ int status_cmd(UAContext *ua, const char *cmd)
}
/* If no args, ask for status type */
if (ua->argc == 1) {
char prmt[MAX_NAME_LENGTH];
char prmt[MAX_NAME_LENGTH];

start_prompt(ua, _("Status available for:\n"));
add_prompt(ua, NT_("Director"));
Expand Down Expand Up @@ -382,6 +385,151 @@ void list_dir_status_header(UAContext *ua)
}
}

static void do_scheduler_status(UAContext *ua)
{
int i, hour, mday, wday, month, wom, woy, yday;
int days = 14; /* Default days for preview */
bool is_last_week = false, /* Are we in the last week of a month? */
schedulegiven = false;
char dt[MAX_TIME_LENGTH];
time_t time_to_check, now, runtime;
char level[15];
char schedulename[MAX_NAME_LENGTH];
const int seconds_per_day = 86400; /* Number of seconds in one day */
struct tm tm;
SCHEDRES *sched;
JOBRES *job;
RUNRES *run;

now = time(NULL); /* Initialize to now */
time_to_check = now;

i = find_arg_with_value(ua, NT_("days"));
if (i >= 0) {
days = atoi(ua->argv[i]);
if (((days < 0) || (days > 366)) && !ua->api) {
ua->send_msg(_("Ignoring invalid value for days. Max is 366.\n"));
days = 14;
}
}

/*
* Schedule given?
*/
i = find_arg_with_value(ua, NT_("schedule"));
if (i >= 0) {
bstrncpy(schedulename, ua->argv[i], sizeof(schedulename));
schedulegiven = true;
}

ua->send_msg("Scheduler Jobs:\n\n");
ua->send_msg("Schedule Jobs Triggered\n");
ua->send_msg("===========================================================\n");

LockRes();
foreach_res(sched, R_SCHEDULE) {
if (schedulegiven) {
if (!bstrcmp(sched->hdr.name, schedulename)) {
continue;
}
}
ua->send_msg("%s\n", sched->hdr.name);
foreach_res(job, R_JOB) {
if (job->schedule && bstrcmp(sched->hdr.name, job->schedule->hdr.name)) {
ua->send_msg(" %s\n", job->name());
}
}
ua->send_msg("\n");
}
UnlockRes();

ua->send_msg("====\n\n");
ua->send_msg("Scheduler Preview for %d days:\n\n", days);
ua->send_msg("Date Schedule Overrides\n");
ua->send_msg("==============================================================\n");

while (time_to_check < (now + (days * seconds_per_day))) {
(void)localtime_r(&time_to_check, &tm);
hour = tm.tm_hour;
mday = tm.tm_mday - 1;
wday = tm.tm_wday;
month = tm.tm_mon;
wom = mday / 7;
woy = tm_woy(time_to_check); /* Get week of year */
yday = tm.tm_yday; /* Get day of year */

is_last_week = is_doy_in_last_week(tm.tm_year + 1900 , yday);

LockRes();
foreach_res(sched, R_SCHEDULE) {
if (schedulegiven) {
if (!bstrcmp(sched->hdr.name, schedulename)) {
continue;
}
}

for (run = sched->run; run; run = run->next) {
bool run_now;

run_now = bit_is_set(hour, run->hour) &&
bit_is_set(mday, run->mday) &&
bit_is_set(wday, run->wday) &&
bit_is_set(month, run->month) &&
(bit_is_set(wom, run->wom) ||
(run->last_set && is_last_week)) &&
bit_is_set(woy, run->woy);

if (run_now) {
/*
* Find time (time_t) job is to be run
*/
(void)localtime_r(&time_to_check, &tm); /* Reset tm structure */
tm.tm_min = run->minute; /* Set run minute */
tm.tm_sec = 0; /* Zero secs */
runtime = mktime(&tm);
bstrftime_wd(dt, sizeof(dt), runtime);

ua->send_msg(dt);
ua->send_msg(" %-22.22s ", sched->hdr.name);

bstrncpy(level, level_to_str(run->level), sizeof(level));
ua->send_msg("Level=%s ", level);

if (run->Priority) {
ua->send_msg("Priority=%d ", run->Priority);
}

if (run->spool_data_set) {
ua->send_msg("Spool Data=%d ", run->spool_data);
}

if (run->accurate_set) {
ua->send_msg("Accurate=%d ", run->accurate);
}

if (run->pool) {
ua->send_msg("Pool=%s ", run->pool->name());
}

if (run->storage) {
ua->send_msg("Storage=%s ", run->storage->name());
}

if (run->msgs) {
ua->send_msg("Messages=%s ", run->msgs->name());
}

ua->send_msg("\n");
}
}
}
UnlockRes();

time_to_check += 3600; /* next hour */
}
ua->send_msg("====\n");
}

static void do_director_status(UAContext *ua)
{
list_dir_status_header(ua);
Expand Down
11 changes: 11 additions & 0 deletions src/lib/btime.c
Expand Up @@ -79,6 +79,17 @@ char *bstrftime_ny(char *dt, int maxlen, utime_t utime)
return dt;
}

/* Formatted time for user display with weekday: weekday dd-Mon hh:mm */
char *bstrftime_wd(char *dt, int maxlen, utime_t utime)
{
time_t time = (time_t)utime;
struct tm tm;

/* ***FIXME**** the format and localtime_r() should be user configurable */
(void)localtime_r(&time, &tm);
strftime(dt, maxlen, "%a %d-%b %H:%M", &tm);
return dt;
}

/* Formatted time for user display: dd-Mon-yy hh:mm (no century) */
char *bstrftime_nc(char *dt, int maxlen, utime_t utime)
Expand Down
1 change: 1 addition & 0 deletions src/lib/btime.h
Expand Up @@ -35,6 +35,7 @@ char *bstrftime(char *dt, int maxlen, utime_t tim);
char *bstrftimes(char *dt, int maxlen, utime_t tim);
char *bstrftime_ny(char *dt, int maxlen, utime_t tim);
char *bstrftime_nc(char *dt, int maxlen, utime_t tim);
char *bstrftime_wd(char *dt, int maxlen, utime_t tim);
utime_t str_to_utime(const char *str);


Expand Down

0 comments on commit ccd4f31

Please sign in to comment.