/* Values for the UV_RestoreVolume flags parameter */
#define RV_FULLRST 0x1
#define RV_OFFLINE 0x2
+#define RV_RDONLY 0x10000
#endif /* _VOLSER_ */
cmd_AddParm(ts, "-noauth", CMD_FLAG, CMD_OPTIONAL, "don't authenticate");\
cmd_AddParm(ts, "-localauth",CMD_FLAG,CMD_OPTIONAL,"use server tickets");\
cmd_AddParm(ts, "-verbose", CMD_FLAG, CMD_OPTIONAL, "verbose");\
+cmd_AddParm(ts, "-crypt", CMD_FLAG, CMD_OPTIONAL, "encrypt commands");\
#define ERROR_EXIT(code) {error=(code); goto error_exit;}
extern struct rx_connection *UV_Bind();
extern struct rx_securityClass *rxnull_NewClientSecurityObject();
extern int UV_SetSecurity();
+extern int UV_SetVolumeInfo();
+extern int vsu_SetCrypt();
extern VL_SetLock();
extern VL_ReleaseLock();
extern VL_DeleteEntry();
}
/*------------------------------------------------------------------------
+ * PRIVATE SetFields
+ *
+ * Description:
+ * Routine used to change the status of a single volume.
+ *
+ * Arguments:
+ * as : Ptr to parsed command line arguments.
+ *
+ * Returns:
+ * 0 for a successful operation,
+ * Otherwise, one of the ubik or VolServer error values.
+ *
+ * Environment:
+ * Nothing interesting.
+ *
+ * Side Effects:
+ * As advertised.
+ *------------------------------------------------------------------------
+ */
+static SetFields(as)
+register struct cmd_syndesc *as;
+{
+ struct nvldbentry entry;
+ afs_int32 vcode = 0;
+ volintInfo info;
+ afs_int32 volid;
+ afs_int32 code, err;
+ afs_int32 aserver, apart;
+ int previdx = -1;
+
+ volid = vsu_GetVolumeID(as->parms[0].items->data, cstruct, &err); /* -id */
+ if (volid == 0) {
+ if (err) PrintError("", err);
+ else fprintf(STDERR, "Unknown volume ID or name '%s'\n", as->parms[0].items->data);
+ return -1;
+ }
+
+ code = VLDB_GetEntryByID (volid, RWVOL, &entry);
+ if (code) {
+ fprintf(STDERR, "Could not fetch the entry for volume number %u from VLDB \n",volid);
+ return (code);
+ }
+ MapHostToNetwork(&entry);
+
+ GetServerAndPart(&entry, RWVOL, &aserver, &apart, &previdx);
+ if (previdx == -1) {
+ fprintf(STDERR,"Volume %s does not exist in VLDB\n\n", as->parms[0].items->data);
+ return (ENOENT);
+ }
+
+ memset(&info, 0, sizeof(info));
+ info.volid = volid;
+ info.type = RWVOL;
+ info.dayUse = -1;
+ info.maxquota = -1;
+ info.flags = -1;
+ info.spare0 = -1;
+ info.spare1 = -1;
+ info.spare2 = -1;
+ info.spare3 = -1;
+
+ if (as->parms[1].items) {
+ /* -max <quota> */
+ code = util_GetInt32(as->parms[1].items->data, &info.maxquota);
+ if (code) {
+ fprintf(STDERR,"invalid quota value\n");
+ return code;
+ }
+ }
+ if (as->parms[2].items) {
+ /* -clearuse */
+ info.dayUse = 0;
+ }
+ code = UV_SetVolumeInfo(aserver, apart, volid, &info);
+ if (code)
+ fprintf(STDERR,"Could not update volume info fields for volume number %u\n",volid);
+ return (code);
+}
+
+/*------------------------------------------------------------------------
* PRIVATE volOnline
*
* Description:
{
afs_int32 avolid, aserver, apart, code,vcode, err;
afs_int32 aoverwrite = ASK;
- int restoreflags;
+ int restoreflags, readonly = 0, offline = 0, voltype = RWVOL;
char prompt;
char afilename[NameLen], avolname[VOLSER_MAXVOLNAME +1],apartName[10];
char volname[VOLSER_MAXVOLNAME +1];
exit(1);
}
}
+ if (as->parms[6].items) offline = 1;
+ if (as->parms[7].items) {
+ readonly = 1;
+ voltype = ROVOL;
+ }
aserver = GetServer(as->parms[0].items->data);
if (aserver == 0) {
fprintf(STDERR,"Volume does not exist; Will perform a full restore\n");
}
- else if (Lp_GetRwIndex(&entry) == -1) { /* RW volume does not exist - do a full */
- restoreflags = RV_FULLRST;
- if ( (aoverwrite == INC) || (aoverwrite == ABORT) )
- fprintf(STDERR,"RW Volume does not exist; Will perform a full restore\n");
+ else if ((!readonly && Lp_GetRwIndex(&entry) == -1) /* RW volume does not exist - do a full */
+ || (readonly && !Lp_ROMatch(0, 0, &entry))) { /* RO volume does not exist - do a full */
+ restoreflags = RV_FULLRST;
+ if ( (aoverwrite == INC) || (aoverwrite == ABORT) )
+ fprintf(STDERR,"%s Volume does not exist; Will perform a full restore\n",
+ readonly ? "RO" : "RW");
- if (avolid == 0) {
- avolid = entry.volumeId[RWVOL];
- }
- else if (entry.volumeId[RWVOL] != 0 && entry.volumeId[RWVOL] != avolid) {
- avolid = entry.volumeId[RWVOL];
- }
+ if (avolid == 0) {
+ avolid = entry.volumeId[voltype];
+ }
+ else if (entry.volumeId[voltype] != 0 && entry.volumeId[voltype] != avolid) {
+ avolid = entry.volumeId[voltype];
+ }
}
else { /* volume exists - do we do a full incremental or abort */
char c, dc;
if(avolid == 0) {
- avolid = entry.volumeId[RWVOL];
+ avolid = entry.volumeId[voltype];
}
- else if(entry.volumeId[RWVOL] != 0 && entry.volumeId[RWVOL] != avolid) {
- avolid = entry.volumeId[RWVOL];
+ else if(entry.volumeId[voltype] != 0 && entry.volumeId[voltype] != avolid) {
+ avolid = entry.volumeId[voltype];
}
/* A file name was specified - check if volume is on another partition */
/* Ask what to do */
if (vol_elsewhere) {
fprintf(STDERR,"The volume %s %u already exists on a different server/part\n",
- volname, entry.volumeId[RWVOL]);
+ volname, entry.volumeId[voltype]);
fprintf(STDERR,
"Do you want to do a full restore or abort? [fa](a): ");
}
else
{
fprintf(STDERR,"The volume %s %u already exists in the VLDB\n",
- volname, entry.volumeId[RWVOL]);
+ volname, entry.volumeId[voltype]);
fprintf(STDERR,
"Do you want to do a full/incremental restore or abort? [fia](a): ");
}
restoreflags = 0;
if (vol_elsewhere) {
fprintf(STDERR,
- "RW volume %u already exists on a different server/part; not allowed\n",
- avolid);
+ "%s volume %u already exists on a different server/part; not allowed\n",
+ readonly ? "RO" : "RW", avolid);
exit(1);
}
}
}
+ if (offline) restoreflags |= RV_OFFLINE;
+ if (readonly) restoreflags |= RV_RDONLY;
code = UV_RestoreVolume(aserver, apart, avolid, avolname,
restoreflags, WriteData, afilename);
if (code) {
fprintf(STDOUT,"Removed replication site %s %s for volume %s\n",as->parms[0].items->data,apartName,as->parms[2].items->data);
return 0;
}
+static ChangeLocation(as)
+register struct cmd_syndesc *as;
+{
+ afs_int32 avolid, aserver, apart,code, err;
+ char apartName[10];
+
+ avolid = vsu_GetVolumeID(as->parms[2].items->data, cstruct, &err);
+ if (avolid == 0) {
+ if (err) PrintError("", err);
+ else fprintf(STDERR, "vos: can't find volume '%s'\n", as->parms[2].items->data);
+ exit(1);
+ }
+ aserver = GetServer(as->parms[0].items->data);
+ if (aserver == 0) {
+ fprintf(STDERR,"vos: server '%s' not found in host table\n", as->parms[0].items->data);
+ exit(1);
+ }
+ apart = volutil_GetPartitionID(as->parms[1].items->data);
+ if (apart < 0) {
+ fprintf(STDERR,"vos: could not interpret partition name '%s'\n",as->parms[1].items->data );
+ exit(1);
+ }
+ if (!IsPartValid(apart,aserver,&code)){/*check for validity of the partition */
+ if(code) PrintError("",code);
+ else fprintf(STDERR,"vos : partition %s does not exist on the server\n",as->parms[1].items->data);
+ exit(1);
+ }
+ code = UV_ChangeLocation(aserver, apart, avolid);
+ if (code) {
+ PrintDiagnostics("addsite", code);
+ exit(1);
+ }
+ MapPartIdIntoName(apart,apartName);
+ fprintf(STDOUT,"Changed location to %s %s for volume %s\n",as->parms[0].items->data, apartName,as->parms[2].items->data);
+ return 0;
+}
static ListPartitions(as)
register struct cmd_syndesc *as;
tcell = as->parms[12].items->data;
if(as->parms[14].items) /* -serverauth specified */
sauth = 1;
+ if(as->parms[16].items) /* -crypt specified */
+ vsu_SetCrypt(1);
if (code = vsu_ClientInit((as->parms[13].items != 0), confdir, tcell, sauth,
&cstruct, UV_SetSecurity)) {
fprintf(STDERR,"could not initialize VLDB library (code=%u) \n",code);
cmd_AddParm(ts, "-file", CMD_SINGLE,CMD_OPTIONAL, "dump file");
cmd_AddParm(ts, "-id", CMD_SINGLE,CMD_OPTIONAL, "volume ID");
cmd_AddParm(ts, "-overwrite", CMD_SINGLE,CMD_OPTIONAL, "abort | full | incremental");
+ cmd_AddParm(ts, "-offline", CMD_FLAG, CMD_OPTIONAL,
+ "leave restored volume offline");
+ cmd_AddParm(ts, "-readonly", CMD_FLAG, CMD_OPTIONAL,
+ "make restored volume read-only");
COMMONPARMS;
ts = cmd_CreateSyntax("unlock", LockReleaseCmd, 0, "release lock on VLDB entry for a volume");
cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID");
COMMONPARMS;
+ ts = cmd_CreateSyntax("changeloc", ChangeLocation, 0, "change an RW volume's location in the VLDB");
+ cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name for new location");
+ cmd_AddParm(ts, "-partition", CMD_SINGLE, 0, "partition name for new location");
+ cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID");
+ COMMONPARMS;
+
ts = cmd_CreateSyntax("addsite", AddSite, 0, "add a replication site");
cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "machine name for new site");
cmd_AddParm(ts, "-partition", CMD_SINGLE, 0, "partition name for new site");
COMMONPARMS;
cmd_CreateAlias (ts, "volinfo");
+ ts = cmd_CreateSyntax("setfields", SetFields, 0, "change volume info fields");
+ cmd_AddParm(ts, "-id", CMD_SINGLE, 0, "volume name or ID");
+ cmd_AddParm(ts, "-maxquota", CMD_SINGLE, CMD_OPTIONAL, "quota (KB)");
+ cmd_AddParm(ts, "-clearuse", CMD_FLAG, CMD_OPTIONAL, "clear dayUse");
+ COMMONPARMS;
+
ts = cmd_CreateSyntax("offline", volOffline, 0, (char *) CMD_HIDDEN);
cmd_AddParm(ts, "-server", CMD_SINGLE, 0, "server name");
cmd_AddParm(ts, "-partition", CMD_SINGLE, 0, "partition name");
int islocked;
struct restoreCookie cookie;
int reuseID;
- afs_int32 newDate, volflag;
+ afs_int32 newDate, volflag, voltype, volsertype;
int index, same, errcode;
char apartName[10];
totid = 0;
temptid = 0;
+ if (flags & RV_RDONLY) {
+ voltype = ROVOL;
+ volsertype = volser_RO;
+ } else {
+ voltype = RWVOL;
+ volsertype = volser_RW;
+ }
+
pvolid = tovolid;
toconn = UV_Bind(toserver, AFSCONF_VOLUMEPORT);
if(pvolid == 0) {/*alot a new id if needed */
goto refail;
}
reuseID = 0;
- }
- else{
+ } else if (flags & RV_RDONLY) {
+ if (entry.flags & RW_EXISTS) {
+ fprintf(STDERR,"Entry for ReadWrite volume %s already exists!\n",entry.name);
+ error = VOLSERBADOP;
+ goto refail;
+ }
+ if (!entry.volumeId[ROVOL]) {
+ fprintf(STDERR,"Existing entry for volume %s has no ReadOnly ID\n",tovolname);
+ error = VOLSERBADOP;
+ goto refail;
+ }
+ pvolid = entry.volumeId[ROVOL];
+ } else {
pvolid = entry.volumeId[RWVOL];
}
}/* at this point we have a volume id to use/reuse for the volume to be restored */
fprintf(STDOUT,"Restoring volume %s Id %u on server %s partition %s ..", tovolname,
pvolid, hostutil_GetNameByINet(toserver), partName);
fflush(STDOUT);
- /*what should the volume be restored as ? rw or ro or bk ?
- right now the default is rw always */
- code = AFSVolCreateVolume(toconn, topart, tovolname, volser_RW, 0,&pvolid, &totid);
+ code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
if (code){
if (flags & RV_FULLRST) { /* full restore: delete then create anew */
if(verbose) {
goto refail;
}
if (verbose) fprintf(STDOUT," done\n");
- code = AFSVolCreateVolume(toconn, topart, tovolname, volser_RW, 0,&pvolid, &totid);
+ code = AFSVolCreateVolume(toconn, topart, tovolname, volsertype, 0,&pvolid, &totid);
if (code){
fprintf(STDERR,"Could not create new volume %u\n",pvolid);
error = code;
}
}
cookie.parent = pvolid;
- cookie.type = RWVOL;
+ cookie.type = voltype;
cookie.clone = 0;
strncpy(cookie.name,tovolname,VOLSER_OLDMAXVOLNAME);
}
code = AFSVolGetStatus(toconn,totid, &tstatus);
if(code) {
- fprintf(STDERR,"Could not get status information about the volume %u\n",tovolid);
+ fprintf(STDERR,"Could not get status information about the volume %u\n",pvolid);
error = code;
goto refail;
}
- code = AFSVolSetIdsTypes(toconn,totid, tovolname, RWVOL, pvolid,0,0);
+ code = AFSVolSetIdsTypes(toconn,totid, tovolname, voltype, pvolid,0,0);
if(code) {
fprintf(STDERR,"Could not set the right type and ID on %u\n",pvolid);
error = code;
/* Volume was restored on the file server, update the
* VLDB to reflect the change.
*/
- vcode = VLDB_GetEntryByID(pvolid,RWVOL, &entry);
+ vcode = VLDB_GetEntryByID(pvolid,voltype, &entry);
if(vcode && vcode != VL_NOENT && vcode != VL_ENTDELETED) {
fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",pvolid);
error = vcode;
entry.nServers = 1;
entry.serverNumber[0] = toserver;/*should be indirect */
entry.serverPartition[0] = topart;
- entry.serverFlags[0] = ITSRWVOL;
- entry.flags = RW_EXISTS;
- if(tstatus.cloneID != 0){
+ entry.serverFlags[0] = (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
+ entry.flags = (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
+ if (flags & RV_RDONLY)
+ entry.volumeId[ROVOL] = pvolid;
+ else if(tstatus.cloneID != 0){
entry.volumeId[ROVOL] = tstatus.cloneID;/*this should come from status info on the volume if non zero */
}
else
EnumerateEntry(&entry);
fprintf(STDOUT,"------- New entry -------\n");
}
- vcode = ubik_Call(VL_SetLock,cstruct, 0, pvolid, RWVOL, VLOP_RESTORE);
+ vcode = ubik_Call(VL_SetLock,cstruct, 0, pvolid, voltype, VLOP_RESTORE);
if(vcode) {
fprintf(STDERR,"Could not lock the entry for volume number %u \n",pvolid);
error = vcode;
strcpy(entry.name, tovolname);
/* Update the vlentry with the new information */
- index = Lp_GetRwIndex(&entry);
+ if (flags & RV_RDONLY)
+ index = Lp_ROMatch(toserver, topart, &entry) - 1;
+ else
+ index = Lp_GetRwIndex(&entry);
if (index == -1) {
- /* Add the rw site for the volume being restored */
+ /* Add the new site for the volume being restored */
entry.serverNumber[entry.nServers] = toserver;
entry.serverPartition[entry.nServers] = topart;
- entry.serverFlags[entry.nServers] = ITSRWVOL;
+ entry.serverFlags[entry.nServers] =
+ (flags & RV_RDONLY) ? ITSROVOL : ITSRWVOL;
entry.nServers++;
} else {
/* This volume should be deleted on the old site
entry.serverPartition[index] = topart;
}
- entry.flags |= RW_EXISTS;
+ entry.flags |= (flags & RV_RDONLY) ? RO_EXISTS : RW_EXISTS;
MapNetworkToHost(&entry,&storeEntry);
- vcode = VLDB_ReplaceEntry(pvolid,RWVOL, &storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
+ vcode = VLDB_ReplaceEntry(pvolid,voltype, &storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP );
if(vcode) {
fprintf(STDERR,"Could not update the entry for volume number %u \n",pvolid);
error = vcode;
if (!error) error = code;
}
if(islocked) {
- vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, pvolid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
+ vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, pvolid, voltype, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
if(vcode) {
fprintf(STDERR,"Could not release lock on the VLDB entry for the volume %u\n",pvolid);
if(!error) error = vcode;
return 0;
}
+/*sets <server> <part> as read/write site for <volid> in the vldb */
+UV_ChangeLocation(server, part, volid)
+afs_int32 server, part, volid;
+{
+ afs_int32 vcode;
+ struct nvldbentry entry,storeEntry;
+ int index;
+
+ vcode = ubik_Call(VL_SetLock,cstruct, 0,volid,RWVOL, VLOP_ADDSITE);
+ if(vcode) {
+ fprintf(STDERR," Could not lock the VLDB entry for volume %u \n", volid);
+ PrintError("",vcode);
+ return(vcode);
+ }
+ vcode = VLDB_GetEntryByID(volid,RWVOL, &entry);
+ if(vcode) {
+ fprintf(STDERR,"Could not fetch the entry for volume number %u from VLDB \n",volid);
+ PrintError("",vcode);
+ return (vcode);
+ }
+ MapHostToNetwork(&entry);
+ index = Lp_GetRwIndex(&entry);
+ if (index < 0) {
+ /* no RW site exists */
+ fprintf(STDERR,"No existing RW site for volume %u", volid);
+ vcode = ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
+ if(vcode) {
+ fprintf(STDERR,"Could not release lock on entry for volume %u \n",volid);
+ PrintError("",vcode);
+ return(vcode);
+ }
+ return VOLSERBADOP;
+ }
+ else { /* change the RW site */
+ entry.serverNumber[index] = server;
+ entry.serverPartition[index] = part;
+ MapNetworkToHost(&entry,&storeEntry);
+ vcode = VLDB_ReplaceEntry(volid,RWVOL,&storeEntry,LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
+ if(vcode){
+ fprintf(STDERR,"Could not update entry for volume %u \n",volid);
+ PrintError("",vcode);
+ ubik_Call(VL_ReleaseLock,cstruct, 0, volid, RWVOL, LOCKREL_OPCODE | LOCKREL_AFSID | LOCKREL_TIMESTAMP);
+ return(vcode);
+ }
+ if(verbose) fprintf(STDOUT," done\n");
+ }
+ return 0;
+}
+
/*list all the partitions on <aserver> */
UV_ListPartitions(aserver, ptrPartList, cntp)
afs_int32 aserver;
error_exit:
if (tid) {
rcode = 0;
- code = AFSVolEndTrans(conn, tid, &code);
+ code = AFSVolEndTrans(conn, tid, &rcode);
if (code || rcode) {
fprintf(STDERR, "SetVolumeStatus: EndTrans Failed\n");
if (!error) error = (code ? code : rcode);
return(error);
}
+UV_SetVolumeInfo(server, partition, volid, infop)
+ afs_int32 server, partition, volid;
+ volintInfo *infop;
+{
+ struct rx_connection *conn = 0;
+ afs_int32 tid=0;
+ afs_int32 code, error=0, rcode;
+
+ conn = UV_Bind(server, AFSCONF_VOLUMEPORT);
+ if (!conn) {
+ fprintf(STDERR, "SetVolumeInfo: Bind Failed");
+ ERROR_EXIT(-1);
+ }
+
+ code = AFSVolTransCreate(conn, volid, partition, ITOffline, &tid);
+ if (code) {
+ fprintf(STDERR, "SetVolumeInfo: TransCreate Failed\n");
+ ERROR_EXIT(code);
+ }
+
+ code = AFSVolSetInfo(conn, tid, infop);
+ if (code) {
+ fprintf(STDERR, "SetVolumeInfo: SetInfo Failed\n");
+ ERROR_EXIT(code);
+ }
+
+ error_exit:
+ if (tid) {
+ rcode = 0;
+ code = AFSVolEndTrans(conn, tid, &rcode);
+ if (code || rcode) {
+ fprintf(STDERR, "SetVolumeInfo: EndTrans Failed\n");
+ if (!error) error = (code ? code : rcode);
+ }
+ }
+
+ if (conn) rx_DestroyConnection(conn);
+ return(error);
+}
+
/*maps the host addresses in <old > (present in network byte order) to
that in< new> (present in host byte order )*/
void
#include "lockdata.h"
struct ubik_client *cstruct;
+static rxkad_level vsu_rxkad_level = rxkad_clear;
extern int VL_CreateEntry(), VL_CreateEntryN();
extern int VL_GetEntryByID(), VL_GetEntryByIDN();
extern int VL_GetEntryByNameO(), VL_GetEntryByNameN();
/*
+ Set encryption. If 'cryptflag' is nonzero, encrpytion is turned on
+ for authenticated connections; if zero, encryption is turned off.
+ Calling this function always results in a level of at least rxkad_auth;
+ to get a rxkad_clear connection, simply don't call this.
+*/
+void vsu_SetCrypt(cryptflag)
+ int cryptflag;
+{
+ if (cryptflag) {
+ vsu_rxkad_level = rxkad_crypt;
+ } else {
+ vsu_rxkad_level = rxkad_auth;
+ }
+}
+
+
+/*
Get the appropriate type of ubik client structure out from the system.
*/
afs_int32 vsu_ClientInit(noAuthFlag, confDir, cellName, sauth, uclientp, secproc)
break;
case 2:
sc = (struct rx_securityClass *)rxkad_NewClientSecurityObject(
- rxkad_clear, &ttoken.sessionKey, ttoken.kvno,
+ vsu_rxkad_level, &ttoken.sessionKey, ttoken.kvno,
ttoken.ticketLen, ttoken.ticket);
break;
default: