allocation map takes into account the infrastructure context
git-svn-id: https://svn.research-infrastructures.eu/d4science/gcube/trunk/portlets/user/rstudio-wrapper-portlet@142831 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
e46051e252
commit
8d851ca255
|
@ -7,11 +7,13 @@ import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
||||||
import java.net.MalformedURLException;
|
import java.net.MalformedURLException;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.gcube.common.portal.PortalContext;
|
import org.gcube.common.portal.PortalContext;
|
||||||
import org.gcube.common.resources.gcore.ServiceEndpoint;
|
import org.gcube.common.resources.gcore.ServiceEndpoint;
|
||||||
import org.gcube.common.scope.api.ScopeProvider;
|
import org.gcube.common.scope.api.ScopeProvider;
|
||||||
import org.gcube.portlets.user.rstudio_wrapper_portlet.client.RStudioService;
|
import org.gcube.portlets.user.rstudio_wrapper_portlet.client.RStudioService;
|
||||||
|
import org.gcube.portlets.user.rstudio_wrapper_portlet.shared.RStudioInstance;
|
||||||
import org.gcube.resources.discovery.client.api.DiscoveryClient;
|
import org.gcube.resources.discovery.client.api.DiscoveryClient;
|
||||||
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
|
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
|
||||||
import org.gcube.vomanagement.usermanagement.UserManager;
|
import org.gcube.vomanagement.usermanagement.UserManager;
|
||||||
|
@ -32,6 +34,7 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
|
|
||||||
private static final Logger _log = LoggerFactory.getLogger(RStudioServiceImpl.class);
|
private static final Logger _log = LoggerFactory.getLogger(RStudioServiceImpl.class);
|
||||||
|
|
||||||
|
private static final String RSTUDIO_INSTANCES = "RStudio-Instances";
|
||||||
private static final String RSTUDIO_URL = "RStudio-URL";
|
private static final String RSTUDIO_URL = "RStudio-URL";
|
||||||
private static final String RCONNECTOR_EntryName = "org.gcube.data.analysis.rconnector.RConnector";
|
private static final String RCONNECTOR_EntryName = "org.gcube.data.analysis.rconnector.RConnector";
|
||||||
private static final String PATH_TO_RCONNECTOR = "/r-connector/gcube/service/connect";
|
private static final String PATH_TO_RCONNECTOR = "/r-connector/gcube/service/connect";
|
||||||
|
@ -48,6 +51,9 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
// user = "costantino.perciante";
|
// user = "costantino.perciante";
|
||||||
return user;
|
return user;
|
||||||
}
|
}
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
*/
|
||||||
@Override
|
@Override
|
||||||
public String retrieveRStudioSecureURL() throws IllegalArgumentException {
|
public String retrieveRStudioSecureURL() throws IllegalArgumentException {
|
||||||
String toReturn = "";
|
String toReturn = "";
|
||||||
|
@ -78,20 +84,31 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
_log.debug("calling rConnector with scope = " + scope + " and token = "+token );
|
_log.debug("calling rConnector with scope = " + scope + " and token = "+token );
|
||||||
List<ServiceEndpoint> resources = getRStudioServiceEndpoints(scope);
|
List<ServiceEndpoint> resources = getRStudioServiceEndpoints(scope);
|
||||||
if (resources.size() == 0){
|
if (resources.size() == 0){
|
||||||
_log.warn("There is no Servcie Endpoint having CATEGORY " + CATEGORY +" and NAME " + SERVICE_EP_NAME + " in this scope. Returning default instance");
|
_log.warn("There is no Service Endpoint having CATEGORY " + CATEGORY +" and NAME " + SERVICE_EP_NAME + " in this scope. Returning default instance");
|
||||||
toReturn = rConnector().build().connect().toURL().toExternalForm();
|
toReturn = rConnector().build().connect().toURL().toExternalForm();
|
||||||
} else {
|
} else {
|
||||||
UserManager um = new LiferayUserManager();
|
UserManager um = new LiferayUserManager();
|
||||||
_log.debug("Checking if user " + curUser.getFullname() + " has already an RStudio Instance set ... ");
|
_log.debug("Checking if user " + curUser.getFullname() + " has already an RStudio Instance set ... ");
|
||||||
//check RStudio
|
String hostedOnSet = null;
|
||||||
|
|
||||||
|
//check if an RStudio instance was previously set (RETRO-COMPATIBILY)
|
||||||
if (um.readCustomAttr(userId, RSTUDIO_URL) != null && um.readCustomAttr(userId, RSTUDIO_URL).toString().compareTo("") != 0) {
|
if (um.readCustomAttr(userId, RSTUDIO_URL) != null && um.readCustomAttr(userId, RSTUDIO_URL).toString().compareTo("") != 0) {
|
||||||
String hostedOn = (String) um.readCustomAttr(userId, RSTUDIO_URL);
|
_log.debug("User had already an RStudio Instance set, upgrading to new version ");
|
||||||
_log.info("**** The instance set for user " + curUser.getFullname() + " is " + hostedOn);
|
hostedOnSet = (String) um.readCustomAttr(userId, RSTUDIO_URL);
|
||||||
toReturn = getRConnectorURL(hostedOn, token);
|
writeRStudioInstanceInScope(um, curUser, scope, hostedOnSet);
|
||||||
_log.debug("User " + curUser.getFullname() + " has RStudio Instance set, returning rConnector URL " + toReturn);
|
um.saveCustomAttr(userId, RSTUDIO_URL, ""); //reset the old value to blank so that from now on it will read from the new field
|
||||||
|
}
|
||||||
|
|
||||||
|
hostedOnSet = getUserRStudioInstances(um,curUser).get(scope);
|
||||||
|
|
||||||
|
_log.info("**** Checking if still exist on this scope: " + scope);
|
||||||
|
//if the instance exists and is still available in the given context
|
||||||
|
if (hostedOnSet != null && checkRStudioInstanceExistence(curUser, hostedOnSet, resources) ) {
|
||||||
|
toReturn = getRConnectorURL(hostedOnSet, token);
|
||||||
|
_log.info("User " + curUser.getFullname() + " has RStudio Instance set and is valid, returning rConnector URL " + toReturn);
|
||||||
}
|
}
|
||||||
else {//need to find the RStudio
|
else {//need to find the RStudio
|
||||||
_log.info("User " + curUser.getFullname() + "DOES NOT HAVE RStudio Instance set, calculating allocation ... ");
|
_log.info("User " + curUser.getFullname() + " DOES NOT have RStudio Instance set or the instance previous set no longer exists, calculating allocation ... ");
|
||||||
HashMap<String, Integer> rStudioDistributionMap = new HashMap<>();
|
HashMap<String, Integer> rStudioDistributionMap = new HashMap<>();
|
||||||
for (ServiceEndpoint res : resources) {
|
for (ServiceEndpoint res : resources) {
|
||||||
String hostedOn = res.profile().runtime().hostedOn();
|
String hostedOn = res.profile().runtime().hostedOn();
|
||||||
|
@ -100,8 +117,8 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
List<GCubeUser> vreUsers = um.listUsersByGroup(pContext.getCurrentGroupId(getThreadLocalRequest()), false);
|
List<GCubeUser> vreUsers = um.listUsersByGroup(pContext.getCurrentGroupId(getThreadLocalRequest()), false);
|
||||||
_log.debug("VRE " + scope + " has totalUsers = " + vreUsers.size());
|
_log.debug("VRE " + scope + " has totalUsers = " + vreUsers.size());
|
||||||
for (GCubeUser gCubeUser : vreUsers) {
|
for (GCubeUser gCubeUser : vreUsers) {
|
||||||
if (um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_URL) != null && um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_URL).toString().compareTo("") != 0) {
|
if (getUserRStudioInstances(um,gCubeUser).get(scope) != null) {
|
||||||
String hostedOn = (String) um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_URL);
|
String hostedOn = getUserRStudioInstances(um,gCubeUser).get(scope);
|
||||||
if (rStudioDistributionMap.containsKey(hostedOn)) {
|
if (rStudioDistributionMap.containsKey(hostedOn)) {
|
||||||
int noToSet = rStudioDistributionMap.get(hostedOn)+1;
|
int noToSet = rStudioDistributionMap.get(hostedOn)+1;
|
||||||
rStudioDistributionMap.put(hostedOn, noToSet);
|
rStudioDistributionMap.put(hostedOn, noToSet);
|
||||||
|
@ -126,8 +143,8 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
}
|
}
|
||||||
i++;
|
i++;
|
||||||
}
|
}
|
||||||
um.saveCustomAttr(userId, RSTUDIO_URL, host2Select);
|
writeRStudioInstanceInScope(um, curUser, scope, host2Select);
|
||||||
_log.debug("User " + curUser.getFullname() + " RStudio Instance set calculated = " + host2Select);
|
_log.debug("User " + curUser.getFullname() + " RStudio Instance set calculated = " + host2Select + " for context " + scope);
|
||||||
toReturn = getRConnectorURL(host2Select, token);
|
toReturn = getRConnectorURL(host2Select, token);
|
||||||
_log.debug("User " + curUser.getFullname() + " has RStudio Instance set, returning rConnector URL " + toReturn);
|
_log.debug("User " + curUser.getFullname() + " has RStudio Instance set, returning rConnector URL " + toReturn);
|
||||||
}
|
}
|
||||||
|
@ -140,6 +157,49 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @param um
|
||||||
|
* @param gCubeUser
|
||||||
|
* @return a map containing the scope and the RStudio Instances set for this user
|
||||||
|
* @throws UserRetrievalFault
|
||||||
|
*/
|
||||||
|
private Map<String, String> getUserRStudioInstances(UserManager um, GCubeUser gCubeUser) throws UserRetrievalFault {
|
||||||
|
Map<String, String> theInstances = new HashMap<>();
|
||||||
|
if (um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_INSTANCES) != null && um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_INSTANCES).toString().compareTo("") != 0) {
|
||||||
|
String[] values = (String[]) um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_INSTANCES);
|
||||||
|
if (values != null && values.length > 0) {
|
||||||
|
for (int i = 0; i < values.length; i++) {
|
||||||
|
String[] splits = values[i].split("\\|");
|
||||||
|
RStudioInstance istance = new RStudioInstance(splits);
|
||||||
|
theInstances.put(istance.getContext(), istance.getHostedOn());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return theInstances;
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* write the RStudio Instance
|
||||||
|
* @param um
|
||||||
|
* @param gCubeUser
|
||||||
|
* @param context the infra scope
|
||||||
|
* @param hostedOn
|
||||||
|
* @throws UserRetrievalFault
|
||||||
|
*/
|
||||||
|
private void writeRStudioInstanceInScope(UserManager um, GCubeUser gCubeUser, String context, String hostedOn) throws UserRetrievalFault {
|
||||||
|
Map<String, String> theInstances = getUserRStudioInstances(um, gCubeUser);
|
||||||
|
theInstances.put(context, hostedOn);
|
||||||
|
String[] theValues = new String[theInstances.size()];
|
||||||
|
int i = 0;
|
||||||
|
for (String instanceScope : theInstances.keySet()) {
|
||||||
|
String toPut = instanceScope+"|"+theInstances.get(instanceScope); //-> /gcube/devNext/NextNext|rstudio.d4science.org:443
|
||||||
|
theValues[i] = toPut;
|
||||||
|
i++;
|
||||||
|
}
|
||||||
|
//overwrite the values
|
||||||
|
um.saveCustomAttr(gCubeUser.getUserId(), RSTUDIO_INSTANCES, theValues);
|
||||||
|
}
|
||||||
|
|
||||||
private String getRConnectorURL(String hostedOn, String token) throws MalformedURLException, IllegalArgumentException {
|
private String getRConnectorURL(String hostedOn, String token) throws MalformedURLException, IllegalArgumentException {
|
||||||
String[] splits = hostedOn.split(":");
|
String[] splits = hostedOn.split(":");
|
||||||
int port = 80;
|
int port = 80;
|
||||||
|
@ -155,33 +215,6 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
return "http://"+hostedOn+PATH_TO_RCONNECTOR+"?gcube-token="+token;
|
return "http://"+hostedOn+PATH_TO_RCONNECTOR+"?gcube-token="+token;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// private String getRConnectorURL(String hostedOn, String token) {
|
|
||||||
// _log.info("getRConnectorURL hostedOn:" + hostedOn);
|
|
||||||
// String[] splits = hostedOn.split(":");
|
|
||||||
// String host = splits[0];
|
|
||||||
// int port = 80;
|
|
||||||
// try {
|
|
||||||
// port = Integer.parseInt(splits[1]);
|
|
||||||
// } catch (Exception e) {
|
|
||||||
// _log.warn("Could not find an integer after :, using default port 80");
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// String toReturn = "";
|
|
||||||
// try {
|
|
||||||
// toReturn = rConnector().at(host, port).build().connect().toURL().toExternalForm();
|
|
||||||
// } catch (MalformedURLException | IllegalArgumentException e) {
|
|
||||||
// e.printStackTrace();
|
|
||||||
// return null;
|
|
||||||
// }
|
|
||||||
// if ((port == 443 || port == 8443) && !toReturn.startsWith("https")) {
|
|
||||||
// toReturn = toReturn.replaceFirst("http", "https");
|
|
||||||
// return toReturn;
|
|
||||||
// }
|
|
||||||
// else {
|
|
||||||
// return toReturn;
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @return the
|
* @return the
|
||||||
|
@ -199,21 +232,13 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
ScopeProvider.instance.set(currScope);
|
ScopeProvider.instance.set(currScope);
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
// /**
|
|
||||||
// *
|
private static boolean checkRStudioInstanceExistence(GCubeUser curUser, String hostedOn, List<ServiceEndpoint> resources) {
|
||||||
// * @return the
|
for (ServiceEndpoint serviceEndpoint : resources)
|
||||||
// * @throws Exception
|
if (serviceEndpoint.profile().runtime().hostedOn().equals(hostedOn)) {
|
||||||
// */
|
_log.info("**** The instance previously set for user " + curUser.getFullname() + " on " + hostedOn + " is still valid");
|
||||||
// private List<GCoreEndpoint> getRStudioServiceEndpoints(String scope) throws Exception {
|
return true;
|
||||||
// _log.debug("getRStudioServiceEndpoints on scope="+scope );
|
}
|
||||||
// String currScope = ScopeProvider.instance.get();
|
return false;
|
||||||
// ScopeProvider.instance.set(scope);
|
}
|
||||||
// SimpleQuery query = queryFor(GCoreEndpoint.class);
|
|
||||||
// query.addCondition("$resource/Profile/ServiceName/text() eq '"+ SERVICE_NAME +"'");
|
|
||||||
// query.addCondition("$resource/Profile/ServiceClass/text() eq '"+ SERVICECLASS +"'");
|
|
||||||
// DiscoveryClient<GCoreEndpoint> client = clientFor(GCoreEndpoint.class);
|
|
||||||
// List<GCoreEndpoint> toReturn = client.submit(query);
|
|
||||||
// ScopeProvider.instance.set(currScope);
|
|
||||||
// return toReturn;
|
|
||||||
// }
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,42 +0,0 @@
|
||||||
package org.gcube.portlets.user.rstudio_wrapper_portlet.shared;
|
|
||||||
|
|
||||||
/**
|
|
||||||
* <p>
|
|
||||||
* FieldVerifier validates that the name the user enters is valid.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* This class is in the <code>shared</code> packing because we use it in both
|
|
||||||
* the client code and on the server. On the client, we verify that the name is
|
|
||||||
* valid before sending an RPC request so the user doesn't have to wait for a
|
|
||||||
* network round trip to get feedback. On the server, we verify that the name is
|
|
||||||
* correct to ensure that the input is correct regardless of where the RPC
|
|
||||||
* originates.
|
|
||||||
* </p>
|
|
||||||
* <p>
|
|
||||||
* When creating a class that is used on both the client and the server, be sure
|
|
||||||
* that all code is translatable and does not use native JavaScript. Code that
|
|
||||||
* is note translatable (such as code that interacts with a database or the file
|
|
||||||
* system) cannot be compiled into client side JavaScript. Code that uses native
|
|
||||||
* JavaScript (such as Widgets) cannot be run on the server.
|
|
||||||
* </p>
|
|
||||||
*/
|
|
||||||
public class FieldVerifier {
|
|
||||||
|
|
||||||
/**
|
|
||||||
* Verifies that the specified name is valid for our service.
|
|
||||||
*
|
|
||||||
* In this example, we only require that the name is at least four
|
|
||||||
* characters. In your application, you can use more complex checks to ensure
|
|
||||||
* that usernames, passwords, email addresses, URLs, and other fields have the
|
|
||||||
* proper syntax.
|
|
||||||
*
|
|
||||||
* @param name the name to validate
|
|
||||||
* @return true if valid, false if invalid
|
|
||||||
*/
|
|
||||||
public static boolean isValidName(String name) {
|
|
||||||
if (name == null) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
return name.length() > 3;
|
|
||||||
}
|
|
||||||
}
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
package org.gcube.portlets.user.rstudio_wrapper_portlet.shared;
|
||||||
|
|
||||||
|
public class RStudioInstance {
|
||||||
|
String context;
|
||||||
|
String hostedOn;
|
||||||
|
|
||||||
|
public RStudioInstance(String[] splits) {
|
||||||
|
this.context = splits[0];
|
||||||
|
this.hostedOn = splits[1];
|
||||||
|
}
|
||||||
|
|
||||||
|
public RStudioInstance(String context, String hostedOn) {
|
||||||
|
this.hostedOn = hostedOn;
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
public String getHostedOn() {
|
||||||
|
return hostedOn;
|
||||||
|
}
|
||||||
|
public void setHostedOn(String hostedOn) {
|
||||||
|
this.hostedOn = hostedOn;
|
||||||
|
}
|
||||||
|
public String getContext() {
|
||||||
|
return context;
|
||||||
|
}
|
||||||
|
public void setContext(String context) {
|
||||||
|
this.context = context;
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
Loading…
Reference in New Issue