Skip to content
Snippets Groups Projects
Commit 168eec58 authored by Steven Murray's avatar Steven Murray Committed by Steven Murray
Browse files

My previous commit was great if all you wanted to do was build CASTOR from the...

My previous commit was great if all you wanted to do was build CASTOR from the trunk directory.  Unfortunatley my previous commit is a failure if you wish to build CASTOR from a sub-directory.  Reverse merging my last commit in order to repair my mistake.
parent 513a895e
No related branches found
No related tags found
No related merge requests found
......@@ -5,13 +5,9 @@ COMM
COMM Make SCSI media changer server programs.
TapeDependsOnLibrary(common,castorcommon)
TapeDependsOnLibrary(upv,castorupv)
TapeDependsOnLibrary(dlf,castordlf)
TapeDependsOnLibrary(tape,castortape)
TAPELIB = DepSharedLibraryTargetName(tape,castortape)
RMCD_OBJS = rmc_serv.o rmc_procreq.o rmclogit.o sendrep.o usrmsg.o
TapeProgramTarget(rmcd,$(RMCD_OBJS),,,755)
TapeProgramTarget(rmcd,$(RMCD_OBJS),$(TAPELIB),$(TAPELIB),755)
ADMMANPAGE(rmcd)
TapeMakeDir($(LOGPATH),0755)
LOGROTATE(castor-rmc-server,installtape)
......@@ -26,3 +22,10 @@ CLIENTLIBMANPAGE(rmc_import)
CLIENTLIBMANPAGE(rmc_mount)
CLIENTLIBMANPAGE(rmc_read_elem_status)
CLIENTLIBMANPAGE(rmc_seterrbuf)
RMCLIB_OBJS = rmc_dismount.o rmc_errmsg.o rmc_export.o rmc_find_cartridge.o rmc_get_geometry.o rmc_import.o rmc_mount.o rmc_read_elem_status.o send2rmc.o
TapeSharedLibraryTarget(castorrmc, $(RMCLIB_OBJS),,)
RMCLIB = DepSharedLibraryTargetName(rmc,castorrmc)
TapeProgramTarget(smc,smc.o,$(RMCLIB),$(RMCLIB),6755)
EXEMANPAGE(smc)
/*
* Copyright (C) 1998-2003 by CERN/IT/PDP/DM
* All rights reserved
*/
#include <errno.h>
#include <fcntl.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include "Ctape.h"
#include "rmc_api.h"
#include "serrno.h"
#include "smc.h"
#include "getconfent.h"
/* exit codes */
#define USERR 1
extern char *optarg;
static void usage(char *cmd)
{
fprintf (stderr, "usage: %s ", cmd);
fprintf (stderr,
"-d -D drive_ordinal -h rmcserver -l loader [-V vid] [-v]\n"
"\t-e -h rmcserver -l loader -V vid [-v]\n"
"\t-i -h rmcserver -l loader [-V vid] [-v]\n"
"\t-m -D drive_ordinal -h rmcserver [-I] -l loader -V vid [-v]\n"
"\t-q D [-D drive_ordinal] -h rmcserver -l loader [-v]\n"
"\t-q L -h rmcserver -l loader [-v]\n"
"\t-q S -h rmcserver -l loader [-N nbelem] [-S starting_slot] [-v]\n"
"\t-q V -h rmcserver -l loader [-N nbelem] [-V vid] [-v]\n");
}
static int smc_qdrive (char *rmchost,
int fd,
char *loader,
struct robot_info *robot_info,
int drvord,
int verbose)
{
int c;
struct smc_element_info *element_info;
int i;
int nbelem;
char *pstatus;
char *smcLibraryType;
char useSpectraLib;
if (drvord < 0) {
drvord = 0;
nbelem = robot_info->device_count;
} else {
nbelem = 1;
}
if ((element_info = malloc (nbelem * sizeof(struct smc_element_info))) == NULL) {
fprintf (stderr, SR012);
return (USERR);
}
if ((c = rmc_read_elem_status (rmchost, loader, 4,
robot_info->device_start+drvord, nbelem, element_info)) < 0) {
free (element_info);
return (c);
}
if (verbose)
printf ("Drive Ordinal\tElement Addr.\tStatus\t\tVid\n");
useSpectraLib=0;
smcLibraryType = getconfent("SMC","LIBRARY_TYPE",0);
if (NULL != smcLibraryType &&
0 == strcasecmp(smcLibraryType,"SPECTRA")) {
useSpectraLib = 1;
}
for (i = 0; i < c; i++) {
if (((element_info+i)->state & 0x1) == 0)
pstatus = "free";
else if ((element_info+i)->state & 0x4)
pstatus = "error";
else if ((element_info+i)->state & 0x8 && !useSpectraLib)
pstatus = "unloaded";
else
pstatus = "loaded";
printf (" %2d\t %d\t%s\t%s\n",
(element_info+i)->element_address-robot_info->device_start,
(element_info+i)->element_address, pstatus,
(element_info+i)->name);
}
free (element_info);
return (0);
}
static int smc_qlib (struct robot_info *robot_info)
{
printf ("Vendor/Product/Revision = <%s>\n", robot_info->inquiry);
printf ("Transport Count = %d, Start = %d\n",
robot_info->transport_count, robot_info->transport_start);
printf ("Slot Count = %d, Start = %d\n",
robot_info->slot_count, robot_info->slot_start);
printf ("Port Count = %d, Start = %d\n",
robot_info->port_count, robot_info->port_start);
printf ("Device Count = %d, Start = %d\n",
robot_info->device_count, robot_info->device_start);
return (0);
}
static int smc_qport (char *rmchost,
int fd,
char *loader,
struct robot_info *robot_info,
int verbose)
{
int c;
struct smc_element_info *element_info;
int i;
int nbelem;
char *pstatus;
nbelem = robot_info->port_count;
if ((element_info = malloc (nbelem * sizeof(struct smc_element_info))) == NULL) {
fprintf (stderr, SR012);
return (USERR);
}
if ((c = rmc_read_elem_status (rmchost, loader, 3,
robot_info->port_start, nbelem, element_info)) < 0) {
free (element_info);
return (serrno - ERMCRBTERR);
}
if (verbose)
printf ("Element Addr.\tVid\tImpExp\n");
for (i = 0; i < c; i++) {
if (((element_info+i)->state & 0x1) == 0)
pstatus = "";
else if (((element_info+i)->state & 0x2) == 0)
pstatus = "export";
else
pstatus = "import";
printf (" %4d\t%s\t%s\n",
(element_info+i)->element_address,
(element_info+i)->name, pstatus);
}
free (element_info);
return (0);
}
static int smc_qslot (char *rmchost,
int fd,
char *loader,
struct robot_info *robot_info,
int slotaddr,
int nbelem,
int verbose)
{
int c;
struct smc_element_info *element_info;
int i;
if (nbelem == 0) {
if (slotaddr < 0)
nbelem = robot_info->slot_count;
else
nbelem = 1;
}
if (slotaddr < 0)
slotaddr = 0;
if ((element_info = malloc (nbelem * sizeof(struct smc_element_info))) == NULL) {
fprintf (stderr, SR012);
return (USERR);
}
if ((c = rmc_read_elem_status (rmchost, loader, 2, slotaddr,
nbelem, element_info)) < 0) {
free (element_info);
return (serrno - ERMCRBTERR);
}
if (verbose)
printf ("Element Addr.\tVid\n");
for (i = 0; i < c; i++) {
printf (" %4d\t%s\n",
element_info[i].element_address, element_info[i].name);
}
free (element_info);
return (0);
}
static int smc_qvid (char *rmchost,
int fd,
char *loader,
struct robot_info *robot_info,
char *reqvid,
int nbelem,
int verbose)
{
int c;
struct smc_element_info *element_info;
int i;
char *ptype;
static char ptypes[5][6] = {"", "hand", "slot", "port", "drive"};
char *vid;
if (*reqvid)
vid = reqvid;
else
vid = "*";
if (nbelem == 0) {
if (strchr (vid, '*') || strchr (vid, '?')) /* pattern matching */
nbelem = robot_info->transport_count + robot_info->slot_count +
robot_info->port_count + robot_info->device_count;
else
nbelem = 1;
}
if ((element_info = malloc (nbelem * sizeof(struct smc_element_info))) == NULL) {
fprintf (stderr, SR012);
return (USERR);
}
if ((c = rmc_find_cartridge (rmchost, loader, vid, 0, 0, nbelem,
element_info)) < 0) {
free (element_info);
return (serrno - ERMCRBTERR);
}
if (verbose)
printf ("Vid\tElement Addr.\tElement Type\n");
for (i = 0; i < c; i++) {
ptype = ptypes[(element_info+i)->element_type];
if ((element_info+i)->element_type == 3) {
if (((element_info+i)->state & 0x2) == 0) {
ptype = "export";
} else {
ptype = "import";
}
}
printf ("%s\t %4d\t%s\n",
(element_info+i)->name, (element_info+i)->element_address,
ptype);
}
free (element_info);
return (0);
}
int main(int argc,
char **argv)
{
int c;
char *dp;
int drvord = -1;
int errflg = 0;
const int fd = -1;
int invert = 0;
char loader[32];
int n;
int nbelem = 0;
char qry_type = 0;
char req_type = 0;
struct robot_info robot_info;
char rmchost[CA_MAXHOSTNAMELEN+1];
int slotaddr = -1;
int targetslotaddr = -1;
int verbose = 0;
char vid[7];
/* parse and check command options */
memset(loader, '\0', sizeof(loader));
memset(rmchost, '\0', sizeof(rmchost));
memset (vid, '\0', sizeof(vid));
while ((c = getopt (argc, argv, "D:deh:Iil:mN:q:S:V:vT:")) != EOF) {
switch (c) {
case 'D': /* drive ordinal */
drvord = strtol (optarg, &dp, 10);
if (*dp != '\0' || drvord < 0) {
fprintf (stderr, SR001);
errflg++;
}
break;
case 'd': /* demount */
case 'e': /* export */
if (req_type) {
fprintf (stderr, SR002, req_type, c);
errflg++;
} else
req_type = c;
break;
case 'h': /* remote server */
if(strlen(optarg) > (sizeof(rmchost) - 1)) {
fprintf(stderr,
"rmcserver %s must be at most %d characters long\n",
optarg, (int)(sizeof(rmchost) - 1));
errflg++;
} else {
strncpy (rmchost, optarg, sizeof(rmchost) - 1);
}
break;
case 'i': /* import */
if (req_type) {
fprintf (stderr, SR002, req_type, c);
errflg++;
} else
req_type = c;
break;
case 'I': /* invert */
invert = 1;
break;
case 'l': /* loader */
if(strlen(optarg) > (sizeof(loader) - 1)) {
fprintf(stderr,
"loader %s must be at most %d characters long\n",
optarg, (int)(sizeof(loader) - 1));
errflg++;
} else {
strncpy (loader, optarg, sizeof(loader) - 1);
}
break;
case 'm': /* mount */
if (req_type) {
fprintf (stderr, SR002, req_type, c);
errflg++;
} else
req_type = c;
break;
case 'N': /* number of elements */
nbelem = strtol (optarg, &dp, 10);
if (*dp != '\0' || nbelem <= 0) {
fprintf (stderr, SR010);
errflg++;
}
break;
case 'q': /* query */
if (req_type) {
fprintf (stderr, SR002, req_type, c);
errflg++;
} else {
req_type = c;
qry_type = *optarg;
if (qry_type != 'D' && qry_type != 'L' &&
qry_type != 'P' && qry_type != 'S' &&
qry_type != 'V') {
fprintf (stderr, SR003, qry_type);
errflg++;
}
}
break;
case 'S': /* starting slot */
slotaddr = strtol (optarg, &dp, 10);
if (*dp != '\0' || slotaddr < 0) {
fprintf (stderr, SR001);
errflg++;
}
break;
case 'T': /* Target slot */
targetslotaddr = strtol (optarg, &dp, 10);
if (*dp != '\0' || targetslotaddr < 0) {
fprintf (stderr, SR001);
errflg++;
}
break;
case 'V': /* vid */
n = strlen (optarg);
if (n > 6) {
fprintf (stderr, SR004, optarg);
errflg++;
} else {
strcpy (vid, optarg);
UPPER (vid);
}
break;
case 'v':
verbose = 1;
break;
case '?':
errflg++;
break;
}
}
if (req_type && *loader == '\0') {
fprintf (stderr, SR005);
errflg++;
}
if (req_type && *rmchost == '\0') {
fprintf (stderr, "rmcserver must be specified\n");
errflg++;
}
if (req_type == 'd' && drvord < 0) {
fprintf (stderr, SR006);
errflg++;
}
if (req_type == 'e' && *vid =='\0') {
fprintf (stderr, SR011);
errflg++;
}
if (req_type == 'm' && (*vid =='\0' || drvord < 0)) {
fprintf (stderr, SR007);
errflg++;
}
if (errflg || req_type == 0) {
usage (argv[0]);
exit (USERR);
}
/* get robot geometry */
if (rmc_get_geometry (rmchost, loader, &robot_info)) {
exit (serrno);
}
if (drvord >= robot_info.device_count) {
fprintf (stderr, SR008, robot_info.device_count);
exit (USERR);
}
if (slotaddr > (robot_info.slot_count + robot_info.slot_start)) {
fprintf (stderr, SR016, robot_info.slot_count + robot_info.slot_start);
exit (USERR);
}
/* process request */
switch (req_type) {
case 'd':
if ((c = rmc_dismount (rmchost, loader, vid, drvord, 0)) < 0) {
c = (serrno == SECOMERR) ? RBT_FAST_RETRY : serrno - ERMCRBTERR;
}
break;
case 'e':
if ((c = rmc_export (rmchost, loader, vid)) < 0) {
c = (serrno == SECOMERR) ? RBT_FAST_RETRY : serrno - ERMCRBTERR;
}
break;
case 'i':
if ((c = rmc_import (rmchost, loader, vid)) < 0) {
c = (serrno == SECOMERR) ? RBT_FAST_RETRY : serrno - ERMCRBTERR;
}
break;
case 'm':
if ((c = rmc_mount (rmchost, loader, vid, invert, drvord)) < 0) {
c = (serrno == SECOMERR) ? RBT_FAST_RETRY : serrno - ERMCRBTERR;
}
break;
case 'q':
switch (qry_type) {
case 'D':
c = smc_qdrive (rmchost, fd, loader, &robot_info, drvord,
verbose);
break;
case 'L':
c = smc_qlib (&robot_info);
break;
case 'P':
c = smc_qport (rmchost, fd, loader, &robot_info, verbose);
break;
case 'S':
c = smc_qslot (rmchost, fd, loader, &robot_info, slotaddr,
nbelem, verbose);
break;
case 'V':
c = smc_qvid (rmchost, fd, loader, &robot_info, vid,
nbelem, verbose);
break;
}
break;
}
exit (c);
}
.\" Copyright (C) 1998-2002 by CERN/IT/PDP/DM
.\" All rights reserved
.\"
.TH SMC 1 "$Date: 2005/06/16 09:43:12 $" CASTOR "Ctape User Commands"
.SH NAME
smc \- command line interface to drive robotic devices through SCSI
.SH SYNOPSIS
.B smc
.BI -d
.BI -D " drive_ordinal"
.BI -h " rmcserver"
.BI -l " loader"
[
.BI -V " vid"
] [
.BI -v
]
.br
.B smc
.BI -e
.BI -h " rmcserver"
.BI -l " loader"
.BI -V " vid"
[
.BI -v
]
.br
.B smc
.BI -i
.BI -h " rmcserver"
.BI -l " loader"
[
.BI -V " vid"
] [
.BI -v
]
.br
.B smc
.BI -m
.BI -D " drive_ordinal"
.BI -h " rmcserver"
[
.BI -I
]
.BI -l " loader"
.BI -V " vid"
[
.BI -v
]
.br
.B smc
.BI -h " rmcserver"
.BI -l " loader"
.B -q D
[
.BI -D " drive_ordinal"
]
[
.BI -v
]
.br
.B smc
.BI -h " rmcserver"
.BI -l " loader"
.B -q L
[
.BI -v
]
.br
.B smc
.BI -h " rmcserver"
.BI -l " loader"
.B -q P
[
.BI -v
]
.br
.B smc
.BI -h " rmcserver"
.BI -l " loader"
.B -q S
[
.BI -N " nbelem"
] [
.BI -S " starting_slot"
] [
.BI -v
]
.br
.B smc
.BI -h " rmcserver"
.BI -l " loader"
.B -q V
[
.BI -N " nbelem"
] [
.BI -V " vid"
] [
.BI -v
]
.SH DESCRIPTION
.B smc
is a program allowing to mount, dismount, export volumes in a robotic
library through SCSI. It allows also to query various elements of the library.
.SH OPTIONS
.TP
.BI \-d
triggers a dismount operation. The drive must be already unloaded.
The drive must be specified while the vid of the cartridge is optional.
If
.B -V
is specified, the vid must match the vid on the cartridge to be dismounted.
.TP
.BI \-e
exports a volume. The cartridge must be in a storage slot (not a drive).
The vid must be specified.
.TP
.BI \-h " rmcserver"
specifies the hostname of the machine where the Remote SCSI Media Changer
daemon runs. This parameter is mandatory.
.TP
.BI \-I
flips media side.
.TP
.BI \-i
imports either a specific volume indicated by
.B -V
option or all volumes in state "import" in the import/export cells.
.TP
.BI \-l " loader"
specifies the picker SCSI device. This parameter is mandatory.
.TP
.BI \-m
triggers a mount operation. The drive must be free.
The drive and the vid must be specified.
.TP
.BI \-N " nbelem"
allows to specify the maximum number of entries to be reported.
.TP
.BI \-q " query_type"
queries the library and produce a report about the status of various elements
in the library.
.I query_type
may be one of the following:
.RS
.TP
.B D
produce a list of drives with their status and the vid of the mounted tape
if any. Unless a specific drive is also given with the option
.BR -D ,
the status of all drives is reported.
.TP
.B L
prints the result of the INQUIRY command (Vendor/Product/Revision).
It gives also the starting address and the number of slots, drives, ports
and transports (hands) in the library.
.TP
.B P
prints the status of import/export slots.
.TP
.B S
prints the status of slots. By default all slots are reported, but the
starting address may be specified with the option
.B -S
and the number of elements to be reported may be given by the option
.BR -N .
.TP
.B V
prints the status of volumes. A single vid or a pattern may also be specified
with the option
.BR -V .
.RE
.TP
.B \-S " starting_slot"
specifies the starting slot address for the query operation.
.TP
.B \-V " vid"
A full vid or a pattern may be specified. In the latter case wild card
characters '*' and '?' may be used but must be escaped because of the shell.
.TP
.B \-v
verbose mode. On query requests it prints headers on top of the columns.
.SH EXAMPLES
.LP
To mount the volume JK2005 on drive 1:
.br
.RS
.B "smc -l /dev/smc01 -m -D 1 -V JK2005"
.RE
.LP
To dismount the volume present on drive 1 after checking the vid:
.br
.RS
.B "smc -l /dev/smc01 -d -D 1 -V JK2005"
.RE
.LP
To query the main charateristics of the library:
.br
.RS
.B "smc -l /dev/smc01 -q L"
.sp
.nf
Vendor/Product/Revision = <STK 9714 1500>
Transport Count = 1, Start = 1000
Slot Count = 99, Start = 0
Port Count = 1, Start = 1010
Device Count = 2, Start = 1030
.fi
.RE
.LP
To query the status of all the drives:
.br
.RS
.B "smc -l /dev/smc01 -q D -v"
.sp
.nf
.cs R 20
Drive Ordinal Element Addr. Status Vid
0 1030 free
1 1031 unloaded JK2005
.cs R
.fi
.RE
.LP
To get the list of a few slots in the library:
.br
.RS
.B "smc -l /dev/smc01 -q S -S 20 -N 10 -v"
.sp
.nf
.cs R 20
Element Addr. Vid
20 JK2021
21 JK2022
22 JK2023
23 JK2024
24 JK2025
25 JK2026
26 JK2027
27 JK2028
28 JK2029
29 JK2030
.cs R
.fi
.RE
.LP
To get the status of volumes for which the vid starts with JK200
.br
.RS
.B "smc -l /dev/smc01 -q V -V 'JK200*' -v"
.sp
.nf
.cs R 20
Vid Element Addr. Element Type
JK2001 0 slot
JK2002 1 slot
JK2003 2 slot
JK2004 3 slot
JK2006 5 slot
JK2007 6 slot
JK2008 7 slot
JK2009 8 slot
JK2005 1031 drive
.cs R
.fi
.RE
.SH RETURN CODES
0 Ok.
.br
1 Parameter error or unrecoverable error (just log it).
.br
2 Should release drive & retry in 600 seconds.
.br
3 Should retry in 60 seconds.
.br
4 Should do first a demount force.
.br
5 Should configure the drive down.
.br
6 Should send a msg to operator and exit.
.br
7 Ops msg (nowait) + release drive + slow retry.
.br
8 Should send a msg to operator and wait.
.br
9 Should unload the tape and retry demount.
.br
16 Robot busy.
.SH AUTHOR
\fBCASTOR\fP Team <castor.support@cern.ch>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment