From d8f07962f2c3451e80bdf8c9fb52bbfa24cdbec7 Mon Sep 17 00:00:00 2001 From: Massimiliano Assante Date: Fri, 10 Feb 2017 18:17:36 +0000 Subject: [PATCH] Task #6946 git-svn-id: https://svn.research-infrastructures.eu/d4science/gcube/trunk/portlets/user/rstudio-wrapper-portlet@142482 82a268e6-3cf1-43bd-a215-b396298e98cf --- .classpath | 25 +-- .settings/org.eclipse.core.resources.prefs | 1 + pom.xml | 12 +- .../server/RStudioServiceImpl.java | 148 ++++++++++++------ .../server/portlet/RProxyPortlet.java | 2 - 5 files changed, 108 insertions(+), 80 deletions(-) diff --git a/.classpath b/.classpath index 09d95e2..22a687f 100644 --- a/.classpath +++ b/.classpath @@ -1,18 +1,18 @@ - + - + - + @@ -39,22 +39,5 @@ - - - - - - - - - - - - - - - - - - + diff --git a/.settings/org.eclipse.core.resources.prefs b/.settings/org.eclipse.core.resources.prefs index 29abf99..160c7b8 100644 --- a/.settings/org.eclipse.core.resources.prefs +++ b/.settings/org.eclipse.core.resources.prefs @@ -3,4 +3,5 @@ encoding//src/main/java=UTF-8 encoding//src/main/resources=UTF-8 encoding//src/test/java=UTF-8 encoding//src/test/resources=UTF-8 +encoding//target/generated-sources/gwt=UTF-8 encoding/=UTF-8 diff --git a/pom.xml b/pom.xml index ab58c94..a66ffca 100644 --- a/pom.xml +++ b/pom.xml @@ -12,7 +12,7 @@ org.gcube.portlets.user rstudio-wrapper-portlet war - 1.2.0-SNAPSHOT + 1.3.0-SNAPSHOT RStudio Wrapper Portlet @@ -61,14 +61,12 @@ provided - org.gcube.applicationsupportlayer - aslcore - provided + org.gcube.common.portal + portal-manager - org.gcube.portal - custom-portal-handler - provided + org.gcube.dvos + usermanagement-core org.gcube.core diff --git a/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/RStudioServiceImpl.java b/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/RStudioServiceImpl.java index 0e814f8..3ca940a 100644 --- a/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/RStudioServiceImpl.java +++ b/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/RStudioServiceImpl.java @@ -4,16 +4,20 @@ 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.application.framework.core.session.ASLSession; -import org.gcube.application.framework.core.session.SessionManager; -import org.gcube.common.resources.gcore.ServiceEndpoint; +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.portal.custom.scopemanager.scopehelper.ScopeHelper; 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; @@ -26,84 +30,128 @@ import com.google.gwt.user.server.rpc.RemoteServiceServlet; public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioService { private static final Logger _log = LoggerFactory.getLogger(RStudioServiceImpl.class); - private static final String SERVICE_EP_NAME = "RConnector"; - private static final String CATEGORY = "DataAnalysis"; - /** - * the current ASLSession - * @return the session - */ - private ASLSession getASLSession() { - String sessionID = this.getThreadLocalRequest().getSession().getId(); - String user = (String) this.getThreadLocalRequest().getSession().getAttribute(ScopeHelper.USERNAME_ATTRIBUTE); - if (user == null) { - _log.warn("USER IS NULL setting testing user and Running OUTSIDE PORTAL"); - user = getDevelopmentUser(); - } - return SessionManager.getInstance().getASLSession(sessionID, user); - } + 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"; + // user = "costantino.perciante"; return user; } @Override public String retrieveRStudioSecureURL() throws IllegalArgumentException { String toReturn = ""; - String token = getASLSession().getSecurityToken(); + 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 { - String scope = getASLSession().getScope(); + _log.debug("calling rConnector with scope = " + scope + " and token = "+token ); - List resources = getRStudioServiceEndpoints(scope); - if (resources.size() > 1) { - _log.error("Too many Service Endpoints having name " + SERVICE_EP_NAME +" in this scope: " + scope); - throw new TooManyRStudioResourcesException("There exist more than 1 Runtime Resource in this scope having name " - + SERVICE_EP_NAME + " and Category " + CATEGORY + ". Only one allowed per scope."); - } - else if (resources.size() == 0){ - _log.warn("There is no Service Endpoint having name " + SERVICE_EP_NAME +" and Category " + CATEGORY + " in this scope. Returning default instance"); + List 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 { - ServiceEndpoint res = resources.get(0); - String hostedOn = res.profile().runtime().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"); + 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 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 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); } - toReturn = rConnector().at(host, port).build().connect().toURL().toExternalForm(); - } - + } catch (Exception e) { e.printStackTrace(); } - _log.debug("returning URL from rConnector = "+toReturn); + _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 getRStudioServiceEndpoints(String scope) throws Exception { + private List getRStudioServiceEndpoints(String scope) throws Exception { _log.debug("getRStudioServiceEndpoints on scope="+scope ); String currScope = ScopeProvider.instance.get(); ScopeProvider.instance.set(scope); - SimpleQuery query = queryFor(ServiceEndpoint.class); - query.addCondition("$resource/Profile/Name/text() eq '"+ SERVICE_EP_NAME +"'"); - query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'"); - DiscoveryClient client = clientFor(ServiceEndpoint.class); - List toReturn = client.submit(query); + SimpleQuery query = queryFor(GCoreEndpoint.class); + query.addCondition("$resource/Profile/ServiceName/text() eq '"+ SERVICE_NAME +"'"); + query.addCondition("$resource/Profile/ServiceClass/text() eq '"+ SERVICECLASS +"'"); + DiscoveryClient client = clientFor(GCoreEndpoint.class); + List toReturn = client.submit(query); ScopeProvider.instance.set(currScope); return toReturn; } - } diff --git a/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/portlet/RProxyPortlet.java b/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/portlet/RProxyPortlet.java index 29b338c..a12c51e 100644 --- a/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/portlet/RProxyPortlet.java +++ b/src/main/java/org/gcube/portlets/user/rstudio_wrapper_portlet/server/portlet/RProxyPortlet.java @@ -10,7 +10,6 @@ import javax.portlet.PortletRequestDispatcher; import javax.portlet.RenderRequest; import javax.portlet.RenderResponse; -import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -18,7 +17,6 @@ public class RProxyPortlet extends GenericPortlet { private static final Logger _log = LoggerFactory.getLogger(RProxyPortlet.class); public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException { response.setContentType("text/html"); - ScopeHelper.setContext(request); _log.debug(" RProxyPortlet context set"); PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/RStudio_view.jsp"); dispatcher.include(request, response);