goto bail_out;
}
+ /* TODO: See priority with bandwidth parameter */
+ if (jcr->job->max_bandwidth > 0) {
+ jcr->max_bandwidth = jcr->job->max_bandwidth;
+ } else if (jcr->client->max_bandwidth > 0) {
+ jcr->max_bandwidth = jcr->client->max_bandwidth;
+ }
+
+ if (jcr->max_bandwidth > 0) {
+ send_bwlimit(jcr, jcr->Job); /* Old clients don't have this command */
+ }
+
/*
* send Storage daemon address to the File daemon
*/
static char levelcmd[] = "level = %s%s%s mtime_only=%d\n";
static char runscript[] = "Run OnSuccess=%u OnFailure=%u AbortOnError=%u When=%u Command=%s\n";
static char runbeforenow[]= "RunBeforeNow\n";
+static char bandwidthcmd[] = "setbandwidth=%lld Job=%s\n";
/* Responses received from File daemon */
static char OKinc[] = "2000 OK include\n";
static char OKRunScript[] = "2000 OK RunScript\n";
static char OKRunBeforeNow[] = "2000 OK RunBeforeNow\n";
static char OKRestoreObject[] = "2000 OK ObjectRestored\n";
+static char OKBandwidth[] = "2000 OK Bandwidth\n";
/* Forward referenced functions */
static bool send_list_item(JCR *jcr, const char *code, char *item, BSOCK *fd);
}
}
+bool send_bwlimit(JCR *jcr, const char *Job)
+{
+ BSOCK *fd = jcr->file_bsock;
+ if (jcr->FDVersion >= 4) {
+ fd->fsend(bandwidthcmd, jcr->max_bandwidth, Job);
+ if (!response(jcr, fd, OKBandwidth, "Bandwidth", DISPLAY_ERROR)) {
+ jcr->max_bandwidth = 0; /* can't set bandwidth limit */
+ return false;
+ }
+ }
+ return true;
+}
+
/*
* Send level command to FD.
* Used for backup jobs and estimate command.
extern bool send_include_list(JCR *jcr);
extern bool send_exclude_list(JCR *jcr);
extern bool send_level_command(JCR *jcr);
+extern bool send_bwlimit(JCR *jcr, const char *Job);
extern int get_attributes_and_put_in_catalog(JCR *jcr);
extern void get_attributes_and_compare_to_catalog(JCR *jcr, JobId_t JobId);
extern int put_file_into_catalog(JCR *jcr, long file_index, char *fname,
bool get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
POOL *get_pool_resource(UAContext *ua);
POOL *select_pool_resource(UAContext *ua);
+JCR *select_running_job(UAContext *ua, const char *reason);
CLIENT *get_client_resource(UAContext *ua);
int get_job_dbr(UAContext *ua, JOB_DBR *jr);
static int release_cmd(UAContext *ua, const char *cmd);
static int reload_cmd(UAContext *ua, const char *cmd);
static int setdebug_cmd(UAContext *ua, const char *cmd);
+static int setbwlimit_cmd(UAContext *ua, const char *cmd);
static int setip_cmd(UAContext *ua, const char *cmd);
static int time_cmd(UAContext *ua, const char *cmd);
static int trace_cmd(UAContext *ua, const char *cmd);
{ NT_("help"), help_cmd, _("Print help on specific command"),
NT_("add autodisplay automount cancel create delete disable\n\tenable estimate exit gui label list llist"
"\n\tmessages memory mount prune purge python quit query\n\trestore relabel release reload run status"
- "\n\tsetdebug setip show sqlquery time trace unmount umount\n\tupdate use var version wait"), false},
+ "\n\tsetbandwidth setdebug setip show sqlquery time trace unmount\n\tumount update use var version wait"), false},
{ NT_("label"), label_cmd, _("Label a tape"), NT_("storage=<storage> volume=<vol> pool=<pool>"), false},
{ NT_("list"), list_cmd, _("List objects from catalog"),
{ NT_("setdebug"), setdebug_cmd, _("Sets debug level"),
NT_("level=<nn> trace=0/1 client=<client-name> | dir | storage=<storage-name> | all"), true},
+ { NT_("setbandwidth"), setbwlimit_cmd, _("Sets bandwidth"),
+ NT_("limit=<nn> client=<client-name> jobid=<number> job=<job-name> ujobid=<unique-jobid>"), true},
+
{ NT_("setip"), setip_cmd, _("Sets new client address -- if authorized"), NT_(""), false},
{ NT_("show"), show_cmd, _("Show resource records"),
NT_("job=<xxx> | pool=<yyy> | fileset=<aaa> schedule=<sss> | client=<zzz> | disabled | all"), true},
return 1;
}
-
/*
* Cancel a job
*/
static int cancel_cmd(UAContext *ua, const char *cmd)
{
- int i, ret;
- int njobs = 0;
- JCR *jcr = NULL;
- char JobName[MAX_NAME_LENGTH];
-
- for (i=1; i<ua->argc; i++) {
- if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
- uint32_t JobId;
- JobId = str_to_int64(ua->argv[i]);
- if (!JobId) {
- break;
- }
- if (!(jcr=get_jcr_by_id(JobId))) {
- ua->error_msg(_("JobId %s is not running. Use Job name to cancel inactive jobs.\n"), ua->argv[i]);
- return 1;
- }
- break;
- } else if (strcasecmp(ua->argk[i], NT_("job")) == 0) {
- if (!ua->argv[i]) {
- break;
- }
- if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
- ua->warning_msg(_("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
- jcr = new_jcr(sizeof(JCR), dird_free_jcr);
- bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
- }
- break;
- } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
- if (!ua->argv[i]) {
- break;
- }
- if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
- ua->warning_msg(_("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
- jcr = new_jcr(sizeof(JCR), dird_free_jcr);
- bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
- }
- break;
- }
-
- }
- if (jcr) {
- if (jcr->job && !acl_access_ok(ua, Job_ACL, jcr->job->name())) {
- ua->error_msg(_("Unauthorized command from this console.\n"));
- return 1;
- }
- } else {
- /*
- * If we still do not have a jcr,
- * throw up a list and ask the user to select one.
- */
- char buf[1000];
- int tjobs = 0; /* total # number jobs */
- /* Count Jobs running */
- foreach_jcr(jcr) {
- if (jcr->JobId == 0) { /* this is us */
- continue;
- }
- tjobs++; /* count of all jobs */
- if (!acl_access_ok(ua, Job_ACL, jcr->job->name())) {
- continue; /* skip not authorized */
- }
- njobs++; /* count of authorized jobs */
- }
- endeach_jcr(jcr);
-
- if (njobs == 0) { /* no authorized */
- if (tjobs == 0) {
- ua->send_msg(_("No Jobs running.\n"));
- } else {
- ua->send_msg(_("None of your jobs are running.\n"));
- }
- return 1;
- }
-
- start_prompt(ua, _("Select Job:\n"));
- foreach_jcr(jcr) {
- char ed1[50];
- if (jcr->JobId == 0) { /* this is us */
- continue;
- }
- if (!acl_access_ok(ua, Job_ACL, jcr->job->name())) {
- continue; /* skip not authorized */
- }
- bsnprintf(buf, sizeof(buf), _("JobId=%s Job=%s"), edit_int64(jcr->JobId, ed1), jcr->Job);
- add_prompt(ua, buf);
- }
- endeach_jcr(jcr);
-
- if (do_prompt(ua, _("Job"), _("Choose Job to cancel"), buf, sizeof(buf)) < 0) {
- return 1;
- }
- if (ua->api && njobs == 1) {
- char nbuf[1000];
- bsnprintf(nbuf, sizeof(nbuf), _("Cancel: %s\n\n%s"), buf,
- _("Confirm cancel?"));
- if (!get_yesno(ua, nbuf) || ua->pint32_val == 0) {
- return 1;
- }
- } else {
- if (njobs == 1) {
- if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) {
- return 1;
- }
- }
- }
- sscanf(buf, "JobId=%d Job=%127s", &njobs, JobName);
- jcr = get_jcr_by_full_name(JobName);
- if (!jcr) {
- ua->warning_msg(_("Job \"%s\" not found.\n"), JobName);
- return 1;
- }
+ JCR *jcr = select_running_job(ua, "cancel");
+ if (!jcr) {
+ return 1;
}
-
- ret = cancel_job(ua, jcr);
+ int ret = cancel_job(ua, jcr);
free_jcr(jcr);
return ret;
}
return 1;
}
+static int setbwlimit_cmd(UAContext *ua, const char *cmd)
+{
+ CLIENT *client=NULL;
+ char Job[MAX_NAME_LENGTH];
+ *Job=0;
+ int32_t limit=-1;
+ int i;
+
+ i = find_arg_with_value(ua, "limit");
+ if (i >= 0) {
+ limit = atoi(ua->argv[i]);
+ }
+ if (limit < 0) {
+ if (!get_pint(ua, _("Enter new bandwidth limit kb/s: "))) {
+ return 1;
+ }
+ limit = ua->pint32_val * 1024; /* kb/s */
+ }
+
+ if (find_arg(ua, "job") > 0) {
+ JCR *jcr = select_running_job(ua, "limit");
+ if (jcr) {
+ jcr->max_bandwidth = limit; /* TODO: see for locking (Should be safe)*/
+ bstrncpy(Job, jcr->Job, sizeof(Job));
+ client = jcr->client;
+ free_jcr(jcr);
+ } else {
+ return 1;
+ }
+
+ } else {
+ client = get_client_resource(ua);
+ }
+
+ if (!client) {
+ return 1;
+ }
+
+ /* Connect to File daemon */
+ ua->jcr->client = client;
+ ua->jcr->max_bandwidth = limit;
+
+ /* Try to connect for 15 seconds */
+ ua->send_msg(_("Connecting to Client %s at %s:%d\n"),
+ client->name(), client->address, client->FDport);
+ if (!connect_to_file_daemon(ua->jcr, 1, 15, 0)) {
+ ua->error_msg(_("Failed to connect to Client.\n"));
+ return 1;
+ }
+ Dmsg0(120, "Connected to file daemon\n");
+ if (!send_bwlimit(ua->jcr, Job)) {
+ ua->error_msg(_("Failed to set bandwidth limit to Client.\n"));
+ }
+
+ ua->jcr->file_bsock->signal(BNET_TERMINATE);
+ ua->jcr->file_bsock->close();
+ ua->jcr->file_bsock = NULL;
+ ua->jcr->client = NULL;
+ ua->jcr->max_bandwidth = 0;
+ return 1;
+}
/*
* Set a new address in a Client resource. We do this only
}
return found;
}
+
+/* Get a running job
+ * "reason" is used in user messages
+ * can be: cancel, limit, ...
+ * Returns: NULL on error
+ * JCR on success (should be free_jcr() after)
+ */
+JCR *select_running_job(UAContext *ua, const char *reason)
+{
+ int i;
+ int njobs = 0;
+ JCR *jcr = NULL;
+ char JobName[MAX_NAME_LENGTH];
+ char temp[256];
+
+ for (i=1; i<ua->argc; i++) {
+ if (strcasecmp(ua->argk[i], NT_("jobid")) == 0) {
+ uint32_t JobId;
+ JobId = str_to_int64(ua->argv[i]);
+ if (!JobId) {
+ break;
+ }
+ if (!(jcr=get_jcr_by_id(JobId))) {
+ ua->error_msg(_("JobId %s is not running. Use Job name to %s inactive jobs.\n"), ua->argv[i], _(reason));
+ return NULL;
+ }
+ break;
+ } else if (strcasecmp(ua->argk[i], NT_("job")) == 0) {
+ if (!ua->argv[i]) {
+ break;
+ }
+ if (!(jcr=get_jcr_by_partial_name(ua->argv[i]))) {
+ ua->warning_msg(_("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
+ jcr = new_jcr(sizeof(JCR), dird_free_jcr);
+ bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
+ }
+ break;
+ } else if (strcasecmp(ua->argk[i], NT_("ujobid")) == 0) {
+ if (!ua->argv[i]) {
+ break;
+ }
+ if (!(jcr=get_jcr_by_full_name(ua->argv[i]))) {
+ ua->warning_msg(_("Warning Job %s is not running. Continuing anyway ...\n"), ua->argv[i]);
+ jcr = new_jcr(sizeof(JCR), dird_free_jcr);
+ bstrncpy(jcr->Job, ua->argv[i], sizeof(jcr->Job));
+ }
+ break;
+ }
+
+ }
+ if (jcr) {
+ if (jcr->job && !acl_access_ok(ua, Job_ACL, jcr->job->name())) {
+ ua->error_msg(_("Unauthorized command from this console.\n"));
+ return NULL;
+ }
+ } else {
+ /*
+ * If we still do not have a jcr,
+ * throw up a list and ask the user to select one.
+ */
+ char buf[1000];
+ int tjobs = 0; /* total # number jobs */
+ /* Count Jobs running */
+ foreach_jcr(jcr) {
+ if (jcr->JobId == 0) { /* this is us */
+ continue;
+ }
+ tjobs++; /* count of all jobs */
+ if (!acl_access_ok(ua, Job_ACL, jcr->job->name())) {
+ continue; /* skip not authorized */
+ }
+ njobs++; /* count of authorized jobs */
+ }
+ endeach_jcr(jcr);
+
+ if (njobs == 0) { /* no authorized */
+ if (tjobs == 0) {
+ ua->send_msg(_("No Jobs running.\n"));
+ } else {
+ ua->send_msg(_("None of your jobs are running.\n"));
+ }
+ return NULL;
+ }
+
+ start_prompt(ua, _("Select Job:\n"));
+ foreach_jcr(jcr) {
+ char ed1[50];
+ if (jcr->JobId == 0) { /* this is us */
+ continue;
+ }
+ if (!acl_access_ok(ua, Job_ACL, jcr->job->name())) {
+ continue; /* skip not authorized */
+ }
+ bsnprintf(buf, sizeof(buf), _("JobId=%s Job=%s"), edit_int64(jcr->JobId, ed1), jcr->Job);
+ add_prompt(ua, buf);
+ }
+ endeach_jcr(jcr);
+ bsnprintf(temp, sizeof(temp), _("Choose Job to %s"), _(reason));
+ if (do_prompt(ua, _("Job"), temp, buf, sizeof(buf)) < 0) {
+ return NULL;
+ }
+ if (!strcmp(reason, "cancel")) {
+ if (ua->api && njobs == 1) {
+ char nbuf[1000];
+ bsnprintf(nbuf, sizeof(nbuf), _("Cancel: %s\n\n%s"), buf,
+ _("Confirm cancel?"));
+ if (!get_yesno(ua, nbuf) || ua->pint32_val == 0) {
+ return NULL;
+ }
+ } else {
+ if (njobs == 1) {
+ if (!get_yesno(ua, _("Confirm cancel (yes/no): ")) || ua->pint32_val == 0) {
+ return NULL;
+ }
+ }
+ }
+ }
+ sscanf(buf, "JobId=%d Job=%127s", &njobs, JobName);
+ jcr = get_jcr_by_full_name(JobName);
+ if (!jcr) {
+ ua->warning_msg(_("Job \"%s\" not found.\n"), JobName);
+ return NULL;
+ }
+ }
+ return jcr;
+}
* prior to 10Mar08 no version
* 1 10Mar08
* 2 13Mar09 - added the ability to restore from multiple storages
- * 3 03Sep10 - added the restore object command for vss plugin
+ * 3 03Sep10 - added the restore object command for vss plugin 4.0
+ * 4 25Nov10 - added bandwidth command 5.1
*/
-static char OK_hello[] = "2000 OK Hello 3\n";
+static char OK_hello[] = "2000 OK Hello 4\n";
static char Dir_sorry[] = "2999 Authentication failed.\n";
static pthread_mutex_t mutex = PTHREAD_MUTEX_INITIALIZER;
static int bootstrap_cmd(JCR *jcr);
static int cancel_cmd(JCR *jcr);
static int setdebug_cmd(JCR *jcr);
+static int setbandwidth_cmd(JCR *jcr);
static int estimate_cmd(JCR *jcr);
static int hello_cmd(JCR *jcr);
static int job_cmd(JCR *jcr);
{"backup", backup_cmd, 0},
{"cancel", cancel_cmd, 0},
{"setdebug=", setdebug_cmd, 0},
+ {"setbandwidth=",setbandwidth_cmd, 0},
{"estimate", estimate_cmd, 0},
{"Hello", hello_cmd, 1},
{"fileset", fileset_cmd, 0},
static char runbefore[] = "RunBeforeJob %s";
static char runafter[] = "RunAfterJob %s";
static char runscript[] = "Run OnSuccess=%d OnFailure=%d AbortOnError=%d When=%d Command=%s";
+static char setbandwidth[]= "setbandwidth=%lld Job=%127s";
/* Responses sent to Director */
static char errmsg[] = "2999 Invalid command\n";
static char no_auth[] = "2998 No Authorization\n";
static char invalid_cmd[] = "2997 Invalid command for a Director with Monitor directive enabled.\n";
+static char OKBandwidth[] = "2000 OK Bandwidth\n";
static char OKinc[] = "2000 OK include\n";
static char OKest[] = "2000 OK estimate files=%s bytes=%s\n";
static char OKlevel[] = "2000 OK level\n";
return 1;
}
+/**
+ * Set bandwidth limit as requested by the Director
+ *
+ */
+static int setbandwidth_cmd(JCR *jcr)
+{
+ BSOCK *dir = jcr->dir_bsock;
+ int64_t bw=0;
+ JCR *cjcr;
+ char Job[MAX_NAME_LENGTH];
+ *Job=0;
+
+ if (sscanf(dir->msg, setbandwidth, &bw, Job) != 2 || bw < 0) {
+ pm_strcpy(jcr->errmsg, dir->msg);
+ dir->fsend(_("2991 Bad setbandwidth command: %s\n"), jcr->errmsg);
+ return 0;
+ }
+
+ if (*Job) {
+ if(!(cjcr=get_jcr_by_full_name(Job))) {
+ dir->fsend(_("2901 Job %s not found.\n"), Job);
+ } else {
+ if (cjcr->store_bsock) {
+ cjcr->store_bsock->set_bwlimit(bw);
+ }
+ cjcr->max_bandwidth = bw;
+ free_jcr(cjcr);
+ }
+
+ } else { /* No job requested, apply globally */
+ me->max_bandwidth = bw; /* Overwrite directive */
+ }
+
+ return dir->fsend(OKBandwidth);
+}
/**
* Set debug level as requested by the Director
sd->set_source_address(me->FDsrc_addr);
/* TODO: see if we put limit on restore and backup... */
- if (jcr->director->max_bandwidth) {
- sd->set_bwlimit(jcr->director->max_bandwidth);
-
- } else if (me->max_bandwidth) {
- sd->set_bwlimit(me->max_bandwidth);
+ if (!jcr->max_bandwidth) {
+ if (jcr->director->max_bandwidth) {
+ jcr->max_bandwidth = jcr->director->max_bandwidth;
+
+ } else if (me->max_bandwidth) {
+ jcr->max_bandwidth = me->max_bandwidth;
+ }
}
+ sd->set_bwlimit(jcr->max_bandwidth);
if (!sd->connect(jcr, 10, (int)me->SDConnectTimeout, me->heartbeat_interval,
_("Storage daemon"), jcr->stored_addr, NULL, stored_port, 1)) {
char *plugin_options; /* user set options for plugin */
bool cmd_plugin; /* Set when processing a command Plugin = */
POOLMEM *comment; /* Comment for this Job */
+ int64_t max_bandwidth; /* Bandwidth limit for this Job */
/* Daemon specific part of JCR */
/* This should be empty in the library */