package diskCacheV111.admin;
import com.google.common.base.Strings;
import com.google.common.base.Throwables;
import jline.console.completer.Completer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.io.CharArrayWriter;
import java.io.FileNotFoundException;
import java.io.PrintWriter;
import java.io.Serializable;
import java.net.InetSocketAddress;
import java.util.ArrayList;
import java.util.Collections;
import java.util.EnumSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.StringTokenizer;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import diskCacheV111.pools.PoolV2Mode;
import diskCacheV111.util.CacheException;
import diskCacheV111.util.PnfsId;
import diskCacheV111.util.SpreadAndWait;
import diskCacheV111.util.TimeoutCacheException;
import diskCacheV111.vehicles.DCapProtocolInfo;
import diskCacheV111.vehicles.Message;
import diskCacheV111.vehicles.PnfsFlagMessage;
import diskCacheV111.vehicles.PnfsGetCacheLocationsMessage;
import diskCacheV111.vehicles.PnfsMapPathMessage;
import diskCacheV111.vehicles.Pool2PoolTransferMsg;
import diskCacheV111.vehicles.PoolLinkInfo;
import diskCacheV111.vehicles.PoolMgrGetPoolByLink;
import diskCacheV111.vehicles.PoolMgrGetPoolLinks;
import diskCacheV111.vehicles.PoolMgrReplicateFileMsg;
import diskCacheV111.vehicles.PoolModifyModeMessage;
import diskCacheV111.vehicles.PoolModifyPersistencyMessage;
import diskCacheV111.vehicles.PoolRemoveFilesMessage;
import diskCacheV111.vehicles.PoolSetStickyMessage;
import diskCacheV111.vehicles.QuotaMgrCheckQuotaMessage;
import dmg.cells.nucleus.CellEndpoint;
import dmg.cells.nucleus.CellMessage;
import dmg.cells.nucleus.CellPath;
import dmg.cells.nucleus.NoRouteToCellException;
import dmg.cells.nucleus.SerializationException;
import dmg.util.AclException;
import dmg.util.AuthorizedString;
import dmg.util.CommandException;
import dmg.util.CommandExitException;
import dmg.util.CommandInterpreter;
import dmg.util.CommandSyntaxException;
import dmg.util.CommandThrowableException;
import org.dcache.cells.CellStub;
import org.dcache.namespace.FileAttribute;
import org.dcache.util.Args;
import org.dcache.util.CacheExceptionFactory;
import org.dcache.vehicles.FileAttributes;
import org.dcache.vehicles.PnfsGetFileAttributes;
import static java.util.concurrent.TimeUnit.MILLISECONDS;
/**
* @author Christian Bernardt, Patrick Fuhrmann
* @version 0.2, 10 December 2010
*/
public class LegacyAdminShell
extends CommandInterpreter
implements Completer
{
private static final Logger _log =
LoggerFactory.getLogger(LegacyAdminShell.class);
private static final String ADMIN_COMMAND_NOOP = "xyzzy";
private static final int CD_PROBE_MESSAGE_TIMEOUT_MS = 1000;
private final CellEndpoint cellEndPoint;
private final CellStub _acmStub;
private final CellStub _poolManager;
private final CellStub _pnfsManager;
private final CellStub _cellStub;
private String _user;
private final String _authUser;
private long _timeout = TimeUnit.SECONDS.toMillis(10);
private boolean _fullException;
private final String _instance ;
private Position _currentPosition = new Position();
private final boolean _debug = false ;
private Completer _completer;
private static class Position
{
private CellPath remote;
private String remoteName;
private boolean hyperMode;
private List<String> hyperPath = new ArrayList<>();
private String moduleName;
private Position()
{
}
private Position(Position position)
{
remote = position.remote;
remoteName = position.remoteName;
hyperMode = position.hyperMode;
hyperPath = new ArrayList<>(position.hyperPath);
moduleName = position.moduleName;
}
private Position(String removeCell)
{
hyperMode = false;
remoteName = removeCell;
remote = remoteName == null ? null : new CellPath(remoteName);
}
private void clearHyperMode()
{
hyperMode = false;
remoteName = null;
remote = null;
hyperPath = new ArrayList<>();
moduleName = null;
}
private void gotoLocal()
{
remoteName = null;
remote = null;
hyperPath = new ArrayList<>();
moduleName = null;
}
private String getPrefix()
{
if ((hyperPath == null) || (hyperPath.size() < 3)) {
return "";
}
StringBuilder sb = new StringBuilder();
for (int i = 2, n = hyperPath.size(); i < n; i++) {
sb.append(hyperPath.get(i)).append(" ");
}
return sb.toString();
}
private void finish()
{
if (!hyperMode) {
return;
}
int size = hyperPath.size();
String domainName = size > 0 ? hyperPath.get(0) : null;
String cellName = size > 1 ? hyperPath.get(1) : null;
moduleName = size > 2 ? hyperPath.get(2) : null;
if (domainName == null) {
remoteName = null;
} else if (cellName == null) {
remoteName = domainName.equals("*") ?
"topo" : "System@" + domainName;
} else {
remoteName = domainName.equals("*") ?
cellName : cellName + "@" + domainName;
}
remote = remoteName == null ? null : new CellPath(remoteName);
}
private void mergePath(Path path)
{
hyperMode = true;
String[] pathString = path.getPath();
if (path.isAbsolutePath()) {
hyperPath = new ArrayList<>();
Collections.addAll(hyperPath, pathString);
} else {
for (String pathElement : pathString) {
switch (pathElement) {
case ".":
break;
case "..":
int currentSize = hyperPath.size();
if (currentSize == 0) {
continue;
}
hyperPath.remove(currentSize - 1);
break;
default:
hyperPath.add(pathElement);
break;
}
}
}
finish();
}
}
private class Path
{
private final String _pathString;
private boolean _isAbsolutePath;
private boolean _isPath;
private boolean _isDomain;
private final String[] _path;
private Path(String pathString)
{
_pathString = pathString;
if (_pathString.indexOf('@') > -1) {
_isDomain = true;
StringTokenizer st = new StringTokenizer(pathString, "@");
_path = new String[2];
_path[0] = st.nextToken();
_path[1] = st.nextToken();
} else if (_pathString.indexOf('/') > -1) {
_isPath = true;
_isAbsolutePath = _pathString.startsWith("/");
StringTokenizer st = new StringTokenizer(_pathString, "/");
int count = st.countTokens();
_path = new String[count];
for (int i = 0; i < _path.length; i++) {
_path[i] = st.nextToken();
}
} else {
_path = new String[1];
_path[0] = _pathString;
}
}
private boolean isAbsolutePath()
{
return _isAbsolutePath;
}
private boolean isDomain()
{
return _isDomain;
}
private boolean isPath()
{
return _isPath;
}
private String[] getPath()
{
return _path;
}
@Override
public String toString()
{
return _pathString;
}
}
public LegacyAdminShell(String user, CellEndpoint cellEndpoint, String prompt)
{
cellEndPoint = cellEndpoint;
_user = user;
_authUser = user;
_acmStub = new CellStub(cellEndpoint, new CellPath("acm"));
_poolManager = new CellStub(cellEndpoint, new CellPath("PoolManager"));
_pnfsManager = new CellStub(cellEndpoint, new CellPath("PnfsManager"), 30000, MILLISECONDS);
_cellStub = new CellStub(cellEndpoint);
_instance = prompt;
addCommandListener(new HelpCommands());
}
protected String getUser()
{
return _user;
}
public void checkPermission(String aclName)
throws AclException
{
Object[] request = new Object[5];
request[0] = "request";
request[1] = "<nobody>";
request[2] = "check-permission";
request[3] = getUser();
request[4] = aclName;
Object[] r;
try {
r = _acmStub.sendAndWait(request, Object[].class, _timeout);
} catch (NoRouteToCellException | TimeoutCacheException e) {
throw new AclException(e.getMessage());
} catch (CacheException | InterruptedException e) {
throw new AclException("Problem: " + e.getMessage());
}
if (r.length < 6 || !(r[5] instanceof Boolean)) {
throw new AclException("Protocol violation 4456");
}
if (!((Boolean) r[5])) {
throw new AclException(getUser(), aclName);
}
}
public String getHello(){
return "\n dCache Admin (VII) (user="+getUser()+")\n\n" ;
}
public String getPrompt(){
if( _currentPosition.hyperMode ){
StringBuilder sb = new StringBuilder() ;
sb.append("(").append(getUser()).append(") ");
if( _debug ){
String remote = _currentPosition.remoteName == null ? "local" : _currentPosition.remoteName;
sb.append("[").append(remote).append("] ");
}
sb.append(_instance == null ? "/" : ( "/" + _instance ) ) ;
for (Object pathElement : _currentPosition.hyperPath) {
sb.append("/").append(pathElement.toString());
}
sb.append(" > ");
return sb.toString();
}else{
return ( _instance == null ? "" : ( "[" + _instance + "] " ) ) +
( _currentPosition.remote == null ? "(local) " : ( "(" + _currentPosition.remoteName +") " ) ) +
getUser()+" > " ;
}
}
public Object ac_logoff(Args args) throws CommandException
{
throw new CommandExitException("Done", 0);
}
public static final String hh_su = "<userName>";
public String ac_su_$_1(Args args) throws Exception
{
String user = args.argv(0);
if (user.equals(_authUser)) {
_user = _authUser;
return "User changed BACK to " + _user;
} else if (user.equals(_user)) {
return "User not changed, still " + _user;
}
try {
checkPermission("system.*.newuser");
} catch (AclException acle) {
checkPermission("system." + user + ".newuser");
}
_user = user;
return "User changed to " + _user;
}
public static final String hh_set_exception = "message|detail";
public String ac_set_exception_$_0_1(Args args) throws CommandException
{
if (args.argc() > 0) {
if (args.argv(0).equals("message")) {
_fullException = false;
} else if (args.argv(0).equals("detail")) {
_fullException = true;
} else {
throw new
CommandSyntaxException("set exception message|detail");
}
}
return "Exception = " + (_fullException ? "detail" : "message");
}
public static final String hh_set_timeout = "<timeout/sec> # command timeout in seconds";
public String ac_set_timeout_$_0_1(Args args)
{
if (args.argc() > 0) {
long timeout = Integer.parseInt(args.argv(0)) * 1000L;
if (timeout < 1000L) {
throw new
IllegalArgumentException("<timeout> >= 1");
}
_timeout = timeout;
}
return "Timeout = " + (_timeout / 1000L);
}
public static final String hh_getpoolbylink = "<linkName> [-size=<filesize>] [-service=<serviceCellName]";
public String ac_getpoolbylink_$_1(Args args) throws Exception
{
String linkName = args.argv(0);
String service = args.getOpt("service");
String sizeString = args.getOpt("size");
PoolMgrGetPoolByLink msg = new PoolMgrGetPoolByLink(linkName);
if (sizeString != null) {
msg.setFilesize(Long.parseLong(sizeString));
}
service = service == null ? "PoolManager" : service;
Object result = sendObject(service, msg);
if (result == null) {
throw new
Exception("QuotaRequest timed out");
}
if (result instanceof PoolMgrGetPoolByLink) {
PoolMgrGetPoolByLink link = (PoolMgrGetPoolByLink) result;
int rc = link.getReturnCode();
if (rc != 0) {
return "Problem " + rc + " <" + link.getErrorObject() + "> reported for link " + linkName;
} else {
return "Pool <" + link.getPoolName() + "> selected for link " + linkName;
}
}
return "Unexpected class " + result.getClass().getName() +
" arrived with message " + result.toString();
}
public static final String hh_quota_query = "<storageClassName>|* [-l] [-service=<serviceCellName>]";
public Object ac_quota_query_$_1(Args args) throws Exception
{
String storageClassName = args.argv(0);
String service = args.getOpt("service");
service = service == null ? "QuotaManager" : service;
boolean extended = args.hasOption("l");
Message msg;
if (storageClassName.equals("*")) {
msg = new PoolMgrGetPoolLinks();
} else {
msg = new QuotaMgrCheckQuotaMessage(storageClassName);
}
Object result = sendObject(service, msg);
if (result == null) {
throw new
Exception("QuotaRequest timed out");
}
if (result instanceof QuotaMgrCheckQuotaMessage) {
return result.toString();
} else if (result instanceof PoolMgrGetPoolLinks) {
if (extended) {
PoolMgrGetPoolLinks info = (PoolMgrGetPoolLinks) result;
PoolLinkInfo[] links = info.getPoolLinkInfos();
StringBuilder sb = new StringBuilder();
if (links == null) {
return "Object doesn't contain a Links list";
}
for (PoolLinkInfo link : links) {
sb.append(" Link ").append(link.getName()).append(" : ")
.append(link.getAvailableSpaceInBytes()).append("\n");
String[] storageGroups = link.getStorageGroups();
if (storageGroups == null) {
continue;
}
for (String storageGroup : storageGroups) {
sb.append(" ").append(storageGroup).append("\n");
}
}
return sb.toString();
}
return result.toString();
}
return "Unexpected class " + result.getClass().getName() +
" arrived with message " + result.toString();
}
public static final String hh_set_sticky = "<pnfsId>|<globalPath> [-target=<target>] [-silent]";
public Object ac_set_sticky_$_1(Args args) throws Exception
{
return setSticky(
args.argv(0),
args.getOpt("target"),
true,
!args.hasOption("silent") ? new StringBuffer() : null);
}
public static final String hh_set_unsticky = "<pnfsId>|<globalPath> [-target=<target>] [-silent]";
public Object ac_set_unsticky_$_1(Args args) throws Exception
{
return setSticky(
args.argv(0),
args.getOpt("target"),
false,
!args.hasOption("silent") ? new StringBuffer() : null);
}
public static final String hh_uncache = "<pnfsId>|<globalPath> [-target=<target>] [-silent]";
public Object ac_uncache_$_1(Args args) throws Exception
{
try {
return uncache(
args.argv(0),
args.getOpt("target"),
!args.hasOption("silent") ? new StringBuffer() : null);
} catch (Exception ee) {
ee.printStackTrace();
throw ee;
}
}
public static final String fh_repinfoof =
"repinfoof <pnfsId> | <globalPath> # lists info the status of a file by pnfsid or by path.\n" +
"The information includes pools on which the file has been stored (info provided by \"cacheinfoof\" in the PnfsManager cell)\n" +
"and the repository info of the file (info provided by \"rep ls\" in the pool cell).\n";
public static final String hh_repinfoof = "<pnfsId> | <globalPath>";
public String ac_repinfoof_$_1(Args args)
throws CacheException, SerializationException, NoRouteToCellException, InterruptedException, CommandException
{
StringBuilder sb = new StringBuilder();
String fileIdentifier = args.argv(0);
FileAttributes fileAttributes = getFileLocations(fileIdentifier);
PnfsId pnfsId = fileAttributes.getPnfsId();
if (fileAttributes.getLocations().isEmpty()) { // nothing to do
return "No file locations found";
}
Map<CellPath, String> replies = askPoolsForRepLs(fileAttributes, pnfsId);
for (Map.Entry<CellPath, String> reply : replies.entrySet()) {
sb.append(reply.getKey().getCellName()).append(" : ");
sb.append(reply.getValue());
}
return sb.toString();
}
private FileAttributes getFileLocations(String fileIdentifier)
throws CacheException, SerializationException, NoRouteToCellException, InterruptedException, CommandException
{
Set<FileAttribute> request = EnumSet.of(FileAttribute.LOCATIONS, FileAttribute.PNFSID);
PnfsGetFileAttributes msg;
if (PnfsId.isValid(fileIdentifier)) {
PnfsId pnfsId = new PnfsId(fileIdentifier);
msg = new PnfsGetFileAttributes(pnfsId, request);
} else {
msg = new PnfsGetFileAttributes(fileIdentifier, request);
}
PnfsGetFileAttributes replyFileLocations = (PnfsGetFileAttributes) sendObject("PnfsManager", msg);
if (replyFileLocations == null) {
throw new CacheException("Request to the PnfsManager timed out");
}
if (replyFileLocations.getReturnCode() != 0) {
throw CacheExceptionFactory.exceptionOf(replyFileLocations);
}
return replyFileLocations.getFileAttributes();
}
private Map<CellPath, String> askPoolsForRepLs(FileAttributes fileAttributes, PnfsId pnfsId)
{
SpreadAndWait<String> spreader = new SpreadAndWait<>(new CellStub(cellEndPoint, null, _timeout));
for (String poolName : fileAttributes.getLocations()) {
spreader.send(new CellPath(poolName), String.class, "rep ls " + pnfsId);
}
try {
spreader.waitForReplies();
} catch (InterruptedException ex) {
_log.info("InterruptedException while waiting for a reply from pools " + ex);
}
return spreader.getReplies();
}
private String setSticky(
String destination,
String target,
boolean mode,
StringBuffer sb)
throws Exception
{
if (Strings.isNullOrEmpty(target)) {
target = "*";
}
boolean verbose = sb != null;
PnfsFlagReply reply = setPnfsFlag(destination, "s", target, mode);
PnfsId pnfsId = reply.getPnfsId();
PnfsGetCacheLocationsMessage pnfsMessage =
new PnfsGetCacheLocationsMessage(pnfsId);
pnfsMessage = (PnfsGetCacheLocationsMessage) sendObject("PnfsManager", pnfsMessage);
if (pnfsMessage.getReturnCode() != 0) {
throw new
FileNotFoundException(destination);
}
List<String> list = pnfsMessage.getCacheLocations();
if (verbose) {
sb.append("Location(s) : ");
for (String location : list) {
sb.append(location).append(",");
}
sb.append("\n");
}
if (target.equals("*")) {
if (verbose) {
sb.append("Selection : <all>\n");
}
} else if (list.contains(target)) {
if (verbose) {
sb.append("Selection : ").append(target).append("\n");
}
list = new ArrayList<>();
list.add(target);
} else {
if (verbose) {
sb.append("Selection : <nothing>\n");
}
return sb == null ? "" : sb.toString();
}
PoolSetStickyMessage sticky;
for (String poolName : list) {
if (verbose) {
sb.append(poolName).append(" : ");
}
try {
sticky = new PoolSetStickyMessage(poolName, pnfsId, mode);
sticky = (PoolSetStickyMessage) sendObject(poolName, sticky);
if (verbose) {
int rc = sticky.getReturnCode();
if (rc != 0) {
sb.append("[").append(rc).append("] ").
append(sticky.getErrorObject().toString());
} else {
sb.append("ok");
}
}
} catch (Exception ee) {
if (verbose) {
sb.append(ee.getMessage());
}
}
if (verbose) {
sb.append("\n");
}
}
return sb == null ? "" : sb.toString();
}
private String uncache(String destination, String target, StringBuffer sb)
throws Exception
{
if ((target == null) || (target.isEmpty())) {
target = "*";
}
boolean verbose = sb != null;
PnfsId pnfsId;
if (destination.startsWith("/pnfs")) {
PnfsMapPathMessage map = new PnfsMapPathMessage(destination);
map = (PnfsMapPathMessage) sendObject("PnfsManager", map);
if (map.getReturnCode() != 0) {
Object o = map.getErrorObject();
if (o instanceof Exception) {
throw (Exception) o;
} else {
throw new Exception(o.toString());
}
}
if ((pnfsId = map.getPnfsId()) == null) {
throw new
FileNotFoundException(destination);
}
} else {
pnfsId = new PnfsId(destination);
}
int dbId = pnfsId.getDatabaseId();
try {
checkPermission("pool.*.uncache");
} catch (AclException ee) {
checkPermission("pool." + dbId + ".uncache");
}
PnfsGetCacheLocationsMessage pnfsMessage =
new PnfsGetCacheLocationsMessage(pnfsId);
pnfsMessage = (PnfsGetCacheLocationsMessage) sendObject("PnfsManager", pnfsMessage);
if (pnfsMessage.getReturnCode() != 0) {
throw new
FileNotFoundException(destination);
}
List<String> locations = pnfsMessage.getCacheLocations();
if (verbose) {
sb.append("Location(s) : ");
for (Object location : locations) {
sb.append(location.toString()).append(",");
}
sb.append("\n");
}
if (target.equals("*")) {
if (verbose) {
sb.append("Selection : <all>\n");
}
} else if (locations.contains(target)) {
if (verbose) {
sb.append("Selection : ").append(target).append("\n");
}
locations = new ArrayList<>();
locations.add(target);
} else {
if (verbose) {
sb.append("Selection : <nothing>\n");
}
return sb == null ? "" : sb.toString();
}
PoolRemoveFilesMessage remove;
for (Object location : locations) {
String poolName = location.toString();
if (verbose) {
sb.append(poolName).append(" : ");
}
try {
remove = new PoolRemoveFilesMessage(poolName, pnfsId.toString());
remove = (PoolRemoveFilesMessage) sendObject(poolName, remove);
if (verbose) {
int rc = remove.getReturnCode();
if (rc != 0) {
Object obj = remove.getErrorObject();
if ((obj != null) && (obj instanceof Object[])) {
Object o = ((Object[]) obj)[0];
if (o != null) {
sb.append("[").append(rc).append("] Failed ").
append(o.toString());
}
} else if (obj != null) {
sb.append("[").append(rc).append("] Failed ").
append(obj.toString());
}
} else {
sb.append("ok");
}
}
} catch (Exception ee) {
if (verbose) {
sb.append(ee.getMessage());
}
}
if (verbose) {
sb.append("\n");
}
}
return sb == null ? "" : sb.toString();
}
private static class PnfsFlagReply
{
private final PnfsId _pnfsId;
private final PnfsFlagMessage _message;
public PnfsFlagReply(PnfsId pnfsId, PnfsFlagMessage message)
{
_pnfsId = pnfsId;
_message = message;
}
public PnfsId getPnfsId()
{
return _pnfsId;
}
public PnfsFlagMessage getPnfsFlagMessage()
{
return _message;
}
}
public static final String hh_flags_set = "<pnfsId>|<globalPath> <key> <value>";
public Object ac_flags_set_$_3(Args args) throws Exception
{
String destination = args.argv(0);
String key = args.argv(1);
String value = args.argv(2);
PnfsFlagMessage result =
setPnfsFlag(destination, key, value, true).getPnfsFlagMessage();
return result.getReturnCode() == 0 ? "" : result.getErrorObject().toString();
}
private PnfsFlagReply setPnfsFlag(
String destination,
String key,
String value,
boolean mode)
throws Exception
{
PnfsId pnfsId;
if (destination.startsWith("/pnfs")) {
PnfsMapPathMessage map = new PnfsMapPathMessage(destination);
map = (PnfsMapPathMessage) sendObject("PnfsManager", map);
if (map.getReturnCode() != 0) {
Object o = map.getErrorObject();
if (o instanceof Exception) {
throw (Exception) o;
} else {
throw new Exception(o.toString());
}
}
pnfsId = map.getPnfsId();
if (pnfsId == null) {
throw new FileNotFoundException(destination);
}
} else {
pnfsId = new PnfsId(destination);
}
int dbId = pnfsId.getDatabaseId();
try {
checkPermission("pnfs.*.update");
} catch (AclException ee) {
checkPermission("pnfs." + key + "." + dbId + ".update");
}
PnfsFlagMessage pfm = new PnfsFlagMessage(pnfsId, key,
mode ? PnfsFlagMessage.FlagOperation.SET : PnfsFlagMessage.FlagOperation.REMOVE);
pfm.setValue(value);
PnfsFlagMessage result = (PnfsFlagMessage) sendObject("PnfsManager", pfm);
if (result.getReturnCode() != 0) {
Object o = result.getErrorObject();
if (o instanceof Exception) {
throw (Exception) o;
} else {
throw new Exception(o.toString());
}
}
return new PnfsFlagReply(pnfsId, result);
}
public static final String hh_flags_remove = "<pnfsId> <key>";
public Object ac_flags_remove_$_2(Args args) throws Exception
{
PnfsId pnfsId;
if (args.argv(0).startsWith("/pnfs")) {
PnfsMapPathMessage map = new PnfsMapPathMessage(args.argv(0));
map = (PnfsMapPathMessage) sendObject("PnfsManager", map);
if (map.getReturnCode() != 0) {
Object o = map.getErrorObject();
if (o instanceof Exception) {
throw (Exception) o;
} else {
throw new Exception(o.toString());
}
}
pnfsId = map.getPnfsId();
} else {
pnfsId = new PnfsId(args.argv(0));
}
int dbId = pnfsId.getDatabaseId();
String key = args.argv(1);
try {
checkPermission("pnfs.*.update");
} catch (AclException ee) {
checkPermission("pnfs." + key + "." + dbId + ".update");
}
PnfsFlagMessage pfm = new PnfsFlagMessage(pnfsId, key, PnfsFlagMessage.FlagOperation.REMOVE);
PnfsFlagMessage result = (PnfsFlagMessage) sendObject("PnfsManager", pfm);
if (result.getReturnCode() != 0) {
Object o = result.getErrorObject();
if (o instanceof Exception) {
throw (Exception) o;
} else {
throw new Exception(o.toString());
}
}
return result.getReturnCode() == 0 ? "" : result.getErrorObject().toString();
}
public static final String hh_p2p = "<pnfsId> [<sourcePool> <destinationPool>] [-ip=<address]";
public String ac_p2p_$_1_3(Args args) throws CacheException, InterruptedException, NoRouteToCellException
{
if (args.argc() >= 3) {
String source = args.argv(1);
String dest = args.argv(2);
PnfsId pnfsId = new PnfsId(args.argv(0));
Pool2PoolTransferMsg p2p = new Pool2PoolTransferMsg(source, dest,
FileAttributes.ofPnfsId(pnfsId));
cellEndPoint.sendMessage(
new CellMessage(new CellPath(dest), p2p)
);
return "P2p of " + pnfsId + " initiated from " + source + " to " + dest;
} else {
PnfsId pnfsId = new PnfsId(args.argv(0));
String ip = args.getOpt("ip");
PnfsGetFileAttributes fileAttributesMsg =
new PnfsGetFileAttributes(pnfsId, PoolMgrReplicateFileMsg.getRequiredAttributes());
fileAttributesMsg = _pnfsManager.sendAndWait(fileAttributesMsg);
DCapProtocolInfo pinfo =
new DCapProtocolInfo("DCap", 0, 0, new InetSocketAddress("localhost", 0));
String timeoutString = args.getOpt("timeout");
long timeout = timeoutString != null ?
Long.parseLong(timeoutString) * 1000L :
60000L;
PoolMgrReplicateFileMsg select =
new PoolMgrReplicateFileMsg(fileAttributesMsg.getFileAttributes(), pinfo);
select = _poolManager.sendAndWait(select, timeout);
return "p2p -> " + select.getPoolName();
}
}
public String fh_modify_poolmode =
" a) modify poolmode enable <poolname>[,<poolname>...]\n" +
" b) modify poolmode [OPTIONS] disable <poolname>[,<poolname>...] [<code> [<message>]]\n" +
" OPTIONS :\n" +
" -fetch # disallows fetch (transfer to client)\n" +
" -stage # disallows staging (from HSM)\n" +
" -store # disallows store (transfer from client)\n" +
" -p2p-client\n" +
" -rdonly # := store,stage,p2p-client\n" +
" -strict # := disallows everything\n";
public static final String hh_modify_poolmode =
"enable|disable <poolname>[,<poolname>...] [<code> [<message>]] [-strict|-stage|-rdonly|-fetch|-store]";
public String ac_modify_poolmode_$_2_4(Args args) throws Exception
{
checkPermission("*.*.*");
String enable = args.argv(0);
String poolList = args.argv(1);
String message = args.argc() > 3 ? args.argv(3) : null;
int code = args.argc() > 2 ? Integer.parseInt(args.argv(2)) : 0;
PoolV2Mode mode = new PoolV2Mode();
switch (enable) {
case "disable":
int modeBits = PoolV2Mode.DISABLED;
if (args.hasOption("strict")) {
modeBits |= PoolV2Mode.DISABLED_STRICT;
}
if (args.hasOption("stage")) {
modeBits |= PoolV2Mode.DISABLED_STAGE;
}
if (args.hasOption("fetch")) {
modeBits |= PoolV2Mode.DISABLED_FETCH;
}
if (args.hasOption("store")) {
modeBits |= PoolV2Mode.DISABLED_STORE;
}
if (args.hasOption("p2p-client")) {
modeBits |= PoolV2Mode.DISABLED_P2P_CLIENT;
}
if (args.hasOption("p2p-server")) {
modeBits |= PoolV2Mode.DISABLED_P2P_SERVER;
}
if (args.hasOption("rdonly")) {
modeBits |= PoolV2Mode.DISABLED_RDONLY;
}
mode.setMode(modeBits);
break;
case "enable":
break;
default:
throw new
CommandSyntaxException("Invalid keyword : " + enable);
}
StringTokenizer st = new StringTokenizer(poolList, ",");
PoolModifyModeMessage modify;
StringBuilder sb = new StringBuilder();
sb.append("Sending new pool mode : ").append(mode).append("\n");
while (st.hasMoreTokens()) {
String poolName = st.nextToken();
modify = new PoolModifyModeMessage(poolName, mode);
modify.setStatusInfo(code, message);
sb.append(" ").append(poolName).append(" -> ");
try {
modify = (PoolModifyModeMessage) sendObject(poolName, modify);
} catch (Exception ee) {
sb.append(ee.getMessage()).append("\n");
continue;
}
if (modify.getReturnCode() != 0) {
sb.append(modify.getErrorObject().toString()).append("\n");
continue;
}
sb.append("OK\n");
}
return sb.toString();
}
public static final String hh_set_deletable = "<pnfsId> # DEBUG for advisory delete (srm)";
public String ac_set_deletable_$_1(Args args) throws Exception
{
checkPermission("*.*.*");
PnfsId pnfsId = new PnfsId(args.argv(0));
StringBuilder sb = new StringBuilder();
PnfsFlagMessage pfm = new PnfsFlagMessage(pnfsId, "d", PnfsFlagMessage.FlagOperation.SET);
pfm.setValue("true");
try {
pfm = (PnfsFlagMessage) sendObject("PnfsManager", pfm);
} catch (Exception ee) {
sb.append("Attempt to set 'd' flag reported an Exception : ")
.append(ee);
sb.append("\n");
sb.append("Operation aborted\n");
return sb.toString();
}
if (pfm.getReturnCode() != 0) {
sb.append("set 'd' flag reported : ").append(pfm.getErrorObject());
return sb.toString();
}
sb.append("Setting 'd' succeeded\n");
PnfsGetCacheLocationsMessage locations = new PnfsGetCacheLocationsMessage(pnfsId);
try {
locations = (PnfsGetCacheLocationsMessage) sendObject("PnfsManager", locations);
} catch (Exception ee) {
sb.append("Attempt to get cache locations reported an Exception : ")
.append(ee);
sb.append("\n");
sb.append("Operation aborted\n");
return sb.toString();
}
if (locations.getReturnCode() != 0) {
sb.append("Problem in getting cache location(s) : ")
.append(locations.getErrorObject());
return sb.toString();
}
List<String> assumedLocations = locations.getCacheLocations();
sb.append("Assumed cache locations : ").append(assumedLocations.toString()).append("\n");
for (Object assumedLocation : assumedLocations) {
String poolName = assumedLocation.toString();
PoolModifyPersistencyMessage p =
new PoolModifyPersistencyMessage(poolName, pnfsId, false);
try {
p = (PoolModifyPersistencyMessage) sendObject(poolName, p);
} catch (Exception ee) {
sb.append("Attempt to contact ").
append(poolName).
append(" reported an Exception : ").
append(ee.toString()).
append("\n").
append(" Operation continues\n");
continue;
}
if (locations.getReturnCode() != 0) {
sb.append("Set 'cached' reply from ").
append(poolName).
append(" : ").
append(p.getErrorObject()).
append("\n");
} else {
sb.append("Set 'cached' OK for ").
append(poolName).
append("\n");
}
}
return sb.toString();
}
public static final String hh_flags_ls = "<pnfsId> <key>";
public Object ac_flags_ls_$_2(Args args) throws Exception
{
PnfsId pnfsId;
if (args.argv(0).startsWith("/pnfs")) {
PnfsMapPathMessage map = new PnfsMapPathMessage(args.argv(0));
map = (PnfsMapPathMessage) sendObject("PnfsManager", map);
if (map.getReturnCode() != 0) {
Object o = map.getErrorObject();
if (o instanceof Exception) {
throw (Exception) o;
} else {
throw new Exception(o.toString());
}
}
pnfsId = map.getPnfsId();
} else {
pnfsId = new PnfsId(args.argv(0));
}
String key = args.argv(1);
PnfsFlagMessage pfm = new PnfsFlagMessage(pnfsId, key, PnfsFlagMessage.FlagOperation.GET);
PnfsFlagMessage result = (PnfsFlagMessage) sendObject("PnfsManager", pfm);
return result.getReturnCode() == 0 ?
(key + " -> " + result.getValue()) :
result.getErrorObject().toString();
}
public static final String hh_pnfs_map = "<globalPath>";
public String ac_pnfs_map_$_1(Args args) throws Exception
{
if (!args.argv(0).startsWith("/pnfs")) {
throw new
IllegalArgumentException("not a global dCache path (/pnfs...)");
}
PnfsMapPathMessage map = new PnfsMapPathMessage(args.argv(0));
map = (PnfsMapPathMessage) sendObject("PnfsManager", map);
if (map.getReturnCode() != 0) {
Object o = map.getErrorObject();
if (o instanceof Exception) {
throw (Exception) o;
} else {
throw new Exception(o.toString());
}
}
return map.getPnfsId().toString();
}
//
// input remoteName
// ----------------------------------------------------------------
// / null
// /* null [no really defined]
// /<domain> System@<domain>
// /<domain>/<cell> <cell>@<domain>
// /*/<cells> <cell>
// /<domain>|*/<cells>/<module> see above
//
public static final String fh_cd =
" SYNTAX I :\n" +
" cd <cellPath>\n" +
" <cellPath> : <cellName>[@<domainName>]\n" +
" The cd command will send all subsequent commands to the specified cell.\n" +
" Use '..' to get back to local mode\n" +
"" +
" SYNTAX II : \n" +
" cd <cellDirectoryPath>\n" +
" <cellDirecotryPath> : /<domainName>[/<cellName>[/<moduleName[...]]]" +
" The cd command will send all subsequent commands to the specified cell resp. module.\n" +
" Use the standard unix directory syntax to navigate though the cell/domain realm.\n" +
" Simple '..' will bring you back to 'SYNTAX I'\n" +
" Special paths : " +
" /*/<cellName> : use the * directory for wellknown cells.\n" +
" /local : use the local directory for the local domain\n" +
" /<domain> : if no cell is given, the system cell is selected\n" +
" except for the /* director where the topo cell is\n" +
" chosen, if available\n" +
"\n";
public static final String hh_cd = "<cellPath> | <cellDirectoryPath> # see 'help cd'";
public String ac_cd_$_1(Args args) throws Exception
{
String remoteCell = args.argv(0);
Path path = new Path(remoteCell);
Position newPosition;
if (path.isDomain()) {
//
// switch back do domain mode (hyper mode or not)
//
newPosition = new Position(remoteCell);
} else if (_currentPosition.hyperMode) {
//
// we are and stay in hyper mode
//
newPosition = new Position(_currentPosition);
newPosition.mergePath(path);
} else if (path.isPath()) {
if (path.isAbsolutePath()) {
newPosition = new Position(_currentPosition);
newPosition.mergePath(path);
} else {
//
// not hyper mode, got a path but not an absolute one.
// so we wouldn't know what to do.
//
throw new
IllegalArgumentException("Need absolute path to switch to directory mode");
}
} else {
//
//
//
newPosition = new Position(remoteCell);
}
if (newPosition.remoteName != null) {
checkCellExists(newPosition.remote);
checkCdPermission(newPosition.remoteName);
}
synchronized (this) {
_currentPosition = newPosition;
}
return "";
}
private void checkCdPermission(String remoteName) throws AclException
{
int pos = remoteName.indexOf('-');
String prefix = null;
if (pos > 0) {
prefix = remoteName.substring(0, pos);
}
try {
checkPermission("cell.*.execute");
} catch (AclException acle) {
try {
checkPermission("cell." + remoteName + ".execute");
} catch (AclException acle2) {
if (prefix == null) {
throw acle2;
}
try {
checkPermission("cell." + prefix + "-pools.execute");
} catch (AclException acle3) {
throw new AclException(getUser(), remoteName);
}
}
}
}
private void checkCellExists(CellPath remoteCell)
{
try {
_cellStub.sendAndWait(remoteCell, ADMIN_COMMAND_NOOP, Object.class, CD_PROBE_MESSAGE_TIMEOUT_MS);
} catch (NoRouteToCellException e) {
throw new IllegalArgumentException("Cannot cd to this cell as it doesn't exist.");
} catch (CacheException e) {
// Some other failure, but apparently the cell exists
_log.info("Cell probe failed: {}", e.getMessage());
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
@Override
public int complete(String buffer, int cursor, List<CharSequence> candidates)
{
try {
if (_completer == null) {
Object help = executeCommand("help");
if (help == null) {
return -1;
}
_completer = new HelpCompleter(String.valueOf(help));
}
return _completer.complete(buffer, cursor, candidates);
} catch (Exception e) {
_log.info("Completion failed: " + e.toString());
return -1;
}
}
public Object executeCommand(String str) throws CommandException, InterruptedException, NoRouteToCellException
{
_log.info("String command (super) " + str);
if (str.trim().isEmpty()) {
return "";
}
if (str.equals("..")) {
_currentPosition.clearHyperMode();
_currentPosition.gotoLocal();
return "";
}
Args args = new Args(str);
if (_currentPosition.remote == null) {
return localCommand(args);
} else {
if (_currentPosition.hyperMode) {
if ((args.argc() == 1) && (args.argv(0).equals("cd"))) {
_currentPosition.gotoLocal();
return "";
} else if ((args.argc() > 1) && (args.argv(0).equals("cd"))) {
return localCommand(args);
}
String prefix = _currentPosition.getPrefix();
if (!prefix.isEmpty()) {
if ((args.argc() >= 1) && (args.argv(0).equals("help"))) {
if (args.argc() == 1) {
str = "help " + prefix;
}
} else {
str = prefix + " " + str;
}
}
}
return sendObject(_currentPosition.remote, new AuthorizedString(_user, str));
}
}
private Object localCommand(Args args) throws CommandException
{
_log.info("Local command {}", args);
Object or = command(args);
if (or == null) {
return "";
}
String r = or.toString();
if (r.length() < 1) {
return "";
}
if (r.substring(r.length() - 1).equals("\n")) {
return r;
} else {
return r + "\n";
}
}
private Object sendObject(String cellPath, Serializable object)
throws NoRouteToCellException, InterruptedException, CommandException
{
return sendObject(new CellPath(cellPath), object);
}
private Object sendObject(CellPath cellPath, Serializable object)
throws NoRouteToCellException, InterruptedException, CommandException
{
try {
return _cellStub.send(cellPath, object, Object.class, _timeout).get();
} catch (ExecutionException e) {
Throwable cause = e.getCause();
if (_fullException) {
return getStackTrace(cause);
}
Throwables.throwIfInstanceOf(cause, Error.class);
Throwables.throwIfInstanceOf(cause, NoRouteToCellException.class);
Throwables.throwIfInstanceOf(cause, CommandException.class);
throw new CommandThrowableException(cause.toString(), cause);
}
}
protected Object sendCommand(CellPath destination, String command)
throws InterruptedException, NoRouteToCellException, TimeoutCacheException
{
try {
Object obj = _cellStub.sendAndWait(destination,
new AuthorizedString(_user, command),
Object.class,
_timeout);
if (obj instanceof Throwable && _fullException) {
return getStackTrace((Throwable) obj);
}
return obj;
} catch (TimeoutCacheException e) {
throw new TimeoutCacheException("Request timed out");
} catch (CacheException e) {
if (_fullException) {
return getStackTrace(e);
}
return e;
}
}
private Object getStackTrace(Throwable obj)
{
CharArrayWriter ca = new CharArrayWriter();
obj.printStackTrace(new PrintWriter(ca));
return ca.toString();
}
public Object executeCommand(CellPath destination, Object str)
throws InterruptedException, TimeoutCacheException, NoRouteToCellException
{
_log.info("Object command ({}) {}",destination, str);
return sendCommand(destination, str.toString());
}
}