From 99ba4af989cdd4f83d1118b41f0b00b014fd24d2 Mon Sep 17 00:00:00 2001 From: Marco van Wieringen Date: Sat, 20 Jun 2015 17:46:27 +0200 Subject: [PATCH] Status storage should only show configured devices. When you do a status storage from the director to a defined storage on a storage daemon you expect that it only shows you the actually configured devices in the director and not all devices configured in the storage daemon. For that to work we now send the list of devices (normally one) that are configured in the director config and use that as the selection criteria for showing the right devices only. --- src/dird/sd_cmds.c | 24 +++++++-- src/stored/dir_cmd.c | 4 +- src/stored/protos.h | 7 +++ src/stored/status.c | 118 ++++++++++++++++++++++++++++++++++++------- 4 files changed, 130 insertions(+), 23 deletions(-) diff --git a/src/dird/sd_cmds.c b/src/dird/sd_cmds.c index afc2fa9326a..0ac2e30182a 100644 --- a/src/dird/sd_cmds.c +++ b/src/dird/sd_cmds.c @@ -3,7 +3,7 @@ Copyright (C) 2000-2010 Free Software Foundation Europe e.V. Copyright (C) 2011-2012 Planets Communications B.V. - Copyright (C) 2013-2013 Bareos GmbH & Co. KG + Copyright (C) 2013-2015 Bareos GmbH & Co. KG This program is Free Software; you can redistribute it and/or modify it under the terms of version three of the GNU Affero General Public @@ -53,7 +53,7 @@ static char canceljobcmd[] = static char dotstatuscmd[] = ".status %s\n"; static char statuscmd[] = - "status\n"; + "status %s\n"; static char bandwidthcmd[] = "setbandwidth=%lld Job=%s\n"; static char pluginoptionscmd[] = @@ -772,8 +772,26 @@ void do_native_storage_status(UAContext *ua, STORERES *store, char *cmd) sd = ua->jcr->store_bsock; if (cmd) { sd->fsend(dotstatuscmd, cmd); + } else { - sd->fsend(statuscmd); + int cnt = 0; + DEVICERES *device; + POOL_MEM devicenames; + + /* + * Build a list of devicenames that belong to this storage defintion. + */ + foreach_alist(device, store->device) { + if (cnt == 0) { + pm_strcpy(devicenames, device->name()); + } else { + pm_strcat(devicenames, ","); + pm_strcat(devicenames, device->name()); + } + } + + bash_spaces(devicenames); + sd->fsend(statuscmd, devicenames.c_str()); } while (sd->recv() >= 0) { diff --git a/src/stored/dir_cmd.c b/src/stored/dir_cmd.c index c2f179f9363..09ef3b7761d 100644 --- a/src/stored/dir_cmd.c +++ b/src/stored/dir_cmd.c @@ -115,7 +115,7 @@ static char OKpluginoptions[] = extern bool finish_cmd(JCR *jcr); extern bool job_cmd(JCR *jcr); extern bool nextrun_cmd(JCR *jcr); -extern bool qstatus_cmd(JCR *jcr); +extern bool dotstatus_cmd(JCR *jcr); //extern bool query_cmd(JCR *jcr); extern bool status_cmd(JCR *sjcr); extern bool use_cmd(JCR *jcr); @@ -190,7 +190,7 @@ static struct s_cmds cmds[] = { { "setdebug=", setdebug_cmd, false }, /* Set debug level */ { "stats", stats_cmd, false }, { "status", status_cmd, true }, - { ".status", qstatus_cmd, true }, + { ".status", dotstatus_cmd, true }, { "unmount", unmount_cmd, false }, { "use storage=", use_cmd, false }, { NULL, NULL, false } /* list terminator */ diff --git a/src/stored/protos.h b/src/stored/protos.h index 4efc0873ed0..51bbeb3b5d7 100644 --- a/src/stored/protos.h +++ b/src/stored/protos.h @@ -162,6 +162,13 @@ void free_bsr(BSR *bsr); void free_restore_volume_list(JCR *jcr); void create_restore_volume_list(JCR *jcr); +/* status.c */ +bool status_cmd(JCR *jcr); +bool dotstatus_cmd(JCR *jcr); +#if defined(HAVE_WIN32) +char *bareos_status(char *buf, int buf_len); +#endif + /* read.c */ bool do_read_data(JCR *jcr); diff --git a/src/stored/status.c b/src/stored/status.c index f8936a5ced6..c4125b969c8 100644 --- a/src/stored/status.c +++ b/src/stored/status.c @@ -3,7 +3,7 @@ Copyright (C) 2003-2012 Free Software Foundation Europe e.V. Copyright (C) 2011-2012 Planets Communications B.V. - Copyright (C) 2013-2013 Bareos GmbH & Co. KG + Copyright (C) 2013-2015 Bareos GmbH & Co. KG This program is Free Software; you can redistribute it and/or modify it under the terms of version three of the GNU Affero General Public @@ -38,10 +38,12 @@ extern BSOCK *filed_chan; extern void *start_heap; /* Static variables */ -static char qstatus[] = +static char statuscmd[] = + "status %s\n"; +static char dotstatuscmd[] = ".status %127s\n"; -static char OKqstatus[] = +static char OKdotstatus[] = "3000 OK .status\n"; static char DotStatusJob[] = "JobId=%d JobStatus=%c JobErrors=%d\n"; @@ -61,14 +63,14 @@ static void list_terminated_jobs(STATUS_PKT *sp); static void list_running_jobs(STATUS_PKT *sp); static void list_jobs_waiting_on_reservation(STATUS_PKT *sp); static void list_status_header(STATUS_PKT *sp); -static void list_devices(JCR *jcr, STATUS_PKT *sp); +static void list_devices(JCR *jcr, STATUS_PKT *sp, const char *devicenames); static const char *level_to_str(int level); /* * Status command from Director */ -static void output_status(JCR *jcr, STATUS_PKT *sp) +static void output_status(JCR *jcr, STATUS_PKT *sp, const char *devicenames) { int len; POOL_MEM msg(PM_MESSAGE); @@ -93,7 +95,7 @@ static void output_status(JCR *jcr, STATUS_PKT *sp) /* * List devices */ - list_devices(jcr, sp); + list_devices(jcr, sp, devicenames); if (!sp->api) { len = Mmsg(msg, _("Used Volume status:\n")); @@ -152,7 +154,37 @@ static find_device(char *devname) } #endif -static void list_devices(JCR *jcr, STATUS_PKT *sp) +static bool need_to_list_device(const char *devicenames, const char *devicename) +{ + char *cur, *bp; + POOL_MEM namelist; + + /* + * Make a local copy that we can split on ',' + */ + pm_strcpy(namelist, devicenames); + + /* + * See if devicename is in the list. + */ + cur = namelist.c_str(); + while (cur) { + bp = strchr(cur, ','); + if (bp) { + *bp++ = '\0'; + } + + if (bstrcasecmp(cur, devicename)) { + return true; + } + + cur = bp; + } + + return false; +} + +static void list_devices(JCR *jcr, STATUS_PKT *sp, const char *devicenames) { int len; int bpb; @@ -168,6 +200,13 @@ static void list_devices(JCR *jcr, STATUS_PKT *sp) } foreach_res(changer, R_AUTOCHANGER) { + /* + * See if we need to list this autochanger. + */ + if (devicenames && !need_to_list_device(devicenames, changer->hdr.name)) { + continue; + } + len = Mmsg(msg, _("Autochanger \"%s\" with devices:\n"), changer->hdr.name); sendit(msg, len, sp); @@ -183,6 +222,30 @@ static void list_devices(JCR *jcr, STATUS_PKT *sp) } foreach_res(device, R_DEVICE) { + /* + * See if we need to check for devicenames at all. + */ + if (devicenames) { + /* + * See if this device is part of an autochanger. + */ + if (device->changer_res) { + /* + * See if we need to list this particular device part of the given autochanger. + */ + if (!need_to_list_device(devicenames, device->changer_res->hdr.name)) { + continue; + } + } else { + /* + * Try matching a non autochanger device. + */ + if (!need_to_list_device(devicenames, device->hdr.name)) { + continue; + } + } + } + dev = device->dev; if (dev && dev->is_open()) { if (dev->is_labeled()) { @@ -226,8 +289,10 @@ static void list_devices(JCR *jcr, STATUS_PKT *sp) len = Mmsg(msg, _("\nDevice %s open but no Bareos volume is currently mounted.\n"), dev->print_name()); sendit(msg, len, sp); } + trigger_device_status_hook(jcr, device, sp, bsdEventDriveStatus); send_blocked_status(dev, sp); + if (dev->can_append()) { bpb = dev->VolCatInfo.VolCatBlocks; if (bpb <= 0) { @@ -255,10 +320,12 @@ static void list_devices(JCR *jcr, STATUS_PKT *sp) edit_uint64_with_commas(bpb, b3)); sendit(msg, len, sp); } + len = Mmsg(msg, _(" Positioned at File=%s Block=%s\n"), edit_uint64_with_commas(dev->file, b1), edit_uint64_with_commas(dev->block_num, b2)); sendit(msg, len, sp); + trigger_device_status_hook(jcr, device, sp, bsdEventVolumeStatus); } else { if (dev) { @@ -877,32 +944,46 @@ static void sendit(POOL_MEM &msg, int len, STATUS_PKT *sp) */ bool status_cmd(JCR *jcr) { - BSOCK *dir = jcr->dir_bsock; + POOL_MEM devicenames; STATUS_PKT sp; + BSOCK *dir = jcr->dir_bsock; - dir->fsend("\n"); sp.bs = dir; - output_status(jcr, &sp); + devicenames.check_size(dir->msglen); + if (sscanf(dir->msg, statuscmd, devicenames.c_str()) != 1) { + pm_strcpy(jcr->errmsg, dir->msg); + dir->fsend(_("3900 No arg in status command: %s\n"), jcr->errmsg); + dir->signal(BNET_EOD); + + return false; + } + unbash_spaces(devicenames); + + dir->fsend("\n"); + output_status(jcr, &sp, devicenames.c_str()); dir->signal(BNET_EOD); + return true; } /* * .status command from Director */ -bool qstatus_cmd(JCR *jcr) +bool dotstatus_cmd(JCR *jcr) { - BSOCK *dir = jcr->dir_bsock; - POOL_MEM cmd; JCR *njcr; - s_last_job* job; + POOL_MEM cmd; STATUS_PKT sp; + s_last_job* job; + BSOCK *dir = jcr->dir_bsock; sp.bs = dir; - if (sscanf(dir->msg, qstatus, cmd.c_str()) != 1) { + cmd.check_size(dir->msglen); + if (sscanf(dir->msg, dotstatuscmd, cmd.c_str()) != 1) { pm_strcpy(jcr->errmsg, dir->msg); dir->fsend(_("3900 No arg in .status command: %s\n"), jcr->errmsg); dir->signal(BNET_EOD); + return false; } unbash_spaces(cmd); @@ -910,7 +991,7 @@ bool qstatus_cmd(JCR *jcr) Dmsg1(200, "cmd=%s\n", cmd.c_str()); if (bstrcasecmp(cmd.c_str(), "current")) { - dir->fsend(OKqstatus, cmd.c_str()); + dir->fsend(OKdotstatus, cmd.c_str()); foreach_jcr(njcr) { if (njcr->JobId != 0) { dir->fsend(DotStatusJob, njcr->JobId, njcr->JobStatus, njcr->JobErrors); @@ -918,7 +999,7 @@ bool qstatus_cmd(JCR *jcr) } endeach_jcr(njcr); } else if (bstrcasecmp(cmd.c_str(), "last")) { - dir->fsend(OKqstatus, cmd.c_str()); + dir->fsend(OKdotstatus, cmd.c_str()); if ((last_jobs) && (last_jobs->size() > 0)) { job = (s_last_job*)last_jobs->last(); dir->fsend(DotStatusJob, job->JobId, job->JobStatus, job->Errors); @@ -934,7 +1015,7 @@ bool qstatus_cmd(JCR *jcr) list_jobs_waiting_on_reservation(&sp); } else if (bstrcasecmp(cmd.c_str(), "devices")) { sp.api = true; - list_devices(jcr, &sp); + list_devices(jcr, &sp, NULL); } else if (bstrcasecmp(cmd.c_str(), "volumes")) { sp.api = true; list_volumes(sendit, &sp); @@ -954,6 +1035,7 @@ bool qstatus_cmd(JCR *jcr) return false; } dir->signal(BNET_EOD); + return true; }