Task #6946
git-svn-id: https://svn.research-infrastructures.eu/d4science/gcube/trunk/portlets/user/rstudio-wrapper-portlet@142482 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
87bb948416
commit
d8f07962f2
25
.classpath
25
.classpath
|
@ -1,18 +1,18 @@
|
||||||
<?xml version="1.0" encoding="UTF-8"?>
|
<?xml version="1.0" encoding="UTF-8"?>
|
||||||
<classpath>
|
<classpath>
|
||||||
<classpathentry kind="src" output="target/rstudio-wrapper-portlet-1.1.0-SNAPSHOT/WEB-INF/classes" path="src/main/java">
|
<classpathentry kind="src" output="target/rstudio-wrapper-portlet-1.3.0-SNAPSHOT/WEB-INF/classes" path="src/main/java">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="optional" value="true"/>
|
<attribute name="optional" value="true"/>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="src" output="target/rstudio-wrapper-portlet-1.1.0-SNAPSHOT/WEB-INF/classes" path="target/generated-sources/gwt">
|
<classpathentry kind="src" output="target/rstudio-wrapper-portlet-1.3.0-SNAPSHOT/WEB-INF/classes" path="target/generated-sources/gwt">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="optional" value="true"/>
|
<attribute name="optional" value="true"/>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry excluding="**" kind="src" output="target/rstudio-wrapper-portlet-1.1.0-SNAPSHOT/WEB-INF/classes" path="src/main/resources">
|
<classpathentry excluding="**" kind="src" output="target/rstudio-wrapper-portlet-1.3.0-SNAPSHOT/WEB-INF/classes" path="src/main/resources">
|
||||||
<attributes>
|
<attributes>
|
||||||
<attribute name="maven.pomderived" value="true"/>
|
<attribute name="maven.pomderived" value="true"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
|
@ -39,22 +39,5 @@
|
||||||
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
|
<attribute name="org.eclipse.jst.component.dependency" value="/WEB-INF/lib"/>
|
||||||
</attributes>
|
</attributes>
|
||||||
</classpathentry>
|
</classpathentry>
|
||||||
<classpathentry kind="lib" path="/Users/massi/portal/externals/GWT/gwt-2.7.0/gwt-user.jar">
|
<classpathentry kind="output" path="target/rstudio-wrapper-portlet-1.3.0-SNAPSHOT/WEB-INF/classes"/>
|
||||||
<attributes>
|
|
||||||
<attribute name="javadoc_location" value="file:/Users/massi/portal/externals/GWT/gwt-2.7.0/doc/javadoc/"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="lib" path="/Users/massi/portal/externals/GWT/gwt-2.7.0/gwt-codeserver.jar">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="javadoc_location" value="file:/Users/massi/portal/externals/GWT/gwt-2.7.0/doc/javadoc/"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="lib" path="/Users/massi/portal/externals/GWT/gwt-2.7.0/gwt-dev.jar">
|
|
||||||
<attributes>
|
|
||||||
<attribute name="javadoc_location" value="file:/Users/massi/portal/externals/GWT/gwt-2.7.0/doc/javadoc/"/>
|
|
||||||
</attributes>
|
|
||||||
</classpathentry>
|
|
||||||
<classpathentry kind="lib" path="/Users/massi/portal/externals/GWT/gwt-2.7.0/validation-api-1.0.0.GA-sources.jar"/>
|
|
||||||
<classpathentry kind="lib" path="/Users/massi/portal/externals/GWT/gwt-2.7.0/validation-api-1.0.0.GA.jar" sourcepath="/Users/massi/portal/externals/GWT/gwt-2.7.0/validation-api-1.0.0.GA-sources.jar"/>
|
|
||||||
<classpathentry kind="output" path="target/rstudio-wrapper-portlet-1.1.0-SNAPSHOT/WEB-INF/classes"/>
|
|
||||||
</classpath>
|
</classpath>
|
||||||
|
|
|
@ -3,4 +3,5 @@ encoding//src/main/java=UTF-8
|
||||||
encoding//src/main/resources=UTF-8
|
encoding//src/main/resources=UTF-8
|
||||||
encoding//src/test/java=UTF-8
|
encoding//src/test/java=UTF-8
|
||||||
encoding//src/test/resources=UTF-8
|
encoding//src/test/resources=UTF-8
|
||||||
|
encoding//target/generated-sources/gwt=UTF-8
|
||||||
encoding/<project>=UTF-8
|
encoding/<project>=UTF-8
|
||||||
|
|
12
pom.xml
12
pom.xml
|
@ -12,7 +12,7 @@
|
||||||
<groupId>org.gcube.portlets.user</groupId>
|
<groupId>org.gcube.portlets.user</groupId>
|
||||||
<artifactId>rstudio-wrapper-portlet</artifactId>
|
<artifactId>rstudio-wrapper-portlet</artifactId>
|
||||||
<packaging>war</packaging>
|
<packaging>war</packaging>
|
||||||
<version>1.2.0-SNAPSHOT</version>
|
<version>1.3.0-SNAPSHOT</version>
|
||||||
<name>RStudio Wrapper Portlet</name>
|
<name>RStudio Wrapper Portlet</name>
|
||||||
|
|
||||||
<properties>
|
<properties>
|
||||||
|
@ -61,14 +61,12 @@
|
||||||
<scope>provided</scope>
|
<scope>provided</scope>
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.applicationsupportlayer</groupId>
|
<groupId>org.gcube.common.portal</groupId>
|
||||||
<artifactId>aslcore</artifactId>
|
<artifactId>portal-manager</artifactId>
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.portal</groupId>
|
<groupId>org.gcube.dvos</groupId>
|
||||||
<artifactId>custom-portal-handler</artifactId>
|
<artifactId>usermanagement-core</artifactId>
|
||||||
<scope>provided</scope>
|
|
||||||
</dependency>
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>org.gcube.core</groupId>
|
<groupId>org.gcube.core</groupId>
|
||||||
|
|
|
@ -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.clientFor;
|
||||||
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
import static org.gcube.resources.discovery.icclient.ICFactory.queryFor;
|
||||||
|
|
||||||
|
import java.net.MalformedURLException;
|
||||||
|
import java.util.HashMap;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.gcube.application.framework.core.session.ASLSession;
|
import org.gcube.common.portal.PortalContext;
|
||||||
import org.gcube.application.framework.core.session.SessionManager;
|
import org.gcube.common.resources.gcore.GCoreEndpoint;
|
||||||
import org.gcube.common.resources.gcore.ServiceEndpoint;
|
import org.gcube.common.resources.gcore.GCoreEndpoint.Profile.Endpoint;
|
||||||
import org.gcube.common.scope.api.ScopeProvider;
|
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.portlets.user.rstudio_wrapper_portlet.client.RStudioService;
|
||||||
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.impl.LiferayUserManager;
|
||||||
|
import org.gcube.vomanagement.usermanagement.model.GCubeUser;
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -26,66 +30,111 @@ import com.google.gwt.user.server.rpc.RemoteServiceServlet;
|
||||||
public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioService {
|
public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioService {
|
||||||
|
|
||||||
private static final Logger _log = LoggerFactory.getLogger(RStudioServiceImpl.class);
|
private static final Logger _log = LoggerFactory.getLogger(RStudioServiceImpl.class);
|
||||||
private static final String SERVICE_EP_NAME = "RConnector";
|
private static final String SERVICE_NAME = "RConnector";
|
||||||
private static final String CATEGORY = "DataAnalysis";
|
private static final String SERVICECLASS = "DataAnalysis";
|
||||||
/**
|
private static final String RSTUDIO_URL = "RStudio-URL";
|
||||||
* the current ASLSession
|
private static final String RCONNECTOR_EntryName = "org.gcube.data.analysis.rconnector.RConnector";
|
||||||
* @return the session
|
private static final String PATH_TO_RCONNECTOR = "/r-connector/gcube/service/connect";
|
||||||
*/
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
/**
|
/**
|
||||||
* when packaging test will fail if the user is not set to test.user
|
* when packaging test will fail if the user is not set to test.user
|
||||||
* @return .
|
* @return .
|
||||||
*/
|
*/
|
||||||
public String getDevelopmentUser() {
|
public String getDevelopmentUser() {
|
||||||
String user = "test.user";
|
String user = "test.user";
|
||||||
// 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 = "";
|
||||||
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 {
|
try {
|
||||||
String scope = getASLSession().getScope();
|
|
||||||
_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<GCoreEndpoint> resources = getRStudioServiceEndpoints(scope);
|
||||||
if (resources.size() > 1) {
|
if (resources.size() == 0){
|
||||||
_log.error("Too many Service Endpoints having name " + SERVICE_EP_NAME +" in this scope: " + scope);
|
_log.warn("There is no gCORE Endpoint having name " + SERVICE_NAME +" and CLASS " + SERVICECLASS + " in this scope. Returning default instance");
|
||||||
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");
|
|
||||||
toReturn = rConnector().build().connect().toURL().toExternalForm();
|
toReturn = rConnector().build().connect().toURL().toExternalForm();
|
||||||
} else {
|
} else {
|
||||||
ServiceEndpoint res = resources.get(0);
|
UserManager um = new LiferayUserManager();
|
||||||
String hostedOn = res.profile().runtime().hostedOn();
|
_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(":");
|
String[] splits = hostedOn.split(":");
|
||||||
String host = splits[0];
|
|
||||||
int port = 80;
|
int port = 80;
|
||||||
try {
|
try {
|
||||||
port = Integer.parseInt(splits[1]);
|
port = Integer.parseInt(splits[1]);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
_log.warn("Could not find an integer after :, using default port 80");
|
_log.warn("Could not find an integer after :, using default port 80");
|
||||||
}
|
}
|
||||||
toReturn = rConnector().at(host, port).build().connect().toURL().toExternalForm();
|
//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;
|
||||||
}
|
}
|
||||||
|
|
||||||
} catch (Exception e) {
|
|
||||||
e.printStackTrace();
|
|
||||||
}
|
|
||||||
_log.debug("returning URL from rConnector = "+toReturn);
|
|
||||||
return toReturn;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,17 +142,16 @@ public class RStudioServiceImpl extends RemoteServiceServlet implements RStudioS
|
||||||
* @return the
|
* @return the
|
||||||
* @throws Exception
|
* @throws Exception
|
||||||
*/
|
*/
|
||||||
private List<ServiceEndpoint> getRStudioServiceEndpoints(String scope) throws Exception {
|
private List<GCoreEndpoint> getRStudioServiceEndpoints(String scope) throws Exception {
|
||||||
_log.debug("getRStudioServiceEndpoints on scope="+scope );
|
_log.debug("getRStudioServiceEndpoints on scope="+scope );
|
||||||
String currScope = ScopeProvider.instance.get();
|
String currScope = ScopeProvider.instance.get();
|
||||||
ScopeProvider.instance.set(scope);
|
ScopeProvider.instance.set(scope);
|
||||||
SimpleQuery query = queryFor(ServiceEndpoint.class);
|
SimpleQuery query = queryFor(GCoreEndpoint.class);
|
||||||
query.addCondition("$resource/Profile/Name/text() eq '"+ SERVICE_EP_NAME +"'");
|
query.addCondition("$resource/Profile/ServiceName/text() eq '"+ SERVICE_NAME +"'");
|
||||||
query.addCondition("$resource/Profile/Category/text() eq '"+ CATEGORY +"'");
|
query.addCondition("$resource/Profile/ServiceClass/text() eq '"+ SERVICECLASS +"'");
|
||||||
DiscoveryClient<ServiceEndpoint> client = clientFor(ServiceEndpoint.class);
|
DiscoveryClient<GCoreEndpoint> client = clientFor(GCoreEndpoint.class);
|
||||||
List<ServiceEndpoint> toReturn = client.submit(query);
|
List<GCoreEndpoint> toReturn = client.submit(query);
|
||||||
ScopeProvider.instance.set(currScope);
|
ScopeProvider.instance.set(currScope);
|
||||||
return toReturn;
|
return toReturn;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import javax.portlet.PortletRequestDispatcher;
|
||||||
import javax.portlet.RenderRequest;
|
import javax.portlet.RenderRequest;
|
||||||
import javax.portlet.RenderResponse;
|
import javax.portlet.RenderResponse;
|
||||||
|
|
||||||
import org.gcube.portal.custom.scopemanager.scopehelper.ScopeHelper;
|
|
||||||
import org.slf4j.Logger;
|
import org.slf4j.Logger;
|
||||||
import org.slf4j.LoggerFactory;
|
import org.slf4j.LoggerFactory;
|
||||||
|
|
||||||
|
@ -18,7 +17,6 @@ public class RProxyPortlet extends GenericPortlet {
|
||||||
private static final Logger _log = LoggerFactory.getLogger(RProxyPortlet.class);
|
private static final Logger _log = LoggerFactory.getLogger(RProxyPortlet.class);
|
||||||
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
|
public void doView(RenderRequest request, RenderResponse response) throws PortletException, IOException {
|
||||||
response.setContentType("text/html");
|
response.setContentType("text/html");
|
||||||
ScopeHelper.setContext(request);
|
|
||||||
_log.debug(" RProxyPortlet context set");
|
_log.debug(" RProxyPortlet context set");
|
||||||
PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/RStudio_view.jsp");
|
PortletRequestDispatcher dispatcher = getPortletContext().getRequestDispatcher("/WEB-INF/jsp/RStudio_view.jsp");
|
||||||
dispatcher.include(request, response);
|
dispatcher.include(request, response);
|
||||||
|
|
Loading…
Reference in New Issue