- Pruning with Admin job.
- Restore of all files for a Job or set of jobs even if the file
records have been removed from the catalog.
-========= probably not in 1.38 =============
- - MaximumPartSize = bytes (SD, Device resource)
- Defines the maximum part size.
- - Requires Mount = Yes/No (SD, Device resource)
- Defines if the device require to be mounted to be read, and if it
- must be written in a special way. If it set, the following directives
- must be defined in the same Device resource:
- + Mount Point = directory
- Directory where the device must be mounted.
- + Mount Command = name-string
- Command that must be executed to mount the device. Before the command
- is executed, %a is replaced with the Archive Device, and %m with the
- Mount Point.
- + Unmount Command = name-string
- Command that must be executed to unmount the device. Before the
- command is executed, %a is replaced with the Archive Device, and
- %m with the Mount Point.
- + Write Part Command = name-string
- Command that must be executed to write a part to the device. Before
- the command is executed, %a is replaced with the Archive Device, %m
- with the Mount Point, %n with the current part number (0-based),
- and %v with the current part filename.
- + Free Space Command = name-string
- Command that must be executed to check how much free space is left
- on the device. Before the command is executed, %a is replaced with
- the Archive Device, %m with the Mount Point, %n with the current part
- number (0-based), and %v with the current part filename.
- - Write Part After Job = Yes/No (DIR, Job Resource, and Schedule Resource)
- If this directive is set to yes (default no), a new part file will be
- created after the job is finished.
-=======
For 1.39:
- Look at NDMP
General:
+Changes to 1.37.36:
+13Aug05
+- Add drive specification to mount, unmount, release, label,
+ and relabel for Autochangers. Note Dir<->SD protocol has
+ changed.
+
Changes to 1.37.35:
12Aug05
- Disable parts of NLS as the configure does not work here.
void add_prompt(UAContext *ua, const char *prompt);
int do_prompt(UAContext *ua, const char *automsg, const char *msg, char *prompt, int max_prompt);
CAT *get_catalog_resource(UAContext *ua);
-STORE *get_storage_resource(UAContext *ua, int use_default);
+STORE *get_storage_resource(UAContext *ua, bool use_default);
int get_media_type(UAContext *ua, char *MediaType, int max_media);
bool get_pool_dbr(UAContext *ua, POOL_DBR *pr);
int get_client_dbr(UAContext *ua, CLIENT_DBR *cr);
}
/* Get media type */
- if ((store = get_storage_resource(ua, 0)) != NULL) {
+ if ((store = get_storage_resource(ua, false/*no default*/)) != NULL) {
bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
} else if (!get_media_type(ua, mr.MediaType, sizeof(mr.MediaType))) {
return 1;
return 1;
}
}
- store = get_storage_resource(ua, 0);
+ store = get_storage_resource(ua, false/*no default*/);
if (store) {
do_storage_setdebug(ua, store, level, trace_flag);
return 1;
set_trace(trace_flag);
break;
case 1:
- store = get_storage_resource(ua, 0);
+ store = get_storage_resource(ua, false/*no default*/);
if (store) {
do_storage_setdebug(ua, store, level, trace_flag);
}
BSOCK *sd;
JCR *jcr = ua->jcr;
char dev_name[MAX_NAME_LENGTH];
+ int drive;
if (!open_db(ua)) {
return;
}
Dmsg2(120, "%s: %s\n", command, ua->UA_sock->msg);
- store = get_storage_resource(ua, 1);
+ store = get_storage_resource(ua, true/*use default*/);
if (!store) {
return;
}
+ drive = ua->int32_val;
- Dmsg2(120, "Found storage, MediaType=%s DevName=%s\n",
- store->media_type, store->dev_name());
+ Dmsg3(120, "Found storage, MediaType=%s DevName=%s drive=%d\n",
+ store->media_type, store->dev_name(), drive);
set_storage(jcr, store);
if (!connect_to_storage_daemon(jcr, 10, SDConnectTimeout, 1)) {
sd = jcr->store_bsock;
bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
bash_spaces(dev_name);
- bnet_fsend(sd, "%s %s", command, dev_name);
+ bnet_fsend(sd, "%s %s drive=%d", command, dev_name, drive);
while (bnet_recv(sd) >= 0) {
bsendmsg(ua, "%s", sd->msg);
}
}
/*
- * mount [storage | device] <name>
+ * mount [storage=<name>] [drive=nn]
*/
static int mount_cmd(UAContext *ua, const char *cmd)
{
/*
- * unmount [storage | device] <name>
+ * unmount [storage=<name>] [drive=nn]
*/
static int unmount_cmd(UAContext *ua, const char *cmd)
{
/*
- * release [storage | device] <name>
+ * release [storage=<name>] [drive=nn]
*/
static int release_cmd(UAContext *ua, const char *cmd)
{
/* Forward referenced functions */
static int do_label(UAContext *ua, const char *cmd, int relabel);
-static void label_from_barcodes(UAContext *ua);
+static void label_from_barcodes(UAContext *ua, int drive);
static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
- POOL_DBR *pr, int relabel, bool media_record_exits);
+ POOL_DBR *pr, int relabel, bool media_record_exits, int drive);
static vol_list_t *get_vol_list_from_SD(UAContext *ua, bool scan);
static void free_vol_list(vol_list_t *vol_list);
static bool is_cleaning_tape(UAContext *ua, MEDIA_DBR *mr, POOL_DBR *pr);
static BSOCK *open_sd_bsock(UAContext *ua);
static void close_sd_bsock(UAContext *ua);
-static char *get_volume_name_from_SD(UAContext *ua, int Slot);
+static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive);
static int get_num_slots_from_SD(UAContext *ua);
char *slot_list;
bool scan;
int max_slots;
+ int drive = -1;
if (!open_db(ua)) {
free(vl->VolName);
vl->VolName = NULL;
}
- vl->VolName = get_volume_name_from_SD(ua, vl->Slot);
+ vl->VolName = get_volume_name_from_SD(ua, vl->Slot, drive);
Dmsg2(100, "Got Vol=%s from SD for Slot=%d\n", vl->VolName, vl->Slot);
}
slot_list[vl->Slot] = 0; /* clear Slot */
bool print_reminder = true;
int ok = FALSE;
int i;
+ int drive;
bool media_record_exists = false;
static const char *barcode_keyword[] = {
"barcode",
if (!open_db(ua)) {
return 1;
}
- store = get_storage_resource(ua, 1);
+ store = get_storage_resource(ua, true/*use default*/);
if (!store) {
return 1;
}
+ drive = ua->int32_val;
set_storage(ua->jcr, store);
if (!relabel && find_arg_keyword(ua, barcode_keyword) >= 0) {
- label_from_barcodes(ua);
+ label_from_barcodes(ua, drive);
return 1;
}
}
}
- ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists);
+ ok = send_label_request(ua, &mr, &omr, &pr, relabel, media_record_exists, drive);
if (ok) {
sd = ua->jcr->store_bsock;
bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
bsendmsg(ua, _("Requesting to mount %s ...\n"), dev_name);
bash_spaces(dev_name);
- bnet_fsend(sd, "mount %s", dev_name);
+ bnet_fsend(sd, "mount %s drive=%d", dev_name, drive);
unbash_spaces(dev_name);
while (bnet_recv(sd) >= 0) {
bsendmsg(ua, "%s", sd->msg);
* Request SD to send us the slot:barcodes, then wiffle
* through them all labeling them.
*/
-static void label_from_barcodes(UAContext *ua)
+static void label_from_barcodes(UAContext *ua, int drive)
{
STORE *store = ua->jcr->store;
POOL_DBR pr;
bstrncpy(mr.MediaType, store->media_type, sizeof(mr.MediaType));
mr.Slot = vl->Slot;
- send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists);
+ send_label_request(ua, &mr, &omr, &pr, 0, media_record_exists, drive);
}
* NOTE! This routine opens the SD socket but leaves it open
*/
static bool send_label_request(UAContext *ua, MEDIA_DBR *mr, MEDIA_DBR *omr,
- POOL_DBR *pr, int relabel, bool media_record_exists)
+ POOL_DBR *pr, int relabel, bool media_record_exists,
+ int drive)
{
BSOCK *sd;
char dev_name[MAX_NAME_LENGTH];
bash_spaces(pr->Name);
if (relabel) {
bash_spaces(omr->VolumeName);
- bnet_fsend(sd, "relabel %s OldName=%s NewName=%s PoolName=%s MediaType=%s Slot=%d",
- dev_name, omr->VolumeName, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
+ bnet_fsend(sd, "relabel %s OldName=%s NewName=%s PoolName=%s "
+ "MediaType=%s Slot=%d drive=%d",
+ dev_name, omr->VolumeName, mr->VolumeName, pr->Name,
+ mr->MediaType, mr->Slot, drive);
bsendmsg(ua, _("Sending relabel command from \"%s\" to \"%s\" ...\n"),
omr->VolumeName, mr->VolumeName);
} else {
- bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d",
- dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
+ bnet_fsend(sd, "label %s VolumeName=%s PoolName=%s MediaType=%s "
+ "Slot=%d drive=%d",
+ dev_name, mr->VolumeName, pr->Name, mr->MediaType,
+ mr->Slot, drive);
bsendmsg(ua, _("Sending label command for Volume \"%s\" Slot %d ...\n"),
mr->VolumeName, mr->Slot);
- Dmsg5(100, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d\n",
- dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot);
+ Dmsg6(100, "label %s VolumeName=%s PoolName=%s MediaType=%s Slot=%d drive=%d\n",
+ dev_name, mr->VolumeName, pr->Name, mr->MediaType, mr->Slot, drive);
}
while (bnet_recv(sd) >= 0) {
}
}
-static char *get_volume_name_from_SD(UAContext *ua, int Slot)
+static char *get_volume_name_from_SD(UAContext *ua, int Slot, int drive)
{
STORE *store = ua->jcr->store;
BSOCK *sd;
bstrncpy(dev_name, store->dev_name(), sizeof(dev_name));
bash_spaces(dev_name);
/* Ask for autochanger list of volumes */
- bnet_fsend(sd, _("readlabel %s Slot=%d\n"), dev_name, Slot);
+ bnet_fsend(sd, _("readlabel %s Slot=%d drive=%d\n"), dev_name, Slot, drive);
Dmsg1(100, "Sent: %s", sd->msg);
/* Get Volume name in this Slot */
* If use_default is set, we assume that any keyword without a value
* is the name of the Storage resource wanted.
*/
-STORE *get_storage_resource(UAContext *ua, int use_default)
+STORE *get_storage_resource(UAContext *ua, bool use_default)
{
char *store_name = NULL;
STORE *store = NULL;
int i;
char ed1[50];
-
+ ua->int32_val = -2; /* dummy */
for (i=1; i<ua->argc; i++) {
+ if (strcasecmp("drive", ua->argk[i]) == 0 && ua->argv[i]) {
+ ua->int32_val = atoi(ua->argv[i]);
+ }
if (use_default && !ua->argv[i]) {
/* Ignore slots, scan and barcode(s) keywords */
- if (strncasecmp("scan", ua->argk[i], 4) == 0 ||
- strncasecmp("barcode", ua->argk[i], 7) == 0 ||
- strncasecmp("slots", ua->argk[i], 5) == 0) {
+ if (strcasecmp("scan", ua->argk[i]) == 0 ||
+ strcasecmp("barcode", ua->argk[i]) == 0 ||
+ strcasecmp("slots", ua->argk[i]) == 0) {
continue;
}
/* Default argument is storage */
if (!store) {
store = select_storage_resource(ua);
}
+ /* Get drive for autochanger if possible */
+ if (store && store->autochanger && ua->int32_val == -2) {
+ ua->cmd[0] = 0;
+ if (!get_cmd(ua, _("Enter autochanger drive [0]: "))) {
+ ua->int32_val = -1; /* None */
+ } else {
+ ua->int32_val = atoi(ua->cmd);
+ }
+ }
return store;
}
static bool unmount_cmd(JCR *jcr);
static bool autochanger_cmd(JCR *sjcr);
static bool do_label(JCR *jcr, int relabel);
-static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name);
+static DEVICE *find_device(JCR *jcr, POOL_MEM &dev_name, int drive);
static void read_volume_label(JCR *jcr, DEVICE *dev, int Slot);
static void label_volume_if_ok(JCR *jcr, DEVICE *dev, char *oldname,
char *newname, char *poolname,
DEVICE *dev;
bool ok = false;
int slot;
+ int drive;
newname = get_memory(dir->msglen+1);
oldname = get_memory(dir->msglen+1);
poolname = get_memory(dir->msglen+1);
mtype = get_memory(dir->msglen+1);
if (relabel) {
- if (sscanf(dir->msg, "relabel %127s OldName=%127s NewName=%127s PoolName=%127s MediaType=%127s Slot=%d",
- dev_name.c_str(), oldname, newname, poolname, mtype, &slot) == 6) {
+ if (sscanf(dir->msg, "relabel %127s OldName=%127s NewName=%127s PoolName=%127s "
+ "MediaType=%127s Slot=%d drive=%d",
+ dev_name.c_str(), oldname, newname, poolname, mtype,
+ &slot, &drive) == 7) {
ok = true;
}
} else {
*oldname = 0;
- if (sscanf(dir->msg, "label %127s VolumeName=%127s PoolName=%127s MediaType=%127s Slot=%d",
- dev_name.c_str(), newname, poolname, mtype, &slot) == 5) {
+ if (sscanf(dir->msg, "label %127s VolumeName=%127s PoolName=%127s "
+ "MediaType=%127s Slot=%d drive=%d",
+ dev_name.c_str(), newname, poolname, mtype, &slot, &drive) == 6) {
ok = true;
}
}
unbash_spaces(oldname);
unbash_spaces(poolname);
unbash_spaces(mtype);
- dev = find_device(jcr, dev_name);
+ dev = find_device(jcr, dev_name, drive);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
return ok;
}
-static DEVICE *find_device(JCR *jcr, POOL_MEM &devname)
+static DEVICE *find_device(JCR *jcr, POOL_MEM &devname, int drive)
{
DEVRES *device;
AUTOCHANGER *changer;
if (!device->dev->autoselect) {
continue; /* device is not available */
}
- Dmsg1(20, "Found changer device %s\n", device->hdr.name);
- found = true;
- break;
+ if (drive < 0 || drive == (int)device->dev->drive_index) {
+ Dmsg1(20, "Found changer device %s\n", device->hdr.name);
+ found = true;
+ break;
+ }
}
break; /* we found it but could not open a device */
}
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
DCR *dcr;
+ int drive;
- if (sscanf(dir->msg, "mount %127s", devname.c_str()) == 1) {
- dev = find_device(jcr, devname);
+ if (sscanf(dir->msg, "mount %127s drive=%d", devname.c_str(), &drive) == 2) {
+ dev = find_device(jcr, devname, drive);
dcr = jcr->dcr;
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
POOL_MEM devname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
+ int drive;
- if (sscanf(dir->msg, "unmount %127s", devname.c_str()) == 1) {
- dev = find_device(jcr, devname);
+ if (sscanf(dir->msg, "unmount %127s drive=%d", devname.c_str(), &drive) == 2) {
+ dev = find_device(jcr, devname, drive);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
POOL_MEM devname;
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
+ int drive;
- if (sscanf(dir->msg, "release %127s", devname.c_str()) == 1) {
- dev = find_device(jcr, devname);
+ if (sscanf(dir->msg, "release %127s drive=%d", devname.c_str(), &drive) == 2) {
+ dev = find_device(jcr, devname, drive);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
ok = true;
}
if (ok) {
- dev = find_device(jcr, devname);
+ dev = find_device(jcr, devname, -1);
dcr = jcr->dcr;
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_tape()) {
bnet_fsend(dir, _("3995 Device %s is not an autochanger.\n"),
dev->print_name());
- } else if (!dev->is_open()) {
- autochanger_cmd(dcr, dir, cmd);
/* Under certain "safe" conditions, we can steal the lock */
- } else if (dev->can_steal_lock()) {
+ } else if (!dev->is_open() || dev->can_steal_lock()) {
autochanger_cmd(dcr, dir, cmd);
} else if (dev->is_busy() || dev->is_blocked()) {
send_dir_busy_message(dir, dev);
BSOCK *dir = jcr->dir_bsock;
DEVICE *dev;
int Slot;
+ int drive;
- if (sscanf(dir->msg, "readlabel %127s Slot=%d", devname.c_str(), &Slot) == 2) {
- dev = find_device(jcr, devname);
+ if (sscanf(dir->msg, "readlabel %127s Slot=%d drive=%d", devname.c_str(),
+ &Slot, &drive) == 3) {
+ dev = find_device(jcr, devname, drive);
if (dev) {
P(dev->mutex); /* Use P to avoid indefinite block */
if (!dev->is_open()) {
/* */
#undef VERSION
-#define VERSION "1.37.35"
-#define BDATE "12 August 2005"
-#define LSMDATE "12Aug05"
+#define VERSION "1.37.36"
+#define BDATE "13 August 2005"
+#define LSMDATE "13Aug05"
/* Debug flags */
#undef DEBUG