rstudio-wrapper-portlet/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/RStudioServiceImpl.java

158 lines
7.0 KiB
Java

package org.gcube.portlets.user.rstudio_wrapper_portlet.server;
import static org.gcube.data.analysis.rconnector.client.Constants.rConnector;
import static org.gcube.resources.discovery.icclient.ICFactory.clientFor;
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
import java.net.MalformedURLException;
import java.util.HashMap;
import java.util.List;
import org.gcube.common.portal.PortalContext;
import org.gcube.common.resources.gcore.GCoreEndpoint;
import org.gcube.common.resources.gcore.GCoreEndpoint.Profile.Endpoint;
import org.gcube.common.scope.api.ScopeProvider;
import org.gcube.portlets.user.rstudio_wrapper_portlet.client.RStudioService;
import org.gcube.resources.discovery.client.api.DiscoveryClient;
import org.gcube.resources.discovery.client.queries.api.SimpleQuery;
import org.gcube.vomanagement.usermanagement.UserManager;
import org.gcube.vomanagement.usermanagement.impl.LiferayUserManager;
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.google.gwt.user.server.rpc.RemoteServiceServlet;
/**
* The server side implementation of the RPC service.
*/
@SuppressWarnings("serial")
public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioService {
private static final Logger _log = LoggerFactory.getLogger(RStudioServiceImpl.class);
private static final String SERVICE_NAME = "RConnector";
private static final String SERVICECLASS = "DataAnalysis";
private static final String RSTUDIO_URL = "RStudio-URL";
private static final String RCONNECTOR_EntryName = "org.gcube.data.analysis.rconnector.RConnector";
private static final String PATH_TO_RCONNECTOR = "/r-connector/gcube/service/connect";
/**
* when packaging test will fail if the user is not set to test.user
* @return .
*/
public String getDevelopmentUser() {
String user = "test.user";
// user = "costantino.perciante";
return user;
}
@Override
public String retrieveRStudioSecureURL() throws IllegalArgumentException {
String toReturn = "";
PortalContext pContext = PortalContext.getConfiguration();
GCubeUser curUser = pContext.getCurrentUser(getThreadLocalRequest());
long userId = curUser.getUserId();
String scope = pContext.getCurrentScope(getThreadLocalRequest());
String token = pContext.getCurrentUserToken(scope, userId);
try {
_log.debug("calling rConnector with scope = " + scope + " and token = "+token );
List<GCoreEndpoint> resources = getRStudioServiceEndpoints(scope);
if (resources.size() == 0){
_log.warn("There is no gCORE Endpoint having name " + SERVICE_NAME +" and CLASS " + SERVICECLASS + " in this scope. Returning default instance");
toReturn = rConnector().build().connect().toURL().toExternalForm();
} else {
UserManager um = new LiferayUserManager();
_log.debug("Checking if user " + curUser.getFullname() + " has already an RStudio Instance set ... ");
//chec RStudio
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("**** The instance set for user " + curUser.getFullname() + " is " + hostedOn);
toReturn = getRConnectorURL(hostedOn, token);
_log.debug("User " + curUser.getFullname() + " has RStudio Instance set, returning rConnector URL " + toReturn);
}
else {//need to find the RStudio
_log.debug("User " + curUser.getFullname() + "DOES NOT HAVE RStudio Instance set, calculating allocation ... ");
HashMap<String, Integer> rStudioDistributionMap = new HashMap<>();
for (GCoreEndpoint res : resources) {
Endpoint ep = res.profile().endpointMap().get(RCONNECTOR_EntryName);
String hostedOn = ep.uri().getHost()+":"+ep.uri().getPort();
rStudioDistributionMap.put(hostedOn, 0);
}
List<GCubeUser> vreUsers = um.listUsersByGroup(pContext.getCurrentGroupId(getThreadLocalRequest()), false);
_log.debug("VRE " + scope + " has totalUsers = " + vreUsers.size());
for (GCubeUser gCubeUser : vreUsers) {
if (um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_URL) != null && um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_URL).toString().compareTo("") != 0) {
String hostedOn = (String) um.readCustomAttr(gCubeUser.getUserId(), RSTUDIO_URL);
if (rStudioDistributionMap.containsKey(hostedOn)) {
int noToSet = rStudioDistributionMap.get(hostedOn)+1;
rStudioDistributionMap.put(hostedOn, noToSet);
_log.debug("rStudioDistributionMap for = " + hostedOn + " -> " + noToSet);
}
}
}
_log.debug("VRE - RStudio allocaiton map as follows: ");
int min = 0;
int i = 0;
String host2Select = "";
for (String host : rStudioDistributionMap.keySet()) {
_log.debug("Host " + host + " has # users=" + rStudioDistributionMap.get(host));
if (i==0) {
host2Select = host;
min = rStudioDistributionMap.get(host);
} else {
int usersNo = rStudioDistributionMap.get(host);
if (usersNo < min) {
_log.debug("Host " + host + " has LESS users than " + host2Select + " updating");
host2Select = host;
}
}
i++;
}
um.saveCustomAttr(userId, RSTUDIO_URL, host2Select);
_log.debug("User " + curUser.getFullname() + " RStudio Instance set calculated = " + host2Select);
toReturn = getRConnectorURL(host2Select, token);
_log.debug("User " + curUser.getFullname() + " has RStudio Instance set, returning rConnector URL " + toReturn);
}
}
} catch (Exception e) {
e.printStackTrace();
}
_log.info("returning URL from rConnector = "+toReturn);
return toReturn;
}
private String getRConnectorURL(String hostedOn, String token) throws MalformedURLException, IllegalArgumentException {
String[] splits = hostedOn.split(":");
int port = 80;
try {
port = Integer.parseInt(splits[1]);
} catch (Exception e) {
_log.warn("Could not find an integer after :, using default port 80");
}
//http://rstudio-dev.d4science.org:80/r-connector/gcube/service/connect?gcube-token=6fa92d94-6568-4510-8443-a1c5ecdf1c7d-98187548s
if (port == 443 || port == 8443)
return "https://"+hostedOn+PATH_TO_RCONNECTOR+"?gcube-token="+token;
else {
return "http://"+hostedOn+PATH_TO_RCONNECTOR+"?gcube-token="+token;
}
}
/**
*
* @return the
* @throws Exception
*/
private List<GCoreEndpoint> getRStudioServiceEndpoints(String scope) throws Exception {
_log.debug("getRStudioServiceEndpoints on scope="+scope );
String currScope = ScopeProvider.instance.get();
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;
}
}