You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@airavata.apache.org by ma...@apache.org on 2017/09/26 19:09:56 UTC
[27/40] airavata git commit: AIRAVATA-2500 Improved error handling,
error messages
AIRAVATA-2500 Improved error handling, error messages
Project: http://git-wip-us.apache.org/repos/asf/airavata/repo
Commit: http://git-wip-us.apache.org/repos/asf/airavata/commit/66689a8b
Tree: http://git-wip-us.apache.org/repos/asf/airavata/tree/66689a8b
Diff: http://git-wip-us.apache.org/repos/asf/airavata/diff/66689a8b
Branch: refs/heads/develop
Commit: 66689a8b817f534d80e1ed0f2594509f53190e95
Parents: 7437112
Author: Marcus Christie <ma...@apache.org>
Authored: Wed Sep 20 14:48:49 2017 -0400
Committer: Marcus Christie <ma...@apache.org>
Committed: Wed Sep 20 15:04:53 2017 -0400
----------------------------------------------------------------------
.../InvalidSetupException.java | 43 ++++++++++
.../InvalidUsernameException.java | 43 ++++++++++
.../accountprovisioning/SSHAccountManager.java | 89 +++++++++++++++-----
.../SSHAccountProvisioner.java | 8 +-
.../airavata/accountprovisioning/SSHUtil.java | 2 +-
.../IULdapSSHAccountProvisioner.java | 15 ++--
.../provisioner/TestSSHAccountProvisioner.java | 10 ++-
7 files changed, 175 insertions(+), 35 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/airavata/blob/66689a8b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/InvalidSetupException.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/InvalidSetupException.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/InvalidSetupException.java
new file mode 100644
index 0000000..004ec97
--- /dev/null
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/InvalidSetupException.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.accountprovisioning;
+
+/**
+ * This exception indicates that some SSHAccountProvisioner setup is missing or incorrect.
+ * Message should indicate what is invalid and potentially how to fix it.
+ */
+public class InvalidSetupException extends Exception {
+
+ public InvalidSetupException() {
+ }
+
+ public InvalidSetupException(String message) {
+ super(message);
+ }
+
+ public InvalidSetupException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InvalidSetupException(Throwable cause) {
+ super(cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/airavata/blob/66689a8b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/InvalidUsernameException.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/InvalidUsernameException.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/InvalidUsernameException.java
new file mode 100644
index 0000000..f78d7df
--- /dev/null
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/InvalidUsernameException.java
@@ -0,0 +1,43 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ *
+ */
+
+package org.apache.airavata.accountprovisioning;
+
+/**
+ * Thrown by {@link SSHAccountProvisioner} when provided userId doesn't map to a local account for any user. For
+ * example, the provided userId maps to a username that doesn't have an account on the cluster but that also doesn't
+ * exist at that institution.
+ */
+public class InvalidUsernameException extends Exception {
+ public InvalidUsernameException() {
+ }
+
+ public InvalidUsernameException(String message) {
+ super(message);
+ }
+
+ public InvalidUsernameException(String message, Throwable cause) {
+ super(message, cause);
+ }
+
+ public InvalidUsernameException(Throwable cause) {
+ super(cause);
+ }
+}
http://git-wip-us.apache.org/repos/asf/airavata/blob/66689a8b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java
index 70c144c..61deb49 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountManager.java
@@ -50,7 +50,7 @@ public class SSHAccountManager {
private final static Logger logger = LoggerFactory.getLogger(SSHAccountManager.class);
- public static boolean doesUserHaveSSHAccount(String gatewayId, String computeResourceId, String username) {
+ public static boolean doesUserHaveSSHAccount(String gatewayId, String computeResourceId, String username) throws InvalidSetupException, InvalidUsernameException {
// get compute resource preferences for the gateway and hostname
RegistryService.Client registryServiceClient = getRegistryServiceClient();
@@ -58,23 +58,32 @@ public class SSHAccountManager {
try {
computeResourcePreference = registryServiceClient.getGatewayComputeResourcePreference(gatewayId, computeResourceId);
} catch(TException e) {
- throw new RuntimeException(e);
+ throw new RuntimeException("Failed to get ComputeResourcePreference for [" + gatewayId + "] and [" + computeResourceId + "]: " + e.getMessage(), e);
} finally {
if (registryServiceClient.getInputProtocol().getTransport().isOpen()) {
registryServiceClient.getInputProtocol().getTransport().close();
}
+ if (registryServiceClient.getOutputProtocol().getTransport().isOpen()) {
+ registryServiceClient.getOutputProtocol().getTransport().close();
+ }
}
// get the account provisioner and config values for the preferences
if (!computeResourcePreference.isSetSshAccountProvisioner()) {
- throw new RuntimeException("Compute resource [" + computeResourceId + "] does not have an SSH Account Provisioner configured for it.");
+ throw new InvalidSetupException("Compute resource [" + computeResourceId + "] does not have an SSH Account Provisioner configured for it.");
}
SSHAccountProvisioner sshAccountProvisioner = createSshAccountProvisioner(gatewayId, computeResourcePreference);
- return sshAccountProvisioner.hasAccount(username);
+ try {
+ return sshAccountProvisioner.hasAccount(username);
+ } catch (InvalidUsernameException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("hasAccount call failed for username [" + username + "]: " + e.getMessage(), e);
+ }
}
- public static UserComputeResourcePreference setupSSHAccount(String gatewayId, String computeResourceId, String username, SSHCredential sshCredential) {
+ public static UserComputeResourcePreference setupSSHAccount(String gatewayId, String computeResourceId, String username, SSHCredential sshCredential) throws InvalidSetupException, InvalidUsernameException {
// get compute resource preferences for the gateway and hostname
RegistryService.Client registryServiceClient = getRegistryServiceClient();
@@ -92,20 +101,26 @@ public class SSHAccountManager {
}
}
} catch(TException e) {
- throw new RuntimeException(e);
+ throw new RuntimeException("Failed to retrieve compute resource information for [" + gatewayId + "] and " +
+ "[" + computeResourceId + "]: " + e.getMessage(), e);
} finally {
if (registryServiceClient.getInputProtocol().getTransport().isOpen()) {
registryServiceClient.getInputProtocol().getTransport().close();
}
+ if (registryServiceClient.getOutputProtocol().getTransport().isOpen()) {
+ registryServiceClient.getOutputProtocol().getTransport().close();
+ }
}
if (sshJobSubmission == null) {
- throw new RuntimeException("Compute resource [" + computeResourceId + "] does not have an SSH Job Submission interface.");
+ throw new InvalidSetupException("Compute resource [" + computeResourceId + "] does not have an SSH Job Submission " +
+ "interface.");
}
// get the account provisioner and config values for the preferences
if (!computeResourcePreference.isSetSshAccountProvisioner()) {
- throw new RuntimeException("Compute resource [" + computeResourceId + "] does not have an SSH Account Provisioner configured for it.");
+ throw new InvalidSetupException("Compute resource [" + computeResourceId + "] does not have an SSH Account Provisioner " +
+ "configured for it.");
}
// instantiate and init the account provisioner
@@ -113,19 +128,39 @@ public class SSHAccountManager {
boolean canCreateAccount = SSHAccountProvisionerFactory.canCreateAccount(computeResourcePreference.getSshAccountProvisioner());
// First check if username has an account
- boolean hasAccount = sshAccountProvisioner.hasAccount(username);
+ boolean hasAccount = false;
+ try {
+ hasAccount = sshAccountProvisioner.hasAccount(username);
+ } catch (InvalidUsernameException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("hasAccount call failed for username [" + username + "]: " + e.getMessage(), e);
+ }
if (!hasAccount && !canCreateAccount) {
- throw new RuntimeException("User [" + username + "] doesn't have account and [" + computeResourceId + "] doesn't have a SSH Account Provisioner that supports creating accounts.");
+ throw new InvalidSetupException("User [" + username + "] doesn't have account and [" + computeResourceId + "] doesn't " +
+ "have a SSH Account Provisioner that supports creating accounts.");
}
// Install SSH key
- sshAccountProvisioner.installSSHKey(username, sshCredential.getPublicKey());
+ try {
+ sshAccountProvisioner.installSSHKey(username, sshCredential.getPublicKey());
+ } catch (InvalidUsernameException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new RuntimeException("installSSHKey call failed for username [" + username + "]: " + e.getMessage(), e);
+ }
// Verify can authenticate to host
String sshHostname = sshJobSubmission.getAlternativeSSHHostName() != null ? sshJobSubmission.getAlternativeSSHHostName() : computeResourceDescription.getHostName();
int sshPort = sshJobSubmission.getSshPort();
- boolean validated = SSHUtil.validate(sshHostname, sshPort, username, sshCredential);
+ boolean validated = false;
+ try {
+ validated = SSHUtil.validate(sshHostname, sshPort, username, sshCredential);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to validate SSH public key installation for account for user [" +
+ username + "] on host [" + sshHostname + "]: " + e.getMessage(), e);
+ }
if (!validated) {
throw new RuntimeException("Failed to validate installation of key for [" + username
+ "] on [" + computeResourceDescription.getHostName() + "] using SSH Account Provisioner ["
@@ -134,7 +169,12 @@ public class SSHAccountManager {
// create the scratch location on the host
String scratchLocation = sshAccountProvisioner.getScratchLocation(username);
- SSHUtil.execute(sshHostname, sshPort, username, sshCredential, "mkdir -p " + scratchLocation);
+ try {
+ SSHUtil.execute(sshHostname, sshPort, username, sshCredential, "mkdir -p " + scratchLocation);
+ } catch (Exception e) {
+ throw new RuntimeException("Failed to create scratch location [" + scratchLocation + "] for user [" +
+ username + "] on host [" + sshHostname + "]: " + e.getMessage(), e);
+ }
UserComputeResourcePreference userComputeResourcePreference = new UserComputeResourcePreference();
userComputeResourcePreference.setComputeResourceId(computeResourceId);
@@ -143,7 +183,7 @@ public class SSHAccountManager {
return userComputeResourcePreference;
}
- private static SSHAccountProvisioner createSshAccountProvisioner(String gatewayId, ComputeResourcePreference computeResourcePreference) {
+ private static SSHAccountProvisioner createSshAccountProvisioner(String gatewayId, ComputeResourcePreference computeResourcePreference) throws InvalidSetupException {
String provisionerName = computeResourcePreference.getSshAccountProvisioner();
Map<ConfigParam,String> provisionerConfig = convertConfigParams(provisionerName, computeResourcePreference.getSshAccountProvisionerConfig());
@@ -153,7 +193,7 @@ public class SSHAccountManager {
return SSHAccountProvisionerFactory.createSSHAccountProvisioner(provisionerName, resolvedConfig);
}
- private static Map<ConfigParam, String> resolveProvisionerConfig(String gatewayId, String provisionerName, Map<ConfigParam, String> provisionerConfig) {
+ private static Map<ConfigParam, String> resolveProvisionerConfig(String gatewayId, String provisionerName, Map<ConfigParam, String> provisionerConfig) throws InvalidSetupException {
CredentialStoreService.Client credentialStoreServiceClient = null;
try {
credentialStoreServiceClient = getCredentialStoreClient();
@@ -163,6 +203,10 @@ public class SSHAccountManager {
if (configEntry.getKey().getType() == ConfigParam.ConfigParamType.CRED_STORE_PASSWORD_TOKEN) {
try {
PasswordCredential password = credentialStoreServiceClient.getPasswordCredential(configEntry.getValue(), gatewayId);
+ if (password == null) {
+ throw new InvalidSetupException("Password credential doesn't exist for config param ["
+ + configEntry.getKey().getName() + "] for token [" + configEntry.getValue() + "] for provisioner [" + provisionerName + "].");
+ }
resolvedConfig.put(configEntry.getKey(), password.getPassword());
} catch (TException e) {
throw new RuntimeException("Failed to get password needed to configure " + provisionerName, e);
@@ -177,17 +221,24 @@ public class SSHAccountManager {
if (credentialStoreServiceClient.getInputProtocol().getTransport().isOpen()) {
credentialStoreServiceClient.getInputProtocol().getTransport().close();
}
+ if (credentialStoreServiceClient.getOutputProtocol().getTransport().isOpen()) {
+ credentialStoreServiceClient.getOutputProtocol().getTransport().close();
+ }
}
}
}
- private static Map<ConfigParam, String> convertConfigParams(String provisionerName, Map<String, String> thriftConfigParams) {
- // TODO: also check that all required parameters are present?
- // TODO: also, this doesn't handle optional entries which should be skipped if missing from thriftConfigParams
+ private static Map<ConfigParam, String> convertConfigParams(String provisionerName, Map<String, String> thriftConfigParams) throws InvalidSetupException {
List<ConfigParam> configParams = SSHAccountProvisionerFactory.getSSHAccountProvisionerConfigParams(provisionerName);
Map<String, ConfigParam> configParamMap = configParams.stream().collect(Collectors.toMap(ConfigParam::getName, Function.identity()));
- return thriftConfigParams.entrySet().stream().collect(Collectors.toMap(entry -> configParamMap.get(entry.getKey()), entry -> entry.getValue()));
+ Map<ConfigParam, String> result = thriftConfigParams.entrySet().stream().collect(Collectors.toMap(entry -> configParamMap.get(entry.getKey()), entry -> entry.getValue()));
+ for (ConfigParam configParam : configParams) {
+ if (!configParam.isOptional() && !result.containsKey(configParam)) {
+ throw new InvalidSetupException("Missing required ConfigParam named [" + configParam.getName() + "] for provisioner [" + provisionerName + "].");
+ }
+ }
+ return result;
}
private static RegistryService.Client getRegistryServiceClient() {
http://git-wip-us.apache.org/repos/asf/airavata/blob/66689a8b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java
index b8abf1f..866ef5c 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHAccountProvisioner.java
@@ -25,8 +25,8 @@ import java.util.Map;
public interface SSHAccountProvisioner {
void init(Map<ConfigParam, String> config);
- boolean hasAccount(String userId);
- void createAccount(String userId, String sshPublicKey);
- void installSSHKey(String userId, String sshPublicKey);
- String getScratchLocation(String userId);
+ boolean hasAccount(String userId) throws InvalidUsernameException;
+ void createAccount(String userId, String sshPublicKey) throws InvalidUsernameException;
+ void installSSHKey(String userId, String sshPublicKey) throws InvalidUsernameException;
+ String getScratchLocation(String userId) throws InvalidUsernameException;
}
http://git-wip-us.apache.org/repos/asf/airavata/blob/66689a8b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java
index 2550270..4ac60bf 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/SSHUtil.java
@@ -53,7 +53,7 @@ public class SSHUtil {
session.connect();
return true;
} catch (JSchException e) {
- throw new RuntimeException(e.getMessage(), e);
+ throw new RuntimeException(e);
} finally {
if (session != null && session.isConnected()) {
session.disconnect();
http://git-wip-us.apache.org/repos/asf/airavata/blob/66689a8b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
index d0c204f..4f0ad07 100644
--- a/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
+++ b/modules/compute-account-provisioning/src/main/java/org/apache/airavata/accountprovisioning/provisioner/IULdapSSHAccountProvisioner.java
@@ -21,6 +21,7 @@
package org.apache.airavata.accountprovisioning.provisioner;
import org.apache.airavata.accountprovisioning.ConfigParam;
+import org.apache.airavata.accountprovisioning.InvalidUsernameException;
import org.apache.airavata.accountprovisioning.SSHAccountManager;
import org.apache.airavata.accountprovisioning.SSHAccountProvisioner;
import org.apache.directory.api.ldap.model.entry.DefaultAttribute;
@@ -62,7 +63,7 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
}
@Override
- public boolean hasAccount(String userId) {
+ public boolean hasAccount(String userId) throws InvalidUsernameException {
String username = getUsername(userId);
boolean result = withLdapConnection(ldapConnection -> {
try {
@@ -75,13 +76,13 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
}
@Override
- public void createAccount(String userId, String sshPublicKey) {
+ public void createAccount(String userId, String sshPublicKey) throws InvalidUsernameException {
throw new UnsupportedOperationException("IULdapSSHAccountProvisioner does not support creating cluster accounts at this time.");
}
@Override
- public void installSSHKey(String userId, String sshPublicKey) {
+ public void installSSHKey(String userId, String sshPublicKey) throws InvalidUsernameException {
String username = getUsername(userId);
boolean success = withLdapConnection(ldapConnection -> {
try {
@@ -119,7 +120,7 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
}
@Override
- public String getScratchLocation(String userId) {
+ public String getScratchLocation(String userId) throws InvalidUsernameException {
String username = getUsername(userId);
String scratchLocation = canonicalScratchLocation.replace("${username}",username);
return scratchLocation;
@@ -147,15 +148,15 @@ public class IULdapSSHAccountProvisioner implements SSHAccountProvisioner {
* Convert from Airavata userId to cluster username. The assumption here is that a userId will be
* an IU email address and the username is just the username portion of the email address.
*/
- private String getUsername(String userId) {
+ private String getUsername(String userId) throws InvalidUsernameException {
int atSignIndex = userId.indexOf("@");
if (atSignIndex < 0) {
- throw new RuntimeException("userId is not an email address: " + userId);
+ throw new InvalidUsernameException("userId is not an email address: " + userId);
}
return userId.substring(0, atSignIndex);
}
- public static void main(String[] args) {
+ public static void main(String[] args) throws InvalidUsernameException {
String ldapPassword = args[0];
IULdapSSHAccountProvisioner sshAccountProvisioner = new IULdapSSHAccountProvisioner();
Map<ConfigParam,String> config = new HashMap<>();
http://git-wip-us.apache.org/repos/asf/airavata/blob/66689a8b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java
----------------------------------------------------------------------
diff --git a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java
index f47552f..f4f9958 100644
--- a/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java
+++ b/modules/compute-account-provisioning/src/test/java/org/apache/airavata/accountprovisioning/provisioner/TestSSHAccountProvisioner.java
@@ -21,6 +21,7 @@
package org.apache.airavata.accountprovisioning.provisioner;
import org.apache.airavata.accountprovisioning.ConfigParam;
+import org.apache.airavata.accountprovisioning.InvalidUsernameException;
import org.apache.airavata.accountprovisioning.SSHAccountProvisioner;
import java.util.Map;
@@ -36,25 +37,26 @@ public class TestSSHAccountProvisioner implements SSHAccountProvisioner {
}
@Override
- public boolean hasAccount(String username) {
+ public boolean hasAccount(String userId) throws InvalidUsernameException {
return false;
}
@Override
- public void createAccount(String username, String sshPublicKey) {
+ public void createAccount(String userId, String sshPublicKey) throws InvalidUsernameException {
}
@Override
- public void installSSHKey(String username, String sshPublicKey) {
+ public void installSSHKey(String userId, String sshPublicKey) throws InvalidUsernameException {
}
@Override
- public String getScratchLocation(String username) {
+ public String getScratchLocation(String userId) throws InvalidUsernameException {
return null;
}
+ // This is here just to facilitate testing
public Map<ConfigParam, String> getConfig() {
return config;
}