Service mavenization completed
git-svn-id: http://svn.research-infrastructures.eu/public/d4science/gcube/trunk/vre-management/ResourceManager@55388 82a268e6-3cf1-43bd-a215-b396298e98cf
This commit is contained in:
parent
a4cf8edb60
commit
1b406bfc6f
|
@ -1,9 +1,6 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="test"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.launching.JRE_CONTAINER"/>
|
||||
<classpathentry kind="con" path="org.eclipse.jdt.USER_LIBRARY/GCORELIBS"/>
|
||||
<classpathentry combineaccessrules="false" kind="src" path="/gcf.TRUNK"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/RMDeps/org.gcube.vremanagement.resourcemanager.stubs.jar"/>
|
||||
<classpathentry kind="lib" path="/Dependencies/RMDeps/softwaregateway-stubs-1.0.0-SNAPSHOT.jar"/>
|
||||
|
|
11
INSTALL
11
INSTALL
|
@ -1,11 +0,0 @@
|
|||
|
||||
to compile:
|
||||
ant garService
|
||||
ant buildStubs
|
||||
|
||||
to deploy:
|
||||
gcore-deploy-service org.gcube.vremanagement.resourcemanager.gar
|
||||
cp org.gcube.vremanagement.resourcemanager.stubs.jar
|
||||
|
||||
|
||||
|
|
@ -0,0 +1,9 @@
|
|||
package = org.gcube.vremanagement.resourcemanager
|
||||
lib.dir = Dependencies/ResourceManager
|
||||
wsdl.1 = ResourceManager
|
||||
package.1 = resourcemanager
|
||||
package.2 = common
|
||||
namespace.1=http://gcube-system.org/namespaces/vremanagement/resourcemanager
|
||||
namespace.2=http://gcube-system.org/common/vremanagement/types
|
||||
|
||||
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<jndiConfig xmlns="http://wsrf.globus.org/jndi/config">
|
||||
|
||||
<service name="gcube/vremanagement/ResourceManager/service">
|
||||
<environment
|
||||
name="configDir"
|
||||
value="@config.dir@"
|
||||
type="java.lang.String"
|
||||
override="false" />
|
||||
|
||||
<environment
|
||||
name="resourceBrokerClass"
|
||||
value="org.gcube.vremanagement.resourcemanager.impl.brokerage.ServiceBroker"
|
||||
type="java.lang.String"
|
||||
override="false" />
|
||||
<!--
|
||||
<environment
|
||||
name="startScopes"
|
||||
value=""
|
||||
type="java.lang.String"
|
||||
override="false" /> -->
|
||||
|
||||
</service>
|
||||
|
||||
<service name="gcube/vremanagement/ResourceManager">
|
||||
|
||||
<environment
|
||||
name="name"
|
||||
value="ResourceManager"
|
||||
type="java.lang.String"
|
||||
override="false" />
|
||||
|
||||
|
||||
<resource name="home" type="org.gcube.vremanagement.resourcemanager.impl.state.ResourceManagerHome">
|
||||
<resourceParams>
|
||||
<parameter>
|
||||
<name>factory</name>
|
||||
<value>org.globus.wsrf.jndi.BeanFactory</value>
|
||||
</parameter>
|
||||
<parameter>
|
||||
<name>resourceClass</name>
|
||||
<value>org.gcube.vremanagement.resourcemanager.impl.state.InstanceState</value>
|
||||
</parameter>
|
||||
</resourceParams>
|
||||
|
||||
</resource>
|
||||
|
||||
</service>
|
||||
|
||||
</jndiConfig>
|
|
@ -0,0 +1,17 @@
|
|||
<deployment name="defaultServerConfig"
|
||||
xmlns="http://xml.apache.org/axis/wsdd/"
|
||||
xmlns:java="http://xml.apache.org/axis/wsdd/providers/java"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
<service name="gcube/vremanagement/ResourceManager" provider="Handler" use="literal" style="document">
|
||||
<parameter name="className" value="org.gcube.vremanagement.resourcemanager.impl.ResourceManager"/>
|
||||
<wsdlFile>share/schema/org.gcube.vremanagement.resourcemanager/ResourceManager_service.wsdl</wsdlFile>
|
||||
<parameter name="allowedMethods" value="*"/>
|
||||
<parameter name="handlerClass" value="org.globus.axis.providers.RPCProvider"/>
|
||||
<parameter name="scope" value="Application"/>
|
||||
<parameter name="providers" value="GCUBEProvider GetCurrentMessageProvider"/>
|
||||
<parameter name="loadOnStartup" value="true"/>
|
||||
<parameter name="securityDescriptor" value="@config.dir@/security_descriptor.xml"/>
|
||||
</service>
|
||||
|
||||
</deployment>
|
|
@ -0,0 +1,50 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<Resource>
|
||||
<ID/>
|
||||
<Type>Service</Type>
|
||||
<Profile>
|
||||
<Description>ResourceManager creates and manages a VRE context</Description>
|
||||
<Class>VREManagement</Class>
|
||||
<Name>ResourceManager</Name>
|
||||
<Version>1.0.0</Version>
|
||||
<Packages>
|
||||
<Main deployable="true">
|
||||
<Description>ResourceManager creates and manages Scopes within a gCube infrastructure</Description>
|
||||
<Name>ResourceManager-service</Name>
|
||||
<Version>1.2.0-SNAPSHOT</Version>
|
||||
<Mandatory level="VRE"/>
|
||||
<Shareable level="NONE"/>
|
||||
<GHNRequirements/>
|
||||
<GARArchive>org.gcube.vremanagement.resourcemanager.gar</GARArchive>
|
||||
<PortType>
|
||||
<Name>gcube/vremanagement/ResourceManager</Name>
|
||||
<Security/>
|
||||
<WSDL/>
|
||||
</PortType>
|
||||
</Main>
|
||||
<Software>
|
||||
<Description>Stubs for ResourceManager: provide facilities to interact with a ResourceManager instance</Description>
|
||||
<Name>ResourceManager-stubs</Name>
|
||||
<Version>1.2.0-SNAPSHOT</Version>
|
||||
<MultiVersion value="true"/>
|
||||
<Mandatory level="GHN"/>
|
||||
<Shareable level="VO"/>
|
||||
<Type>library</Type>
|
||||
<Files>
|
||||
<File>org.gcube.vremanagement.resourcemanager.stubs.jar</File>
|
||||
</Files>
|
||||
</Software>
|
||||
<Software>
|
||||
<Description>Test-suite for ResourceManager: provide sample usages of interaction with a ResourceManager instance</Description>
|
||||
<Name>ResourceManager-test-suite</Name>
|
||||
<Version>1.2.0-SNAPSHOT</Version>
|
||||
<MultiVersion value="true"/>
|
||||
<Shareable level="VO"/>
|
||||
<Type>application</Type>
|
||||
<Files>
|
||||
<File>lib/org.gcube.vremanagement.resourcemanager.testsuite.jar</File>
|
||||
</Files>
|
||||
</Software>
|
||||
</Packages>
|
||||
</Profile>
|
||||
</Resource>
|
|
@ -0,0 +1 @@
|
|||
This folder contains the resource reports.
|
|
@ -0,0 +1,65 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<securityConfig xmlns="http://www.globus.org" >
|
||||
<authz value="none"/>
|
||||
|
||||
<method name="addResources">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="sendReport">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="setScopeOptions">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="getReport">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="removeResources">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="notifyGHNdeath">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="queryResourceProperties">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="subscribe">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="getCurrentMessage">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
<method name="getMultipleResourceProperties">
|
||||
<auth-method>
|
||||
<none/>
|
||||
</auth-method>
|
||||
</method>
|
||||
|
||||
</securityConfig>
|
|
@ -0,0 +1,3 @@
|
|||
|
||||
|
||||
|
|
@ -0,0 +1,70 @@
|
|||
<assembly
|
||||
xmlns="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2"
|
||||
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/plugins/maven-assembly-plugin/assembly/1.1.2 http://maven.apache.org/xsd/assembly-1.1.2.xsd">
|
||||
<id>servicearchive</id>
|
||||
<formats>
|
||||
<format>tar.gz</format>
|
||||
</formats>
|
||||
<baseDirectory>/</baseDirectory>
|
||||
<fileSets>
|
||||
<fileSet>
|
||||
<directory>${distroDirectory}</directory>
|
||||
<outputDirectory>/</outputDirectory>
|
||||
<useDefaultExcludes>true</useDefaultExcludes>
|
||||
<includes>
|
||||
<include>README</include>
|
||||
<include>LICENSE</include>
|
||||
<include>INSTALL</include>
|
||||
<include>MAINTAINERS</include>
|
||||
<include>changelog.xml</include>
|
||||
</includes>
|
||||
<fileMode>755</fileMode>
|
||||
<filtered>true</filtered>
|
||||
</fileSet>
|
||||
</fileSets>
|
||||
<dependencySets>
|
||||
<dependencySet>
|
||||
<includes>
|
||||
<include>*:resource-manager-stubs</include>
|
||||
</includes>
|
||||
<useProjectArtifact>false</useProjectArtifact>
|
||||
<useTransitiveDependencies>false</useTransitiveDependencies>
|
||||
<outputDirectory>resource-manager-stubs</outputDirectory>
|
||||
</dependencySet>
|
||||
<dependencySet>
|
||||
<includes>
|
||||
<include>*:resource-manager-test-suite</include>
|
||||
</includes>
|
||||
<useProjectArtifact>false</useProjectArtifact>
|
||||
<useTransitiveDependencies>false</useTransitiveDependencies>
|
||||
<outputDirectory>resource-manager-test-suite</outputDirectory>
|
||||
</dependencySet>
|
||||
</dependencySets>
|
||||
<files>
|
||||
<file>
|
||||
<source>${configDirectory}/profile.xml</source>
|
||||
<outputDirectory></outputDirectory>
|
||||
<filtered>true</filtered>
|
||||
</file>
|
||||
<file>
|
||||
<source>target/${build.finalName}.gar</source>
|
||||
<outputDirectory>${project.artifactId}</outputDirectory>
|
||||
</file>
|
||||
<file>
|
||||
<source>${distroDirectory}/svnpath.txt</source>
|
||||
<outputDirectory>${project.artifactId}</outputDirectory>
|
||||
<filtered>true</filtered>
|
||||
</file>
|
||||
<file>
|
||||
<source>${distroDirectory}/svnpath.txt</source>
|
||||
<outputDirectory>resource-manager-stubs</outputDirectory>
|
||||
<filtered>true</filtered>
|
||||
</file>
|
||||
<file>
|
||||
<source>${distroDirectory}/svnpath.txt</source>
|
||||
<outputDirectory>resource-manager-test-suite</outputDirectory>
|
||||
<filtered>true</filtered>
|
||||
</file>
|
||||
</files>
|
||||
</assembly>
|
|
@ -0,0 +1 @@
|
|||
${scm.url}
|
|
@ -0,0 +1,77 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<artifactId>maven-parent</artifactId>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<version>1.0.0</version>
|
||||
<relativePath />
|
||||
</parent>
|
||||
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>resource-manager</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<packaging>pom</packaging>
|
||||
|
||||
<name>Resource Manager Reactor</name>
|
||||
|
||||
<modules>
|
||||
<!-- The repository module must be first in order to ensure
|
||||
that the local repository is populated -->
|
||||
<module>resource-manager-stubs</module>
|
||||
<module>resource-manager-service</module>
|
||||
<module>resource-manager-test-suite</module>
|
||||
</modules>
|
||||
|
||||
<properties>
|
||||
<wsdlDirectory>${project.basedir}/../wsdl</wsdlDirectory>
|
||||
<wsdlOutputDirectory>${project.basedir}/../target/generated-sources/wsdl</wsdlOutputDirectory>
|
||||
<configDirectory>${project.basedir}/../config</configDirectory>
|
||||
<distroDirectory>${project.basedir}/../distro</distroDirectory>
|
||||
<namespace>http://gcube-system.org/namespaces/vremanagement/resourcemanager</namespace>
|
||||
<basepackage>org.gcube.vremanagement.resourcemanager</basepackage>
|
||||
</properties>
|
||||
|
||||
<dependencyManagement>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>gcf</artifactId>
|
||||
<version>[1.4.0-SNAPSHOT,1.5.0-SNAPSHOT)</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
</dependencyManagement>
|
||||
|
||||
<build>
|
||||
|
||||
<!-- defines basic configuration for the service plugin -->
|
||||
<pluginManagement>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<artifactId>maven-service-plugin</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<configuration>
|
||||
<serviceId>deployer</serviceId>
|
||||
<basePackage>${basepackage}</basePackage>
|
||||
<wsdlDirectory>${wsdlDirectory}</wsdlDirectory>
|
||||
<wsdlOutputDirectory>${wsdlOutputDirectory}</wsdlOutputDirectory>
|
||||
<configurationDirectory>${configDirectory}</configurationDirectory>
|
||||
</configuration>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</pluginManagement>
|
||||
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,209 @@
|
|||
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
<parent>
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>resource-manager</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
<relativePath>..</relativePath>
|
||||
</parent>
|
||||
|
||||
<artifactId>resource-manager-service</artifactId>
|
||||
<name>Resource Manager Service</name>
|
||||
<description>A service for managing subsets of gCube resources in a given scope</description>
|
||||
|
||||
<scm>
|
||||
<connection>scm:svn:http://svn.d4science.research-infrastructures.eu/gcube/trunk/vre-management/ResourceManager</connection>
|
||||
<developerConnection>scm:svn:https://svn.d4science.research-infrastructures.eu/gcube/trunk/vre-management/ResourceManager</developerConnection>
|
||||
<url>http://svn.d4science.research-infrastructures.eu/gcube/trunk/vre-management/ResourceManager</url>
|
||||
</scm>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- reactor dependencies -->
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>gcf</artifactId>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>resource-manager-stubs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>softwaregateway-stubs</artifactId>
|
||||
<version>[1.0.0-SNAPSHOT,1.1.0-SNAPSHOT)</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.vremanagement</groupId>
|
||||
<artifactId>ghnmanager-stubs</artifactId>
|
||||
<version>[1.5.0-SNAPSHOT,1.6.0-SNAPSHOT)</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.thoughtworks.xstream</groupId>
|
||||
<artifactId>xstream</artifactId>
|
||||
<version>1.3.1</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.vremanagement</groupId>
|
||||
<artifactId>resourcebroker-serialization</artifactId>
|
||||
<version>[1.2.0-SNAPSHOT,1.3.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.vremanagement</groupId>
|
||||
<artifactId>resourcebroker-stubs</artifactId>
|
||||
<version>[1.2.0-SNAPSHOT,1.3.0-SNAPSHOT)</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>deployer-stubs</artifactId>
|
||||
<version>[2.3.0-SNAPSHOT,2.4.0-SNAPSHOT)</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<!-- test dependencies -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<artifactId>my-container</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
|
||||
<profiles>
|
||||
<profile>
|
||||
<id>local-deploy</id>
|
||||
<build>
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<artifactId>maven-service-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<phase>package</phase>
|
||||
<goals>
|
||||
<goal>local-deploy</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
</build>
|
||||
</profile>
|
||||
|
||||
</profiles>
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<!-- builds Gar at install time -->
|
||||
<plugin>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<artifactId>maven-service-plugin</artifactId>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>make-gar</id>
|
||||
<goals>
|
||||
<goal>gar-gen</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- downloads my-container when needed -->
|
||||
<plugin>
|
||||
<artifactId>maven-dependency-plugin</artifactId>
|
||||
<version>2.3</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>install-my-container</id>
|
||||
<phase>generate-test-resources</phase>
|
||||
<configuration>
|
||||
<artifactItems>
|
||||
<artifactItem>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<artifactId>my-container</artifactId>
|
||||
<version>1.0.0</version>
|
||||
<type>tar.gz</type>
|
||||
<classifier>distro</classifier>
|
||||
<overWrite>false</overWrite>
|
||||
<outputDirectory>${project.basedir}</outputDirectory>
|
||||
</artifactItem>
|
||||
</artifactItems>
|
||||
<markersDirectory>${project.basedir}</markersDirectory>
|
||||
</configuration>
|
||||
<goals>
|
||||
<goal>unpack</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- generates service archive -->
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-assembly-plugin</artifactId>
|
||||
<version>2.2</version>
|
||||
<configuration>
|
||||
<descriptors>
|
||||
<descriptor>${distroDirectory}/descriptor.xml</descriptor>
|
||||
</descriptors>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>servicearchive</id>
|
||||
<phase>install</phase>
|
||||
<goals>
|
||||
<goal>single</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<!-- the following is to allow test-suite sources to access protected methods -->
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-source</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>${basedir}/src/main/java</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
</project>
|
|
@ -0,0 +1,327 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.axis.components.uuid.UUIDGenFactory;
|
||||
import org.gcube.common.core.contexts.GCUBEServiceContext;
|
||||
import org.gcube.common.core.faults.GCUBEFault;
|
||||
import org.gcube.common.core.porttypes.GCUBEPortType;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.scope.GCUBEScopeNotSupportedException;
|
||||
import org.gcube.common.core.scope.GCUBEScope.MalformedScopeExpressionException;
|
||||
import org.gcube.common.core.scope.GCUBEScopeManager.IllegalScopeException;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.StatefulPortTypeContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.DeployerReport;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNodeManager;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.DeployerReport.DeployedRunningInstance;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.AddResourcesParameters;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.CreateScopeParameters;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.DisposeScopeParameters;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.InvalidOptionsFaultType;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.InvalidScopeFaultType;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.NoSuchReportFaultType;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.OptionsParameters;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.RemoveResourcesParameters;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ResourcesCreationFaultType;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ResourcesRemovalFaultType;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ScopeOption;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.SendReportParameters;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.operators.AddResourcesOperator;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.operators.DisposeScopeOperator;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.operators.OperatorConfig;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.operators.RemoveResourcesOperator;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.PublishedScopeResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.InstanceState;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.PublishedScopeResource.UnknownScopeOptionException;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session.OPERATION;
|
||||
import org.globus.wsrf.NoSuchResourceException;
|
||||
import org.globus.wsrf.ResourceException;
|
||||
|
||||
|
||||
/**
|
||||
* <em>ResourceManager</em> port-type implementation
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class ResourceManager extends GCUBEPortType {
|
||||
|
||||
/** Singleton resource name*/
|
||||
public static final String SINGLETON_RESOURCE_KEY = "VREManagerState";
|
||||
|
||||
/**
|
||||
* Object logger.
|
||||
*/
|
||||
protected final GCUBELog logger = new GCUBELog(this, ServiceContext.getContext());
|
||||
|
||||
@Override
|
||||
protected GCUBEServiceContext getServiceContext() {
|
||||
return ServiceContext.getContext();
|
||||
}
|
||||
/**
|
||||
* Adds a new group of {@link ScopedResource}s to the managed Scope
|
||||
*
|
||||
* @param resourcesList the resources to join
|
||||
* @return the ID assigned to the operation, it can be used to retrieve the resource session by invoking the {@link ResourceManager#getReport(String)} operation
|
||||
* @throws GCUBEFault if the operation fails
|
||||
*/
|
||||
public synchronized String addResources(AddResourcesParameters resourceList) throws ResourcesCreationFaultType, GCUBEFault {
|
||||
logger.debug("AddResources operation invoked in scope " + ServiceContext.getContext().getScope().getName());
|
||||
try {
|
||||
//checks the input scope
|
||||
GCUBEScope targetScope = this.validateOperationScope(resourceList.getTargetScope());
|
||||
Session report = new Session(UUIDGenFactory.getUUIDGen().nextUUID(),OPERATION.AddResources, targetScope);
|
||||
this.getResource().addSession(report);
|
||||
new AddResourcesOperator(new OperatorConfig(report, this.getResource().getResourceList(), targetScope),resourceList).run();
|
||||
//resource.publish();
|
||||
//returns the session ID, it can be used to invoke the getReport operation
|
||||
return report.getId();
|
||||
} catch (IllegalScopeException ise){
|
||||
logger.error("The target scope (" + resourceList.getTargetScope() + ") is not valid or null or not joined to this instance", ise);
|
||||
throw ServiceContext.getContext().getDefaultException("The target scope (" + resourceList.getTargetScope() + ") is not valid or null or not joined to this instance", ise).toFault();
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to manage the input given resources(s) within the scope: " + e.getMessage(), e);
|
||||
throw ServiceContext.getContext().getDefaultException("Unable to manage the input given resources(s) within the scope: " + e.getMessage(), e).toFault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a group of {@link ScopedResource}s from the managed Scope
|
||||
*
|
||||
* @param resourcesList the resources to remove from the PublishedScopeResource
|
||||
* @throws GCUBEFault if the operation fails
|
||||
*/
|
||||
public synchronized String removeResources(RemoveResourcesParameters resourceList) throws ResourcesRemovalFaultType, InvalidScopeFaultType {
|
||||
|
||||
try {
|
||||
GCUBEScope targetScope = this.validateOperationScope(resourceList.getTargetScope());
|
||||
Session report = new Session(UUIDGenFactory.getUUIDGen().nextUUID(), OPERATION.RemoveResources, targetScope);
|
||||
this.getResource().addSession(report);
|
||||
new RemoveResourcesOperator(new OperatorConfig(report, this.getResource().getResourceList(), targetScope),resourceList).run();
|
||||
return report.getId();
|
||||
} catch (IllegalScopeException ise){
|
||||
logger.error("The target scope (" + resourceList.getTargetScope() + ") is not valid or null or not joined to this instance", ise);
|
||||
throw new InvalidScopeFaultType();
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to manage the input given resources(s) within the scope: " + e.getMessage(), e);
|
||||
//throw ServiceContext.getContext().getDefaultException("Unable to manage the input given resources(s) within the scope: " + e.getMessage(), e).toFault();
|
||||
throw new ResourcesRemovalFaultType();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the managed Scope
|
||||
* @param params
|
||||
* @return
|
||||
* @throws GCUBEFault
|
||||
*/
|
||||
public synchronized String disposeScope(DisposeScopeParameters params) throws InvalidScopeFaultType, GCUBEFault {
|
||||
logger.info("Dispose Scope invoked... the entire scope is going to be thrown away!!");
|
||||
try {
|
||||
GCUBEScope.getScope(params.getName()).getServiceMap();
|
||||
} catch (MalformedScopeExpressionException e) {
|
||||
logger.error("Invalid scope expression " + params.getName());
|
||||
throw new InvalidScopeFaultType();
|
||||
} catch (GCUBEScopeNotSupportedException e) {
|
||||
logger.error("Scope not supported " + params.getName());
|
||||
throw new InvalidScopeFaultType();
|
||||
}
|
||||
try {
|
||||
Session report = new Session(UUIDGenFactory.getUUIDGen().nextUUID(), OPERATION.Dispose,GCUBEScope.getScope(params.getName()));
|
||||
this.getResource().addSession(report);
|
||||
new DisposeScopeOperator(new OperatorConfig(report, this.getResource().getResourceList(), GCUBEScope.getScope(params.getName()))).run();
|
||||
this.getResource().getPublishedScopeResource().dismiss();
|
||||
return report.getId();
|
||||
} catch (NoSuchResourceException e) {
|
||||
logger.error("No resource found for this scope", e);
|
||||
throw ServiceContext.getContext().getDefaultException("No resource found for this scope", e).toFault();
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to dispose the scope: " + e.getMessage(), e);
|
||||
throw ServiceContext.getContext().getDefaultException("Unable to dispose the scope: " + e.getMessage(), e).toFault();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
public synchronized String createScope(CreateScopeParameters params)
|
||||
throws InvalidScopeFaultType, InvalidOptionsFaultType, ResourcesCreationFaultType, GCUBEFault {
|
||||
String name = params.getName();
|
||||
logger.info("Creating the new Scope " + name);
|
||||
try {
|
||||
GCUBEScope.getScope(name).getServiceMap();
|
||||
} catch (MalformedScopeExpressionException e) {
|
||||
throw new InvalidScopeFaultType();
|
||||
} catch (GCUBEScopeNotSupportedException e) {
|
||||
//the service map for this scope does not exist
|
||||
params.getServiceMap();
|
||||
}
|
||||
//String map = params.getServiceMap();
|
||||
this.changeScopeOptions(params.getOptionsParameters());
|
||||
return this.addResources(params.getAddResourcesParameters());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes some options on the scope
|
||||
*
|
||||
* @param options the new options to change
|
||||
* @throws GCUBEFault if any of the input options is not valid
|
||||
*/
|
||||
public void changeScopeOptions(OptionsParameters options) throws InvalidOptionsFaultType, InvalidOptionsFaultType, GCUBEFault {
|
||||
PublishedScopeResource scoperesource = null;
|
||||
try {
|
||||
scoperesource = this.getResource().getPublishedScopeResource();
|
||||
} catch (NoSuchResourceException e) {
|
||||
logger.error("No resource found for this scope", e);
|
||||
throw ServiceContext.getContext().getDefaultException("No resource found for this scope", e).toFault();
|
||||
} catch (Exception e) {
|
||||
logger.error("Change Scope Options fault: ", e);
|
||||
throw ServiceContext.getContext().getDefaultException("Change Scope Options fault: ", e).toFault();
|
||||
}
|
||||
//add the new options
|
||||
for (ScopeOption option : options.getScopeOptionList()) {
|
||||
if (option == null) continue;
|
||||
logger.trace("ScopeOption received: " + option.getName() +"="+ option.getValue());
|
||||
try {
|
||||
scoperesource.setOption(option.getName().trim(), option.getValue().trim());
|
||||
} catch (UnknownScopeOptionException e) {
|
||||
logger.warn("Unknown option: " + option.getName());
|
||||
throw new InvalidOptionsFaultType();
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to read option: " + option.getName());
|
||||
throw new InvalidOptionsFaultType();
|
||||
}
|
||||
}
|
||||
//and publish the scope resource
|
||||
try {
|
||||
scoperesource.publish();
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to publish the ScopeResouce", e);
|
||||
throw ServiceContext.getContext().getDefaultException("Unable to publish the ScopeResouce", e).toFault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives a deployment session. It is called by the Deployer services on the GHNs contacted within the {@link #addResources(AddResourcesParameters)}
|
||||
* operation
|
||||
*
|
||||
* @param session the resource session
|
||||
* @throws GCUBEFault if the session does not have a valid serialization
|
||||
*/
|
||||
public void sendReport(SendReportParameters reportMessage) throws GCUBEFault {
|
||||
logger.info("Received session for session " + reportMessage.getCallbackID());
|
||||
logger.trace("Report content: \n" + reportMessage.getReport());
|
||||
try {
|
||||
Session session = this.getResource().getSession(reportMessage.getCallbackID());
|
||||
DeployerReport dreport = new DeployerReport(reportMessage.getReport());
|
||||
session.addGHNReport(dreport);
|
||||
session.save();
|
||||
PublishedScopeResource resource = this.getResource().getPublishedScopeResource();
|
||||
logger.debug("Status session is: " + dreport.getStatus());
|
||||
if (dreport.getStatus().compareToIgnoreCase("CLOSED") == 0) {
|
||||
logger.trace("Setting the gHN " + dreport.getGHNID() + " as non working");
|
||||
//if the session is closed, declare the node as "non working" node
|
||||
VirtualNodeManager.getNode(dreport.getGHNID(), this.getResource().getManagedScope()).isNotWorking();
|
||||
logger.trace("Parsing running instances (if any)...");
|
||||
Set<ScopedResource> resources = new HashSet<ScopedResource>();
|
||||
for (DeployedRunningInstance instance : dreport.getInstances()) {
|
||||
if (instance.isAlive()) {
|
||||
logger.trace("Adding instance " + instance.getRIID() + " to PublishedScopeResource");
|
||||
resource.addResource(instance.getInstance());
|
||||
resources.add((ScopedResource)instance.getInstance());
|
||||
} else {
|
||||
logger.warn("Instance " + instance.getRIID() + " not found on the IS");
|
||||
}
|
||||
}
|
||||
session.addDeployedInstances(dreport.getInstances());
|
||||
//add the newly generated RIs to the Scope State
|
||||
this.getResource().getResourceList().addResources(resources);
|
||||
}
|
||||
resource.publish();
|
||||
session.save();
|
||||
// //send feedback to the broker if needed
|
||||
// if ((session.isReportClosed()
|
||||
// && ((session.getOperation()==OPERATION.AddResources)
|
||||
// || (session.getOperation()==OPERATION.UpdateResources)
|
||||
// || (session.getOperation()==OPERATION.Create)))) {
|
||||
// this.updateBroker(session);
|
||||
// }
|
||||
|
||||
} catch (NoSuchResourceException e) {
|
||||
logger.error("Unable to find ResourceManager resource", e);
|
||||
throw ServiceContext.getContext().getDefaultException("Unable to find ResourceManager resource", e).toFault();
|
||||
} catch (ResourceException e) {
|
||||
logger.error("Unable to find ResourceManager resource", e);
|
||||
throw ServiceContext.getContext().getDefaultException("Unable to find ResourceManager resource", e).toFault();
|
||||
} catch (Exception e) {
|
||||
throw ServiceContext.getContext().getDefaultException("Unable to parse or save the Deployer Report", e).toFault();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a Resource Report
|
||||
*
|
||||
* @param ID the session identifier
|
||||
* @return the string serialization of the session
|
||||
* @throws GNoSuchReportFaultTypeCUBEFault if the session is not found or does not have a valid serialization
|
||||
*/
|
||||
public String getReport(String ID) throws NoSuchReportFaultType {
|
||||
try {
|
||||
return this.getResource().getSession(ID).toXML();
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to retrieve the Resource Report for ID " + ID,e);
|
||||
throw new NoSuchReportFaultType();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Sends the feedback on the deployment activity to the Broker
|
||||
// * @param services the Resource Report
|
||||
// * @param reports
|
||||
// */
|
||||
// private void updateBroker(Session session) {
|
||||
// if (session.getServices().size()>0) {
|
||||
// try {
|
||||
// logger.info("Sending feedback to the Broker");
|
||||
// BrokerConnector.getBroker(this.getResource().getManagedScope()).sendFeedback(session);
|
||||
// } catch (Exception e) {
|
||||
// logger.error("Can't send feedback to the Broker", e);
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
/**
|
||||
* Validates the input scope of each PublishedScopeResource operation
|
||||
*
|
||||
* @param inScope the scope to check
|
||||
* @return the accepted scope
|
||||
* @throws IllegalScopeException if the given scope has not been accepted
|
||||
*/
|
||||
|
||||
private GCUBEScope validateOperationScope(String inScope) throws IllegalScopeException {
|
||||
if ((inScope == null) || (inScope.compareToIgnoreCase("") == 0))
|
||||
return ServiceContext.getContext().getScope(); // use the instance scope as default
|
||||
else if (GCUBEScope.getScope(inScope.trim()).isEnclosedIn(ServiceContext.getContext().getScope()))
|
||||
return GCUBEScope.getScope(inScope.trim());
|
||||
else
|
||||
throw new IllegalScopeException();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the singleton resource
|
||||
*
|
||||
* @return the {@link InstanceState}
|
||||
* @throws NoSuchResourceException
|
||||
* @throws ResourceException
|
||||
*/
|
||||
private InstanceState getResource() throws NoSuchResourceException, ResourceException{
|
||||
return (InstanceState) StatefulPortTypeContext.getContext().getWSHome().find(StatefulPortTypeContext.getContext().makeKey(SINGLETON_RESOURCE_KEY));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,43 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage;
|
||||
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
* Models the expected behavior of a Broker.
|
||||
* A Broker is an entity that can create Deployment Plans for a set of {@link ScopedDeployedService}s to be deployed
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public interface Broker {
|
||||
|
||||
/**
|
||||
* Initializes the Broker instance
|
||||
* @param scope the scope where the broker will act
|
||||
* @throws Exception if the initialization fails (depends on the broker's nature)
|
||||
*/
|
||||
public void initialize(GCUBEScope scope) throws Exception;
|
||||
|
||||
/**
|
||||
* Creates a deployment plan for the given services
|
||||
* @param session the current session
|
||||
* @param services the services to deploy
|
||||
* @param suggestedGHNs the (eventually) GHNs suggested for the deployment, if specified, only these nodes will be used by the planner
|
||||
* @throws Exception if the preparation of the plan fails
|
||||
*/
|
||||
public void makePlan(Session session, Set<ScopedDeployedService> services, String[] suggestedGHNs) throws Exception;
|
||||
|
||||
/**
|
||||
* Sends feedback to the broker about the execution of the plan for the given session
|
||||
* @param session the current session
|
||||
* @throws Exception if the broker is not able to manage the feedback
|
||||
*/
|
||||
public void sendFeedback(Session session) throws Exception;
|
||||
|
||||
}
|
|
@ -0,0 +1,60 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage;
|
||||
|
||||
import java.lang.reflect.Constructor;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
|
||||
/**
|
||||
* Locates and initializes the Broker to use for services' deployment. A Broker is a component capable to create a plan
|
||||
* for allocating gCube packages to gHNs
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class BrokerConnector {
|
||||
|
||||
private static final String DEFAULT_BROKER = "org.gcube.vremanagement.resourcemanager.impl.brokerage.InternalBroker";
|
||||
|
||||
private static final GCUBELog logger = new GCUBELog(BrokerConnector.class);
|
||||
|
||||
/**
|
||||
* Returns the broker to use in the given scope
|
||||
* @param scope
|
||||
* @return
|
||||
* @throws Exception
|
||||
*/
|
||||
public static Broker getBroker(GCUBEScope scope) throws Exception {
|
||||
Broker broker = null;
|
||||
try {
|
||||
broker = load((String) ServiceContext.getContext().getProperty("resourceBrokerClass", true));
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to load the configured broker", e);
|
||||
try {
|
||||
logger.info("Trying to load the internal broker");
|
||||
broker = load(DEFAULT_BROKER);
|
||||
} catch (Exception e1) {
|
||||
logger.error("Unable to load the internal broker", e1);
|
||||
throw new Exception("unable to find a broker to use");
|
||||
}
|
||||
}
|
||||
if (broker != null) broker.initialize(scope);
|
||||
return broker;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads a broker instance
|
||||
* @param className the full name of the Class implementing the broker to load
|
||||
* @return the broker instance
|
||||
* @throws Exception
|
||||
*/
|
||||
private static Broker load(String className) throws Exception {
|
||||
if (className==null) return null;
|
||||
Class<?> clazz = (Class<?>) Class.forName(className);
|
||||
if (!Broker.class.isAssignableFrom(clazz))
|
||||
throw new Exception(className+" does not implement "+Broker.class.getName());
|
||||
Constructor<?> constructor = clazz.getConstructor(new Class[] {});
|
||||
return (Broker) constructor.newInstance(new Object[]{});
|
||||
}
|
||||
}
|
|
@ -0,0 +1,96 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Arrays;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.axis.types.URI.MalformedURIException;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNodeManager;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode.NoGHNFoundException;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STATUS;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
* Trivial default Broker that assigns the target gHNs to services with a round robin policy
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class InternalBroker implements Broker {
|
||||
|
||||
private final GCUBELog logger=new GCUBELog(this);
|
||||
|
||||
private GCUBEScope scope;
|
||||
|
||||
private String[] suggestedGHNs = new String[0];
|
||||
|
||||
//used to apply a round robin assignment of the input GHNs (if any)
|
||||
private int nodewalker = 0;
|
||||
|
||||
public InternalBroker() {}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initialize(GCUBEScope scope) throws Exception {this.scope = scope;}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void makePlan(Session session, Set<ScopedDeployedService> services, String[] suggestedGHNs) throws Exception {
|
||||
this.suggestedGHNs = suggestedGHNs;
|
||||
for (ScopedDeployedService service : services) {
|
||||
try {
|
||||
this.assignTargetGHN(service);
|
||||
} catch (NoGHNFoundException e1) {
|
||||
logger.error(service.getSourceService() + "Unable to find a suitable target gHN");
|
||||
service.setStatus(STATUS.LOST);
|
||||
service.setErrorMessage("Unable to find a suitable target gHN");
|
||||
throw new IOException(service.getSourceService() + " - unable to find a suitable target gHN for this service");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Selects a target node for the deployment
|
||||
*
|
||||
* @param service the service to deploy
|
||||
* @throws MalformedURIException
|
||||
* @throws NoGHNFoundException if the gHN is not found
|
||||
*/
|
||||
private void assignTargetGHN(ScopedDeployedService service) throws org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode.NoGHNFoundException {
|
||||
if ( (service.getSourceService().getGHN() != null) && (service.getSourceService().getGHN().compareToIgnoreCase("") != 0)) {
|
||||
//a specific GHN has been requested
|
||||
logger.info("A specific GHN (" + service.getSourceService().getGHN() + ") has been requested by the caller for " + service);
|
||||
VirtualNode node = VirtualNodeManager.getNode(service.getSourceService().getGHN(),this.scope);
|
||||
node.setWorkingScope(this.scope);
|
||||
node.isNotWorking();
|
||||
service.setTargetGHN(node);
|
||||
} else if (this.suggestedGHNs.length > 0) {
|
||||
//a set of target GHNs has been requested, assign one of them with a round robin
|
||||
logger.info("A set of target GHNs " + Arrays.toString(this.suggestedGHNs)+" has been requested by the caller for " + service);
|
||||
VirtualNode node = VirtualNodeManager.getNode(this.suggestedGHNs[this.nodewalker++ % this.suggestedGHNs.length],this.scope);
|
||||
node.setWorkingScope(this.scope);
|
||||
node.isNotWorking();
|
||||
service.setTargetGHN(node);
|
||||
} else {
|
||||
logger.info("no GHN has been specified as explicit target");
|
||||
//no GHN has been specified as explicit target
|
||||
throw new NoGHNFoundException("No GHN was assigned to the service from the caller");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void sendFeedback(Session session) throws Exception {
|
||||
/* feedback is not managed by this broker*/
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.axis.message.addressing.EndpointReferenceType;
|
||||
import org.gcube.common.core.contexts.GCUBERemotePortTypeContext;
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.informationsystem.client.AtomicCondition;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBERIQuery;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcebroker.stubs.ResourceBrokerPortType;
|
||||
import org.gcube.vremanagement.resourcebroker.stubs.service.ResourceBrokerServiceAddressingLocator;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker.Feedback;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker.PlanParser;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker.PlanRequest;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
* Broker that exploits the gCube Resource Broker service
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class ServiceBroker implements Broker {
|
||||
|
||||
protected final GCUBELog logger = new GCUBELog(this);
|
||||
|
||||
private GCUBEScope scope;
|
||||
|
||||
private List<GCUBERunningInstance> instances = null;
|
||||
|
||||
private static final int TIMEOUT = 600000; //in milliseconds
|
||||
|
||||
public ServiceBroker() {}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void initialize(GCUBEScope scope) throws Exception {
|
||||
this.scope = scope;
|
||||
logger.info("Initializing the ServiceBroker..");
|
||||
this.instances = this.queryForBrokerInstances();
|
||||
if (this.instances.size() == 0)
|
||||
throw new Exception("unable to find an instance of the Resource Broker in scope");
|
||||
logger.info("Broker instances found: #" + this.instances.size());
|
||||
}
|
||||
|
||||
public void makePlan(Session session, Set<ScopedDeployedService> services, String[] suggestedGHNs) throws Exception {
|
||||
String request = PlanRequest.create(services, suggestedGHNs, scope);;
|
||||
logger.debug("Request for the Broker \n" + request);
|
||||
String plan = null;
|
||||
for (GCUBERunningInstance instance : this.instances) {
|
||||
EndpointReferenceType endpoint = instance.getAccessPoint().getEndpoint("gcube/vremanagement/ResourceBroker");
|
||||
logger.debug("Querying broker instance at " + endpoint.getAddress());
|
||||
try {
|
||||
plan = this.getBrokerPT(endpoint).getPlan(request);
|
||||
logger.debug("Plan received from the broker \n" + plan);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to contact the Resource Broker instance located at " + endpoint.getAddress(), e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
PlanParser.parse(plan, services, scope);
|
||||
session.setDeploymentPlan(plan);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void sendFeedback(Session session) throws Exception {
|
||||
String feedback = Feedback.create(session);
|
||||
logger.debug("Feedback for the Broker \n" + feedback);
|
||||
for (GCUBERunningInstance instance : this.instances) {
|
||||
EndpointReferenceType endpoint = instance.getAccessPoint().getEndpoint("gcube/vremanagement/ResourceBroker");
|
||||
logger.debug("Sending broker feeback to " + endpoint.getAddress());
|
||||
try {
|
||||
this.getBrokerPT(endpoint).handleFeedback(feedback);
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to contact the Resource Broker instance located at " + endpoint.getAddress(), e);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks for all the Resource Broker instances in Scope
|
||||
* @return the list of RIs found
|
||||
* @throws Exception if the query to the IS fails
|
||||
*/
|
||||
private List<GCUBERunningInstance> queryForBrokerInstances() throws Exception {
|
||||
//looks for all the Broker instances
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
GCUBERIQuery lookupQuery = client.getQuery(GCUBERIQuery.class);
|
||||
lookupQuery.addAtomicConditions(new AtomicCondition("//ServiceName","ResourceBroker"));
|
||||
lookupQuery.addAtomicConditions(new AtomicCondition("//ServiceClass","VREManagement"));
|
||||
return client.execute(lookupQuery, this.scope);
|
||||
|
||||
}
|
||||
|
||||
private ResourceBrokerPortType getBrokerPT(EndpointReferenceType endpoint) throws Exception {
|
||||
ResourceBrokerPortType pt = new ResourceBrokerServiceAddressingLocator().getResourceBrokerPortTypePort(endpoint);
|
||||
pt = GCUBERemotePortTypeContext.getProxy(pt, this.scope, TIMEOUT, ServiceContext.getContext());
|
||||
return pt;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,63 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.parser.xstream.XStreamTransformer;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.types.PackageGroup;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.types.PlanResponse;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.types.feedback.DeployNode;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.types.feedback.FeedbackStatus;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session;
|
||||
|
||||
/**
|
||||
*
|
||||
* Feedback for deployment plans. It uses the serialization API provided by the Broker Service
|
||||
* to create the feedback information.
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class Feedback {
|
||||
|
||||
/**
|
||||
* Creates the feedback information for the Broker Service
|
||||
* @param session the current session
|
||||
* @return the XML representation of the feedback information
|
||||
*/
|
||||
@SuppressWarnings("deprecation")
|
||||
public static String create(Session session) throws IOException {
|
||||
Set<ScopedDeployedService> services = session.getServices();
|
||||
XStreamTransformer transformer = new XStreamTransformer();
|
||||
PlanResponse resp = transformer.getResponseFromXML(session.getDeploymentPlan(), false);
|
||||
org.gcube.vremanagement.resourcebroker.utils.serialization.types.feedback.Feedback fb =
|
||||
new org.gcube.vremanagement.resourcebroker.utils.serialization.types.feedback.Feedback();
|
||||
fb.setPlanID(resp.getKey());
|
||||
fb.setScope(resp.getScope());
|
||||
for (PackageGroup group : resp.getPackageGroups()) {
|
||||
ScopedDeployedService service = null;
|
||||
for (ScopedDeployedService s : services) {
|
||||
if (s.getId().compareToIgnoreCase(group.getServiceName()) == 0) {
|
||||
service = s;
|
||||
break;
|
||||
}
|
||||
}
|
||||
//set the status of each package elemnt
|
||||
for (org.gcube.vremanagement.resourcebroker.utils.serialization.types.PackageElem p : group.getPackages()) {
|
||||
if (service == null)
|
||||
p.setStatus(FeedbackStatus.FAILED);
|
||||
else if (service.isSuccess())
|
||||
p.setStatus(FeedbackStatus.SUCCESS);
|
||||
else //this has to be improved by using the PARTIAL state?
|
||||
p.setStatus(FeedbackStatus.FAILED);
|
||||
}
|
||||
|
||||
DeployNode pgToAdd = new DeployNode(group);
|
||||
fb.addDeployNode(pgToAdd);
|
||||
}
|
||||
return transformer.toXML(fb);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,71 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.parser.xstream.XStreamTransformer;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.types.PackageGroup;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.types.PlanResponse;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNodeManager;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode.NoGHNFoundException;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
|
||||
/**
|
||||
*
|
||||
* Parser for deployment plans. It uses the Serialization API provided by the Broker Service
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class PlanParser {
|
||||
|
||||
private static final GCUBELog logger = new GCUBELog(PlanParser.class);
|
||||
|
||||
|
||||
/**
|
||||
* Parses the current plan and assigns gHNs to services
|
||||
* @param plan the plan returned by the Broker
|
||||
* @param services the services to deploy
|
||||
* @param scope the current scope
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void parse(String plan, Set<ScopedDeployedService> services, GCUBEScope scope) throws IOException {
|
||||
XStreamTransformer transformer = new XStreamTransformer();
|
||||
PlanResponse resp = transformer.getResponseFromXML(plan, false);
|
||||
if (resp.getStatus().getStatus().compareToIgnoreCase("FAILED")==0) {
|
||||
logger.error("The creation of the Deployment Plan failed. Broker says: " + resp.getStatus().getMsg());
|
||||
throw new IOException ("Broker says: " + resp.getStatus().getMsg());
|
||||
} else if (resp.getStatus().getStatus().compareToIgnoreCase("SUCCESS")==0) {
|
||||
logger.info("The creation of the Deployment Plan was successful");
|
||||
}
|
||||
//assing ghns to services
|
||||
for (PackageGroup group: resp.getPackageGroups()) {
|
||||
String serviceID = group.getServiceName();
|
||||
String ghnID = group.getGHN();
|
||||
if (ghnID == null) {
|
||||
logger.error("no gHN was assigned to service " + serviceID);
|
||||
throw new IOException("no gHN was assigned to service " + serviceID);
|
||||
}
|
||||
for (ScopedDeployedService service : services) {
|
||||
if (service.getId().compareToIgnoreCase(serviceID) == 0) {
|
||||
logger.info("Assigning gHN " + ghnID + " to " +service);
|
||||
VirtualNode node = null;
|
||||
try {
|
||||
node = VirtualNodeManager.getNode(ghnID,scope);
|
||||
} catch (NoGHNFoundException e) {
|
||||
logger.error("unable to find gHN " + ghnID + " returned by the Broker");
|
||||
throw new IOException("unable to find gHN " + ghnID + " returned by the Broker");
|
||||
}
|
||||
node.setWorkingScope(scope);
|
||||
node.isNotWorking();
|
||||
service.setTargetGHN(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Dependency;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.parser.xstream.XStreamTransformer;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.types.PackageElem;
|
||||
import org.gcube.vremanagement.resourcebroker.utils.serialization.types.PackageGroup;
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates a plan request with the Serialization API provided by the Broker Service
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class PlanRequest {
|
||||
|
||||
/**
|
||||
* Creates the request plan for the Broker Service
|
||||
* @param services the services to deploy
|
||||
* @param suggestedGHNs the GHNs suggested for the deployment
|
||||
* @param scope the scope of the request
|
||||
* @thrown {@link IOException} if the request cannot be created
|
||||
* @return the XML representation of the request
|
||||
*
|
||||
*/
|
||||
public static String create(Set<ScopedDeployedService> services, String[] suggestedGHNs, GCUBEScope scope) throws IOException {
|
||||
org.gcube.vremanagement.resourcebroker.utils.serialization.types.PlanRequest planReq = new org.gcube.vremanagement.resourcebroker.utils.serialization.types.PlanRequest(scope.toString());
|
||||
|
||||
for (ScopedDeployedService service : services) {
|
||||
PackageGroup group = planReq.createPackageGroup( service.getId());
|
||||
for (Dependency dep : service.getLastResolvedDependencies()) {
|
||||
group.addPackage(new PackageElem(false, dep.getService().getClazz(), dep.getService().getName(),
|
||||
dep.getService().getVersion(), dep.getName(), dep.getVersion()));
|
||||
if (service.getSourceService().getGHN() != null)
|
||||
group.setGHN(service.getSourceService().getGHN());
|
||||
}
|
||||
}
|
||||
if (suggestedGHNs != null) {
|
||||
for (String ghn : suggestedGHNs)
|
||||
planReq.getGHNList().addGHN(ghn);
|
||||
}
|
||||
XStreamTransformer transformer = new XStreamTransformer();
|
||||
return transformer.toXML(planReq);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,80 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker.kxml;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.DeployerReport;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session;
|
||||
import org.kxml2.io.KXmlParser;
|
||||
import org.kxml2.io.KXmlSerializer;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Feedback for deployment plans. It uses the KXML library to create the feedback information.
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class KFeedback {
|
||||
|
||||
protected static final GCUBELog logger = new GCUBELog(KFeedback.class);
|
||||
|
||||
/**
|
||||
* Creates the feedback information for the Broker Service
|
||||
* @param session the current session
|
||||
* @return the XML representation of the feedback information
|
||||
* @throws IOException if the feedback information cannot be created
|
||||
*/
|
||||
public static String create(Session session) throws IOException {
|
||||
|
||||
Map<String, DeployerReport> reports = session.getAllGHNReports();
|
||||
Set<ScopedDeployedService> services = session.getServices();
|
||||
KXmlParser parser = new KXmlParser();
|
||||
try {
|
||||
parser.setInput(new BufferedReader(new StringReader(session.getDeploymentPlan())));
|
||||
} catch (XmlPullParserException e) {
|
||||
logger.error("Unable to parse the Deployment Plan", e);
|
||||
throw new IOException ("Unable to parse the Deployment Plan");
|
||||
}
|
||||
StringWriter feedbackRequest = new StringWriter();
|
||||
KXmlSerializer serializer = new KXmlSerializer();
|
||||
serializer.setOutput(feedbackRequest);
|
||||
serializer.startDocument("UTF-8", true);
|
||||
serializer.setPrefix("", "http://gcube-system.org/namespaces/resourcebroker/broker/xsd/deployFeedback");
|
||||
serializer.startTag(null,"KFeedback").attribute(null, "planID", getPlanID(parser));;
|
||||
serializer.startTag(null,"Scope").text(session.getScope().toString()).endTag(null,"Scope");
|
||||
for (String ghnid : reports.keySet()) {
|
||||
serializer.startTag(null,"DeployNode");
|
||||
//TODO: to complete
|
||||
serializer.startTag(null,"GHN").text(ghnid).endTag(null, "GHN");
|
||||
serializer.endTag(null,"DeployNode");
|
||||
}
|
||||
serializer.endTag(null,"KFeedback");
|
||||
return feedbackRequest.toString();
|
||||
}
|
||||
|
||||
private static String getPlanID(KXmlParser parser) throws IOException {
|
||||
String id = "";
|
||||
loop: while (true) {
|
||||
try {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("PlanResponse")) id = parser.getAttributeValue(null, "deployID");
|
||||
break loop;
|
||||
case KXmlParser.END_DOCUMENT: break loop;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to parse the Deployment Plan", e);
|
||||
throw new IOException ("The creation of the Deployment Plan failed. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
return id;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,117 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker.kxml;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNodeManager;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode.NoGHNFoundException;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.kxml2.io.KXmlParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Parser for deployment plans. It uses the KXML library to parse the plan.
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class KPlanParser {
|
||||
|
||||
private static final GCUBELog logger = new GCUBELog(KPlanParser.class);
|
||||
|
||||
/**
|
||||
* Parses the current plan and assigns gHNs to services
|
||||
* @param plan the plan returned by the Broker
|
||||
* @param services the services to deploy
|
||||
* @param scope the current scope
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void parse(String plan, Set<ScopedDeployedService> services, GCUBEScope scope) throws IOException {
|
||||
KXmlParser parser = new KXmlParser();
|
||||
try {
|
||||
parser.setInput(new BufferedReader(new StringReader(plan)));
|
||||
} catch (XmlPullParserException e) {
|
||||
logger.error("Unable to parse the Deployment Plan", e);
|
||||
throw new IOException ("Unable to parse the Deployment Plan");
|
||||
}
|
||||
loop: while (true) {
|
||||
try {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("Status")) parseStatus(parser);
|
||||
else if (parser.getName().equals("PackageGroup")) parsePackageGroup(services, parser, scope);
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: break loop;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to parse the Deployment Plan", e);
|
||||
throw new IOException ("The creation of the Deployment Plan failed. " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void parseStatus(KXmlParser parser) throws IOException {
|
||||
String value = parser.getAttributeValue(null, "value");
|
||||
String errorMsg = "";
|
||||
if (value.compareToIgnoreCase("FAILED")==0) {
|
||||
loop: while (true) {
|
||||
try {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("ErrorMsg")) errorMsg = parser.nextText();
|
||||
break;
|
||||
case KXmlParser.END_TAG: if (parser.getName().equals("Status")) break loop;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to parse the Deployment Plan at Status element", e);
|
||||
throw new IOException ("Failed to parse at Status element");
|
||||
}
|
||||
}
|
||||
logger.error("The creation of the Deployment Plan failed. Broker says: " + errorMsg);
|
||||
throw new IOException ("Broker says: " + errorMsg);
|
||||
} else if (value.compareToIgnoreCase("SUCCESS")==0) {
|
||||
logger.info("The creation of the Deployment Plan was successful");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private static void parsePackageGroup(Set<ScopedDeployedService> services, KXmlParser parser, GCUBEScope scope) throws IOException, NoGHNFoundException {
|
||||
String serviceID = parser.getAttributeValue(null, "service");
|
||||
String ghnID = null;
|
||||
loop: while (true) {
|
||||
try {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("GHN")) ghnID = parser.nextText();
|
||||
break;
|
||||
case KXmlParser.END_TAG: if (parser.getName().equals("PackageGroup")) break loop;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to parse the Deployment Plan at PackageGroup element", e);
|
||||
throw new IOException ("Failed to parse at PackageGroup element");
|
||||
}
|
||||
}
|
||||
if (ghnID == null) {
|
||||
logger.error("a gHN was not assigned to service " + serviceID);
|
||||
throw new NoGHNFoundException("a gHN was not assigned to service " + serviceID);
|
||||
}
|
||||
for (ScopedDeployedService service : services) {
|
||||
if (service.getId().compareToIgnoreCase(serviceID) == 0) {
|
||||
logger.info("Assigning gHN " + ghnID + " to " +service);
|
||||
VirtualNode node = VirtualNodeManager.getNode(ghnID,scope);
|
||||
node.setWorkingScope(scope);
|
||||
service.setTargetGHN(node);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,110 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker.kxml;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.StringWriter;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Dependency;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.kxml2.io.KXmlSerializer;
|
||||
|
||||
/**
|
||||
*
|
||||
* Creates a plan request with the KXML library to create the deployment plan request.
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class KPlanRequest {
|
||||
|
||||
/**
|
||||
* Creates the request plan for the Broker Service
|
||||
*
|
||||
* @param services
|
||||
* the services to deploy
|
||||
* @param suggestedGHNs
|
||||
* the GHNs suggested for the deployment
|
||||
* @param scope
|
||||
* the scope of the request
|
||||
* @thrown {@link IOException} if the request cannot be created
|
||||
* @return the XML representation of the request
|
||||
*
|
||||
*/
|
||||
public static String create(Set<ScopedDeployedService> services,
|
||||
String[] suggestedGHNs, GCUBEScope scope) throws IOException {
|
||||
StringWriter request = new StringWriter();
|
||||
KXmlSerializer serializer = new KXmlSerializer();
|
||||
serializer.setOutput(request);
|
||||
serializer.startDocument("UTF-8", true);
|
||||
serializer.setPrefix("","http://gcube-system.org/namespaces/resourcebroker/broker/xsd/deployRequest");
|
||||
serializer.startTag(null, "PlanRequest");
|
||||
serializer.startTag(null, "Scope").text(scope.toString()).endTag(null,"Scope");
|
||||
// for each service, prepare a section like this:
|
||||
// <PackageGroup service="service1">
|
||||
// <Package reuse="true">
|
||||
// <ServiceClass>PkgServiceClass</ServiceClass>
|
||||
// <ServiceName>PkgServiceName</ServiceName>
|
||||
// <ServiceVersion>PkgServiceVersion</ServiceVersion>
|
||||
// <PackageName>PkgPackageName</PackageName>
|
||||
// <PackageVersion>PkgPackageVersion</PackageVersion>
|
||||
// </Package>
|
||||
// <Package reuse="true">
|
||||
// <ServiceClass>PkgServiceClass2</ServiceClass>
|
||||
// <ServiceName>PkgServiceName2</ServiceName>
|
||||
// <ServiceVersion>PkgServiceVersion2</ServiceVersion>
|
||||
// <PackageName>PkgPackageName2</PackageName>
|
||||
// <PackageVersion>PkgPackageVersion2</PackageVersion>
|
||||
// </Package>
|
||||
// <GHN>d5a5af20-ac50-11de-a928-ab32081f9f00</GHN>
|
||||
// </PackageGroup>
|
||||
for (ScopedDeployedService service : services) {
|
||||
serializer.startTag(null, "PackageGroup").attribute(null,
|
||||
"service", service.getId());
|
||||
for (Dependency dep : service.getLastResolvedDependencies()) {
|
||||
serializer.startTag(null, "Package").attribute(null, "reuse",
|
||||
"false");
|
||||
serializer.startTag(null, "ServiceClass").text(
|
||||
dep.getService().getClazz()).endTag(null,
|
||||
"ServiceClass");
|
||||
serializer.startTag(null, "ServiceName").text(
|
||||
dep.getService().getName()).endTag(null, "ServiceName");
|
||||
serializer.startTag(null, "ServiceVersion").text(
|
||||
dep.getService().getVersion()).endTag(null,
|
||||
"ServiceVersion");
|
||||
serializer.startTag(null, "PackageName").text(dep.getName())
|
||||
.endTag(null, "PackageName");
|
||||
serializer.startTag(null, "PackageVersion").text(
|
||||
dep.getVersion()).endTag(null, "PackageVersion");
|
||||
serializer.endTag(null, "Package");
|
||||
}
|
||||
if (service.getSourceService().getGHN() != null)
|
||||
serializer.startTag(null, "GHN").text(service.getSourceService().getGHN()).endTag(null, "GHN");
|
||||
serializer.endTag(null, "PackageGroup");
|
||||
}
|
||||
|
||||
// GHNLIST
|
||||
if (suggestedGHNs != null) {
|
||||
serializer.startTag(null, "GHNList");
|
||||
for (String ghn : suggestedGHNs)
|
||||
serializer.startTag(null, "GHN").text(ghn).endTag(null, "GHN");
|
||||
serializer.endTag(null, "GHNList");
|
||||
}
|
||||
|
||||
serializer.endTag(null, "PlanRequest");
|
||||
|
||||
return request.toString();
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
try {
|
||||
System.out.println(create(new HashSet<ScopedDeployedService>(),
|
||||
new String[] { "ID" }, GCUBEScope.getScope("/gcube")));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,116 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.contexts;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import org.gcube.common.core.contexts.GCUBEServiceContext;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.handlers.GCUBEHandler;
|
||||
import org.gcube.common.core.utils.handlers.GCUBEScheduledHandler;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.ResourceManager;
|
||||
|
||||
|
||||
/**
|
||||
* ResourceManager service context implementation
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class ServiceContext extends GCUBEServiceContext {
|
||||
|
||||
static ServiceContext cache = new ServiceContext();
|
||||
|
||||
|
||||
/**
|
||||
* Gets the current service context
|
||||
* @return the service context
|
||||
*/
|
||||
public static ServiceContext getContext() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
@Override protected String getJNDIName() {
|
||||
return "gcube/vremanagement/ResourceManager/service";
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected void onReady() throws Exception {
|
||||
super.onReady();
|
||||
// no more than one scope is allowed!
|
||||
if (ServiceContext.getContext().getInstance().getScopes().values().size() != 1) {
|
||||
logger.fatal("ResourceManager is misconfigured, cannot start the service in multiple scopes");
|
||||
throw new IllegalServiceScopeException("ResourceManager has been configured to join more than one scope, while it can work only in ONE single scope");
|
||||
}
|
||||
//creates the stateful resource for the service with a short delay
|
||||
HStateScheduler stateScheduler = new HStateScheduler(10, GCUBEScheduledHandler.Mode.LAZY);
|
||||
stateScheduler.setScheduled(new HState());
|
||||
stateScheduler.run();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates/updates the Deployer stateful resource
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
protected class HStateScheduler extends GCUBEScheduledHandler {
|
||||
|
||||
public HStateScheduler(long interval, Mode mode) {
|
||||
super(interval, mode);
|
||||
}
|
||||
@Override
|
||||
protected boolean repeat(Exception exception, int exceptionCount) {
|
||||
if (exception!=null) {
|
||||
logger.warn("Failed to create the vre manager resource (attempt "+exceptionCount+" out of 20)",exception);
|
||||
if (exceptionCount >= 20) {
|
||||
logger.error("Max attempts reached, no more chance to register the ResourceManager resource, the service startup failed");
|
||||
ServiceContext.getContext().setStatus(GCUBEServiceContext.Status.FAILED);
|
||||
return false;
|
||||
} else
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/** Tries to create the resource in all the instance scopes*/
|
||||
protected class HState extends GCUBEHandler<Object> {
|
||||
|
||||
public HState() {}
|
||||
|
||||
public void run() throws Exception {
|
||||
|
||||
GCUBEScope scope = ServiceContext.getContext().getInstance().getScopes().values().iterator().next();
|
||||
logger.trace("Adding ResourceManager resource to " + scope);
|
||||
ServiceContext.getContext().setScope(scope);
|
||||
StatefulPortTypeContext.getContext().getWSHome().create(StatefulPortTypeContext.getContext().makeKey(ResourceManager.SINGLETON_RESOURCE_KEY));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Given a relative path in the /etc folder of the service, returns its absolute path
|
||||
*
|
||||
* @param path a relative path to a configuration file or folder
|
||||
* @return the absolute path of the file
|
||||
*/
|
||||
public String getConfigurationFileAbsolutePath(String relativepath) {
|
||||
File file = super.getFile(relativepath, false);
|
||||
//eventually creates the directory tree if needed
|
||||
if (!file.exists() || file.isDirectory()) {file.mkdirs();}
|
||||
return file.getAbsolutePath();
|
||||
|
||||
}
|
||||
/** IllegalServiceScopeException exception */
|
||||
public static class IllegalServiceScopeException extends Exception{
|
||||
private static final long serialVersionUID = 1L;
|
||||
public IllegalServiceScopeException(String message) {super(message);}};
|
||||
}
|
|
@ -0,0 +1,40 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.contexts;
|
||||
|
||||
import org.gcube.common.core.contexts.GCUBEServiceContext;
|
||||
import org.gcube.common.core.contexts.GCUBEStatefulPortTypeContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class StatefulPortTypeContext extends GCUBEStatefulPortTypeContext {
|
||||
|
||||
static StatefulPortTypeContext cache = new StatefulPortTypeContext();
|
||||
|
||||
@Override
|
||||
public String getJNDIName() {
|
||||
return "gcube/vremanagement/ResourceManager";
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getNamespace() {
|
||||
return "http://gcube-system.org/namespaces/vremanagement/vremanager";
|
||||
}
|
||||
|
||||
@Override
|
||||
public GCUBEServiceContext getServiceContext() {
|
||||
return ServiceContext.getContext();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the stateful context
|
||||
*/
|
||||
public static GCUBEStatefulPortTypeContext getContext() {
|
||||
return cache;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,383 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.deployment;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Calendar;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.DeployedDependency;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Service;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedRunningInstance;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STATUS;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ProfileDate;
|
||||
import org.kxml2.io.KXmlParser;
|
||||
import org.xmlpull.v1.XmlPullParserException;
|
||||
|
||||
/**
|
||||
* Parser for the report sent by the Deployer Service
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class DeployerReport {
|
||||
|
||||
protected GCUBELog logger = new GCUBELog(this);
|
||||
|
||||
private String report = "";
|
||||
|
||||
private String status = "";
|
||||
|
||||
private String id = "";
|
||||
|
||||
private String host = "";
|
||||
|
||||
private String type = "";
|
||||
|
||||
private Date lastUpdate;
|
||||
|
||||
private List<DeployedDependency> dependencies = new ArrayList<DeployedDependency>();
|
||||
|
||||
private Set<DeployedRunningInstance> instances = new HashSet<DeployedRunningInstance>();
|
||||
|
||||
/**
|
||||
*
|
||||
* @param report the string representation of the report as sent by a Deployer Service
|
||||
*
|
||||
*/
|
||||
public DeployerReport(String report) throws Exception {
|
||||
this.report = report;
|
||||
try {
|
||||
this.parse();
|
||||
} catch (XmlPullParserException e) {
|
||||
throw new Exception("invalid Deployer Report");
|
||||
}
|
||||
}
|
||||
/**
|
||||
* Gets the GHN ID
|
||||
* @return the id
|
||||
*
|
||||
* @throws Exception if it is impossible to parse the Deployer Report or the GHNID element is not found
|
||||
*/
|
||||
public String getGHNID() {
|
||||
//look for GHNID element
|
||||
return this.id;
|
||||
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return this.report;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
/**
|
||||
* @return the lastUpdate
|
||||
*/
|
||||
public Date getLastUpdate() {
|
||||
return lastUpdate;
|
||||
}
|
||||
/**
|
||||
* @return the dependencies
|
||||
*/
|
||||
public List<DeployedDependency> getDependencies() {
|
||||
return dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the hostname from which the report was sent
|
||||
*/
|
||||
public String getHost() {
|
||||
return this.host;
|
||||
}
|
||||
|
||||
private void parse() throws Exception {
|
||||
KXmlParser parser = new KXmlParser();
|
||||
parser.setInput(new BufferedReader(new StringReader(report)));
|
||||
loop: while (true) {
|
||||
try {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("GHNID")) this.id = parser.nextText();
|
||||
else if (parser.getName().equals("Type")) this.type = parser.nextText();
|
||||
else if (parser.getName().equals("LastUpdate")) this.lastUpdate = ProfileDate.fromXMLDateAndTime( parser.nextText());
|
||||
else if (parser.getName().equals("Status")) this.status = parser.nextText();
|
||||
else if (parser.getName().equals("Packages")) this.parsePackages(parser);
|
||||
else if (parser.getName().equals("NewInstances")) this.parseInstances(parser);
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: break loop;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to parse the Deployer Report",e);
|
||||
throw new Exception ("Unable to parse the Deployer Report",e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void parseInstances(KXmlParser parser) throws Exception {
|
||||
|
||||
loop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("NewInstance")) {
|
||||
DeployedRunningInstance instance = new DeployedRunningInstance();
|
||||
innerloop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("ID")) instance.setRIId(parser.nextText());
|
||||
if (parser.getName().equals("ServiceClass")) instance.setServiceClass(parser.nextText());
|
||||
if (parser.getName().equals("ServiceName")) instance.setServiceName(parser.nextText());
|
||||
if (parser.getName().equals("ServiceVersion")) instance.setServiceVersion(parser.nextText());
|
||||
if (parser.getName().equals("PackageVersion")) instance.setPackageVersion(parser.nextText());
|
||||
if (parser.getName().equals("PackageName")) instance.setPackageName(parser.nextText());
|
||||
break ;
|
||||
case KXmlParser.END_TAG: if (parser.getName().equals("NewInstance")){
|
||||
try {
|
||||
ScopedRunningInstance ri = (ScopedRunningInstance) ScopedResourceFactory.newResource(instance.getRIID(), GCUBERunningInstance.TYPE, ServiceContext.getContext().getScope());
|
||||
ri.setHostedON(this.host);
|
||||
ri.setJointTime(Calendar.getInstance().getTime());
|
||||
ri.setStatus(STATUS.PUBLISHED);
|
||||
instance.setInstance(ri);
|
||||
instance.isAlive = true;
|
||||
instance.setMessage("An instance of this service has been correctly activated on " + this.host);
|
||||
} catch (Exception e) {
|
||||
logger.error("An instance of this service has been activated but it didn't start correctly on " + this.host + ". The expected instance identifier was " + instance.getRIID(), e);
|
||||
instance.setMessage("An instance of this service has been activated but it didn't start correctly on " + this.host + ". The expected instance identifier was " + instance.getRIID());
|
||||
instance.isAlive = false;
|
||||
} finally {
|
||||
this.instances.add(instance);
|
||||
}
|
||||
break innerloop;
|
||||
}
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: throw new Exception ("Parsing failed at NewInstance");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KXmlParser.END_TAG: if (parser.getName().equals("NewInstances")) break loop;
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: throw new Exception ("Parsing failed at NewInstances");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void parsePackages(KXmlParser parser) throws Exception {
|
||||
loop: while (true) {
|
||||
try {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("Package")) {
|
||||
DeployedDependency dd = new DeployedDependency();
|
||||
dd.setService(new Service());
|
||||
innerloop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("ServiceClass")) {dd.getService().setClazz(parser.nextText());}
|
||||
else if (parser.getName().equals("ServiceName")) {dd.getService().setName(parser.nextText());}
|
||||
else if (parser.getName().equals("ServiceVersion")) {dd.getService().setVersion(parser.nextText());}
|
||||
else if (parser.getName().equals("PackageName")) {dd.setName(parser.nextText());}
|
||||
else if (parser.getName().equals("PackageVersion")) {dd.setVersion(parser.nextText());}
|
||||
else if (parser.getName().equals("Status")) {dd.setStatus(parser.nextText());}
|
||||
else if (parser.getName().equals("Host")) {dd.setHost(parser.nextText()); this.host = dd.getHost();}
|
||||
else if (parser.getName().equals("Message")) {dd.setMessage(parser.nextText());}
|
||||
else parser.nextText();
|
||||
break;
|
||||
case KXmlParser.END_TAG: if (parser.getName().equals("Package")){ this.dependencies.add(dd); break innerloop;}
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: throw new Exception ("Parsing failed at Package");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KXmlParser.END_TAG: if (parser.getName().equals("Packages")) break loop;
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: throw new Exception ("Parsing failed at Packages");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Exception ("Unable to parse the Deployer Report");
|
||||
}
|
||||
}
|
||||
}
|
||||
/**
|
||||
* @return the status
|
||||
*/
|
||||
public String getStatus() {
|
||||
return this.status;
|
||||
}
|
||||
/**
|
||||
* @return the instances
|
||||
*/
|
||||
public Set<DeployedRunningInstance> getInstances() {
|
||||
return this.instances;
|
||||
}
|
||||
|
||||
public final class DeployedRunningInstance {
|
||||
private ScopedRunningInstance instance;
|
||||
private String riid;
|
||||
private String serviceClass;
|
||||
private String serviceName;
|
||||
private String serviceVersion;
|
||||
private String packageName;
|
||||
private String packageVersion;
|
||||
private boolean isAlive;
|
||||
private String message;
|
||||
/**
|
||||
* @return the instance
|
||||
*/
|
||||
public ScopedRunningInstance getInstance() {
|
||||
return instance;
|
||||
}
|
||||
/**
|
||||
* @param instance the instance to set
|
||||
*/
|
||||
public void setInstance(ScopedRunningInstance instance) {
|
||||
this.instance = instance;
|
||||
}
|
||||
/**
|
||||
* @return the serviceClass
|
||||
*/
|
||||
public String getServiceClass() {
|
||||
return serviceClass;
|
||||
}
|
||||
/**
|
||||
* @param serviceClass the serviceClass to set
|
||||
*/
|
||||
public void setServiceClass(String serviceClass) {
|
||||
this.serviceClass = serviceClass;
|
||||
}
|
||||
/**
|
||||
* @return the serviceName
|
||||
*/
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
/**
|
||||
* @param serviceName the serviceName to set
|
||||
*/
|
||||
public void setServiceName(String serviceName) {
|
||||
this.serviceName = serviceName;
|
||||
}
|
||||
/**
|
||||
* @return the serviceVersion
|
||||
*/
|
||||
public String getServiceVersion() {
|
||||
return serviceVersion;
|
||||
}
|
||||
/**
|
||||
* @param serviceVersion the serviceVersion to set
|
||||
*/
|
||||
public void setServiceVersion(String serviceVersion) {
|
||||
this.serviceVersion = serviceVersion;
|
||||
}
|
||||
/**
|
||||
* @return the packageName
|
||||
*/
|
||||
public String getPackageName() {
|
||||
return packageName;
|
||||
}
|
||||
/**
|
||||
* @param packageName the packageName to set
|
||||
*/
|
||||
public void setPackageName(String packageName) {
|
||||
this.packageName = packageName;
|
||||
}
|
||||
/**
|
||||
* @return the packageVersion
|
||||
*/
|
||||
public String getPackageVersion() {
|
||||
return packageVersion;
|
||||
}
|
||||
/**
|
||||
* @param packageVersion the packageVersion to set
|
||||
*/
|
||||
public void setPackageVersion(String packageVersion) {
|
||||
this.packageVersion = packageVersion;
|
||||
}
|
||||
/**
|
||||
* @return the riid
|
||||
*/
|
||||
public String getRIID() {
|
||||
return riid;
|
||||
}
|
||||
/**
|
||||
* @param riid the riid to set
|
||||
*/
|
||||
public void setRIId(String riid) {
|
||||
this.riid = riid;
|
||||
}
|
||||
/**
|
||||
* @return the isAlive
|
||||
*/
|
||||
public boolean isAlive() {
|
||||
return isAlive;
|
||||
}
|
||||
/**
|
||||
* @param isAlive the isAlive to set
|
||||
*/
|
||||
public void setAlive(boolean isAlive) {
|
||||
this.isAlive = isAlive;
|
||||
}
|
||||
/**
|
||||
* @return the message
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
/**
|
||||
* @param message the message to set
|
||||
*/
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + getOuterType().hashCode();
|
||||
result = prime * result + ((riid == null) ? 0 : riid.hashCode());
|
||||
return result;
|
||||
}
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
DeployedRunningInstance other = (DeployedRunningInstance) obj;
|
||||
if (!getOuterType().equals(other.getOuterType()))
|
||||
return false;
|
||||
if (riid == null) {
|
||||
if (other.riid != null)
|
||||
return false;
|
||||
} else if (!riid.equals(other.riid))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
private DeployerReport getOuterType() {
|
||||
return DeployerReport.this;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,261 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.deployment;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.axis.message.addressing.EndpointReferenceType;
|
||||
import org.gcube.common.core.contexts.GCUBERemotePortTypeContext;
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.informationsystem.client.AtomicCondition;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBERIQuery;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Dependency;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Service;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.softwaregateway.stubs.AccessPortType;
|
||||
import org.gcube.vremanagement.softwaregateway.stubs.DependenciesCoordinates;
|
||||
import org.gcube.vremanagement.softwaregateway.stubs.service.AccessServiceAddressingLocator;
|
||||
import org.kxml2.io.KXmlParser;
|
||||
|
||||
/**
|
||||
* Request for the Software Repository service to solve the service2package
|
||||
* relationships
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class SoftwareGatewayRequest {
|
||||
|
||||
private Map<ScopedDeployedService, DependenciesCoordinates> requests = new HashMap<ScopedDeployedService, DependenciesCoordinates>();
|
||||
|
||||
protected static final String RESOLVED_DEPS_KEY = "listResolvedDeps";
|
||||
|
||||
protected static final String MISSING_DEPS_KEY = "listMissingDeps";
|
||||
/** Target port-type name. */
|
||||
protected static final String REPOSITORY_ENDPOINT = "gcube/vremanagement/softwaregateway/Access";
|
||||
/** Target service name. */
|
||||
protected static final String REPOSITORY_NAME = "SoftwareGateway";
|
||||
/** Target service class. */
|
||||
protected static final String REPOSITORY_CLASS = "VREManagement";
|
||||
/** Timeout for contacting the target service. */
|
||||
protected static final int TIMEOUT = 600000; //in milliseconds
|
||||
/** Object logger */
|
||||
protected final GCUBELog logger = new GCUBELog(this);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new service to the request
|
||||
*
|
||||
* @param service
|
||||
*/
|
||||
public void addService(ScopedDeployedService service) {
|
||||
DependenciesCoordinates message = new DependenciesCoordinates();
|
||||
message.setServiceClass(service.getSourceService().getClazz());
|
||||
message.setServiceName(service.getSourceService().getName());
|
||||
message.setServiceVersion(service.getSourceService().getVersion());
|
||||
requests.put(service, message);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends the request to the appropriate SR
|
||||
*
|
||||
* @throws Exception
|
||||
*/
|
||||
public List<ScopedDeployedService> send() throws Exception {
|
||||
List<ScopedDeployedService> service2package = new ArrayList<ScopedDeployedService>();
|
||||
Map<GCUBEScope, Set<EndpointReferenceType>> eprs = this.findInstances();
|
||||
for (ScopedDeployedService service : requests.keySet()) {
|
||||
DependenciesCoordinates packageCoordinates = requests.get(service);
|
||||
logger.trace("Checking deps for " + packageCoordinates.getServiceName());
|
||||
//look for service deps in one of the instances found
|
||||
inner: for (GCUBEScope scope : eprs.keySet()) {
|
||||
for (EndpointReferenceType epr : eprs.get(scope)) {
|
||||
try {
|
||||
logger.trace("Trying Service Repository located at "+ epr);
|
||||
AccessServiceAddressingLocator locator = new AccessServiceAddressingLocator();
|
||||
AccessPortType pt = locator.getAccessPortTypePort(epr);
|
||||
String report = GCUBERemotePortTypeContext.getProxy(pt, scope, TIMEOUT, ServiceContext.getContext()).getDependencies(packageCoordinates);
|
||||
service2package.add(parseDependenciesReport(service, report));
|
||||
break inner;//no need for looping on the other instances, we just need that one satisfies the request
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to check deps for " + packageCoordinates.getServiceName() + " from Service Repository in " + scope + ": "+ e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
// if we are here, no SR instance was able to resolve the dependencies
|
||||
//ResolvedService s = new ResolvedService(service);
|
||||
service.setErrorMessage("Unable to check deps for this service in any of the Service Repository instance in scope");
|
||||
service2package.add(service);
|
||||
}
|
||||
}
|
||||
return service2package;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the dependencies report
|
||||
* @param report
|
||||
* @return
|
||||
*/
|
||||
private ScopedDeployedService parseDependenciesReport(ScopedDeployedService service, String report) throws Exception {
|
||||
//ResolvedService depsMap = new ResolvedService(service);
|
||||
KXmlParser parser = new KXmlParser();
|
||||
parser.setInput(new BufferedReader(new StringReader(report)));
|
||||
logger.trace("Parsing: " + report);
|
||||
try {
|
||||
loop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("ResolvedDependencies")) this.parseResolvedDependencies(parser, service);
|
||||
if (parser.getName().equals("MissingDependencies")) this.parseMissingDependencies(parser, service);
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT:
|
||||
break loop;
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to parse the deployment report returned by the Software Repository", e);
|
||||
}
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the service section of a dependency
|
||||
*
|
||||
* @param parser the XML parser
|
||||
* @param s the service to populate
|
||||
* @throws Exception
|
||||
*/
|
||||
private void parseService(KXmlParser parser, Service s) throws Exception {
|
||||
inloop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("Class"))
|
||||
s.setClazz(parser.nextText());
|
||||
if (parser.getName().equals("Name"))
|
||||
s.setName(parser.nextText());
|
||||
if (parser.getName().equals("Version"))
|
||||
s.setVersion(parser.nextText());
|
||||
break;
|
||||
case KXmlParser.END_TAG:
|
||||
if (parser.getName().equals("Service"))
|
||||
break inloop;
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT:
|
||||
throw new Exception("Parsing failed at Service");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses a generic dependency section (both missing and resolved)
|
||||
*
|
||||
* @param parser the XML parser
|
||||
* @return the dependency
|
||||
* @throws Exception
|
||||
*/
|
||||
private Dependency parseDependency(KXmlParser parser) throws Exception {
|
||||
Dependency p = new Dependency();
|
||||
loop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("Service")) parseService(parser, p.getService());
|
||||
if (parser.getName().equals("Package")) p.setName(parser.nextText());
|
||||
if (parser.getName().equals("Version")) p.setVersion(parser.nextText());
|
||||
break;
|
||||
case KXmlParser.END_TAG:
|
||||
if ((parser.getName().equals("Dependency")) || (parser.getName().equals("MissingDependency"))) break loop;
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT:
|
||||
throw new Exception("Parsing failed at Dependency");
|
||||
}
|
||||
}
|
||||
return p;
|
||||
}
|
||||
|
||||
private void parseResolvedDependencies(KXmlParser parser, ScopedDeployedService service) throws Exception {
|
||||
logger.trace("Parsing resolved dependencies...");
|
||||
List<Dependency> resolved = new ArrayList<Dependency>();
|
||||
loop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("Dependency")) {
|
||||
logger.trace("Dependency found");
|
||||
resolved.add(this.parseDependency(parser));
|
||||
} break;
|
||||
case KXmlParser.END_TAG:
|
||||
if (parser.getName().equals("ResolvedDependencies")) break loop;
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT:
|
||||
throw new Exception("Parsing failed at ResolvedDependencies");
|
||||
}
|
||||
}
|
||||
logger.trace("Number of deps found: " + resolved.size());
|
||||
service.setResolvedDependencies(resolved);
|
||||
}
|
||||
|
||||
private void parseMissingDependencies(KXmlParser parser, ScopedDeployedService service) throws Exception {
|
||||
logger.trace("Parsing missing dependencies...");
|
||||
List<Dependency> missing = new ArrayList<Dependency>();
|
||||
loop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("MissingDependency")) {
|
||||
logger.trace("Dependency found");
|
||||
missing.add(this.parseDependency(parser));
|
||||
} break;
|
||||
case KXmlParser.END_TAG:
|
||||
if (parser.getName().equals("MissingDependencies")) break loop;
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT:
|
||||
throw new Exception("Parsing failed at MissingDependencies");
|
||||
}
|
||||
}
|
||||
logger.trace("Number of deps found: " + missing.size());
|
||||
service.setMissingDependencies(missing);
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds instances of the Software Repository service in the current scope(s)
|
||||
* @return the list of scopes and the EPR of the available SR
|
||||
* @throws Exception
|
||||
*/
|
||||
protected Map<GCUBEScope, Set<EndpointReferenceType>> findInstances()throws Exception {
|
||||
Map<GCUBEScope, Set<EndpointReferenceType>> scopeMap = new HashMap<GCUBEScope, Set<EndpointReferenceType>>();
|
||||
logger.debug("Looking for SR instances...");
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
GCUBERIQuery lookupQuery = client.getQuery(GCUBERIQuery.class);
|
||||
lookupQuery.addAtomicConditions(new AtomicCondition("//ServiceName",REPOSITORY_NAME));
|
||||
lookupQuery.addAtomicConditions(new AtomicCondition("//ServiceClass",REPOSITORY_CLASS));
|
||||
for (GCUBEScope scope : ServiceContext.getContext().getInstance().getScopes().values()) {
|
||||
/*
|
||||
* if (scope.isInfrastructure()) //TODO: deploy only in a PublishedScopeResource
|
||||
* continue;
|
||||
*/
|
||||
logger.debug("Quering in scope " + scope);
|
||||
List<GCUBERunningInstance> list = client.execute(lookupQuery, scope);
|
||||
logger.debug("Found N." + list.size() + " instances");
|
||||
for (GCUBERunningInstance instance : list) {
|
||||
logger.trace("Found instance " + instance.toString());
|
||||
EndpointReferenceType epr = instance.getAccessPoint().getEndpoint(REPOSITORY_ENDPOINT);
|
||||
logger.trace("Found EPR " + epr.toString());
|
||||
if (!scopeMap.keySet().contains(scope)) {
|
||||
Set<EndpointReferenceType> l = new HashSet<EndpointReferenceType>();
|
||||
scopeMap.put(scope, l);
|
||||
}
|
||||
scopeMap.get(scope).add(epr);
|
||||
}
|
||||
}
|
||||
return scopeMap;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,303 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.deployment;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import org.apache.axis.message.addressing.EndpointReferenceType;
|
||||
import org.gcube.common.core.contexts.GCUBERemotePortTypeContext;
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.informationsystem.client.AtomicCondition;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEGHNQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBERIQuery;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.common.vremanagement.deployer.stubs.common.PackageInfo;
|
||||
import org.gcube.common.vremanagement.deployer.stubs.deployer.DeployParameters;
|
||||
import org.gcube.common.vremanagement.deployer.stubs.deployer.DeployerPortType;
|
||||
import org.gcube.common.vremanagement.deployer.stubs.deployer.UndeployParameters;
|
||||
import org.gcube.common.vremanagement.deployer.stubs.deployer.service.DeployerServiceAddressingLocator;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.StatefulPortTypeContext;
|
||||
|
||||
/**
|
||||
* A target node for deployment and undeployment operations
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class VirtualNode {
|
||||
|
||||
/** Object logger */
|
||||
protected final GCUBELog logger=new GCUBELog(this);
|
||||
|
||||
/**the callback identifier to send to the Deployer*/
|
||||
private String callbackID;
|
||||
|
||||
private String ghnID = "";
|
||||
|
||||
private GCUBEScope scope = null;
|
||||
|
||||
private boolean isWorking = false;
|
||||
|
||||
private Set<PackageInfo> packagesToAdd = new HashSet<PackageInfo>();
|
||||
|
||||
private Set<PackageInfo> packagesToRemove = new HashSet<PackageInfo>();
|
||||
|
||||
private long lastActivity;
|
||||
|
||||
//here only for backward compatibility (deserialization will fail)
|
||||
private String name = "";
|
||||
|
||||
//if we do not receive a deployment session from the node after one hour, we assume that the node is not working anymore
|
||||
private static final long MAX_ACTIVITY = 3600 * 1000; //1h in milliseconds
|
||||
|
||||
protected VirtualNode(String ID, GCUBEScope scope) throws NoGHNFoundException {
|
||||
this.ghnID = ID;
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
public void setCallbackID(String id) {
|
||||
this.callbackID = id;
|
||||
}
|
||||
|
||||
public String detectName() throws NoGHNFoundException {
|
||||
logger.debug("Detecting name for " + this.ghnID);
|
||||
if (GHNContext.getContext().getGHNID().compareToIgnoreCase(this.ghnID) == 0)
|
||||
throw new NoGHNFoundException ("cannot deploy on the same GHN (ghnID=" + this.ghnID + ") where the Resource Manager is deployed");
|
||||
try {
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
GCUBEGHNQuery query = client.getQuery(GCUBEGHNQuery.class);
|
||||
query.addAtomicConditions(new AtomicCondition("/ID/text()", this.ghnID));
|
||||
return client.execute(query, this.scope).get(0).getNodeDescription().getName();
|
||||
} catch (Exception e) {
|
||||
logger.error("unable to find the target GHN (ghnID=" + this.ghnID + ")", e);
|
||||
throw new NoGHNFoundException ("unable to find the target GHN (ghnID=" + this.ghnID + ")");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the packages to remove in the next {@link #deploy()} invocation
|
||||
*
|
||||
* @param packages the list of packagesT to add
|
||||
*/
|
||||
public synchronized void setPackagesToAdd(Set<PackageInfo> packages) {
|
||||
//check if there is a node with all the packagesToAdd already scheduled to be deployed
|
||||
//if so, the service will be already activated there, therefore there is nothing to do
|
||||
if (this.hasPackages(packages))
|
||||
return;
|
||||
this.packagesToAdd.addAll(packages);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packagesToAdd available on this node
|
||||
*
|
||||
* @return the packagesToAdd
|
||||
*/
|
||||
protected Set<PackageInfo> getPackages() {
|
||||
return this.packagesToAdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a list of packagesToAdd is already on this node
|
||||
*
|
||||
* @param packagesToAdd the list of packagesToAdd to check
|
||||
* @return true if all the packagesToAdd are already on this node, false otherwise
|
||||
*/
|
||||
protected boolean hasPackages(Set<PackageInfo> packages) {
|
||||
|
||||
if (packages.size() == 0)
|
||||
return false;
|
||||
if (this.packagesToAdd.size() == 0)
|
||||
return false;
|
||||
input: for (PackageInfo inputPackage : packages) {
|
||||
for (PackageInfo nodePackage : this.packagesToAdd) {
|
||||
if ( (inputPackage.getServiceClass().compareToIgnoreCase(nodePackage.getServiceClass())==0) &&
|
||||
(inputPackage.getServiceName().compareToIgnoreCase(nodePackage.getServiceName())==0) &&
|
||||
(inputPackage.getServiceVersion().compareToIgnoreCase(nodePackage.getServiceVersion())==0) &&
|
||||
(inputPackage.getName().compareToIgnoreCase(nodePackage.getName())==0) &&
|
||||
(inputPackage.getVersion().compareToIgnoreCase(nodePackage.getVersion())==0))
|
||||
continue input;
|
||||
|
||||
}
|
||||
return false; //if we arrive here, no matching package has been found
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the node ghnID
|
||||
*
|
||||
* @return the node ghnID
|
||||
*/
|
||||
public String getID() {
|
||||
return this.ghnID;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sends a request to the physical node to deploy the active list of packages to add
|
||||
*
|
||||
* @throws Exception if the deployment fails
|
||||
*/
|
||||
public synchronized void deploy(GCUBEScope scope) throws Exception {
|
||||
if (packagesToAdd.size() == 0)
|
||||
return;
|
||||
|
||||
if (isWorking && ((System.currentTimeMillis() -this.lastActivity) < MAX_ACTIVITY)) {
|
||||
logger.warn("Can't deploy on " + this +", the gHN is already working");
|
||||
return;
|
||||
}
|
||||
|
||||
EndpointReferenceType callbackEPR = ServiceContext.getContext().getInstance().getAccessPoint().getEndpoint(StatefulPortTypeContext.getContext().getJNDIName());
|
||||
DeployParameters param = new DeployParameters();
|
||||
param.set_package(this.packagesToAdd.toArray(new PackageInfo[0]));
|
||||
param.setTargetScope(new String[] {scope.toString()});
|
||||
param.setCallbackID(callbackID);
|
||||
param.setEndpointReference(callbackEPR);
|
||||
EndpointReferenceType nodeEPR = this.loadDeployer(this.ghnID);
|
||||
logger.trace("Deploying on " + nodeEPR.toString());
|
||||
DeployerPortType pt = GCUBERemotePortTypeContext.getProxy(new DeployerServiceAddressingLocator().getDeployerPortTypePort(nodeEPR),
|
||||
scope, ServiceContext.getContext());
|
||||
pt.deploy(param);
|
||||
this.packagesToAdd.clear();
|
||||
isWorking = true;//this will prevent further requests to the ghn until the deployment session is received back
|
||||
this.lastActivity = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/**
|
||||
* Undeploys the packages from the node
|
||||
* @param scope the scope to use for the undeployment
|
||||
*
|
||||
* @throws Exception if the operation fails
|
||||
*/
|
||||
public synchronized void undeploy(GCUBEScope scope) throws Exception {
|
||||
if (this.packagesToRemove.size() == 0)
|
||||
return;
|
||||
|
||||
if (isWorking && (this.lastActivity - System.currentTimeMillis() < MAX_ACTIVITY)) {
|
||||
logger.warn("Can't undeploy from " + this +", the gHN is already working");
|
||||
return;
|
||||
}
|
||||
|
||||
EndpointReferenceType callbackEPR = ServiceContext.getContext().getInstance().getAccessPoint().getEndpoint(StatefulPortTypeContext.getContext().getJNDIName());
|
||||
UndeployParameters params = new UndeployParameters();
|
||||
params.set_package(this.packagesToRemove.toArray(new PackageInfo[0]));
|
||||
params.setTargetScope(new String[] {scope.toString()});
|
||||
params.setCallbackID(callbackID);
|
||||
params.setEndpointReference(callbackEPR);
|
||||
EndpointReferenceType nodeEPR = this.loadDeployer(this.ghnID);
|
||||
logger.trace("Undeploying from " + nodeEPR.toString() + " in scope " + scope);
|
||||
DeployerPortType pt = GCUBERemotePortTypeContext.getProxy(new DeployerServiceAddressingLocator().getDeployerPortTypePort(nodeEPR),
|
||||
scope, ServiceContext.getContext());
|
||||
pt.undeploy(params);
|
||||
this.packagesToRemove.clear();
|
||||
isWorking = true;//this will prevent further requests to the ghn until the deployment session is received back
|
||||
this.lastActivity = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
/** NoGHNFoundException exception */
|
||||
public static class NoGHNFoundException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
public NoGHNFoundException(String message) {super(message);}
|
||||
}
|
||||
/**
|
||||
* Marks the node as not working node
|
||||
* (usually called when a closed {@link DeployerReport} is received from the node)
|
||||
*/
|
||||
public void isNotWorking() {
|
||||
this.isWorking = false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the packages to remove in the nect {@link #undeploy()} invocation
|
||||
* @param packages the packages to remove from the node
|
||||
*/
|
||||
public synchronized void setPackagesToRemove(Set<PackageInfo> packages) {
|
||||
this.packagesToRemove.addAll(packages);
|
||||
}
|
||||
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "VirtualNode [ghnID=" + ghnID + ", scope="+ scope + "]";
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((ghnID == null) ? 0 : ghnID.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
VirtualNode other = (VirtualNode) obj;
|
||||
if (ghnID == null) {
|
||||
if (other.ghnID != null)
|
||||
return false;
|
||||
} else if (!ghnID.equals(other.ghnID))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns a working scope to the node
|
||||
* @param scope the scope to set
|
||||
*/
|
||||
public void setWorkingScope(GCUBEScope scope) {
|
||||
this.scope = scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the packages scheduled for the next deployment on this node
|
||||
* @return the set of packages
|
||||
*/
|
||||
public Set<PackageInfo> getScheduledPackages() {
|
||||
return this.packagesToAdd;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current scope used on this node
|
||||
* @return the current scope
|
||||
*/
|
||||
public GCUBEScope getWorkingScope() {
|
||||
return this.scope;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Looks for the Deployer's endpoint to contact
|
||||
* @param id the identifier of the gHN
|
||||
* @return the endpoint reference of Deployer's portType to contact
|
||||
* @throws Exception if the search fails
|
||||
*/
|
||||
private EndpointReferenceType loadDeployer(String id) throws Exception {
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
GCUBERIQuery riquery = client.getQuery(GCUBERIQuery.class);
|
||||
riquery.addAtomicConditions(new AtomicCondition("//GHN/@UniqueID", id),
|
||||
new AtomicCondition("//ServiceClass", "VREManagement"),
|
||||
new AtomicCondition("//ServiceName", "Deployer"));
|
||||
List<GCUBERunningInstance> results = client.execute(riquery,ServiceContext.getContext().getScope());
|
||||
return results.get(0).getAccessPoint().getEndpoint("gcube/common/vremanagement/Deployer");
|
||||
}
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.deployment;
|
||||
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode.NoGHNFoundException;
|
||||
|
||||
/**
|
||||
*
|
||||
* Manager for {@link VirtualNode}s
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class VirtualNodeManager {
|
||||
|
||||
/** maps ghn ID to the related virtual node*/
|
||||
private static Map<String, VirtualNode> nodes;
|
||||
|
||||
static { //at startup time, all the nodes are not working
|
||||
if (nodes != null) {
|
||||
for (VirtualNode node : nodes.values()) {
|
||||
node.isNotWorking();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets or builds the VirtualNode
|
||||
* @param ID the node identifier
|
||||
* @param scope the deployment scope
|
||||
* @return the Virtual Node
|
||||
* @throws NoGHNFoundException if the node does not exist
|
||||
*/
|
||||
public static VirtualNode getNode(String ID, GCUBEScope scope) throws NoGHNFoundException {
|
||||
checkNodes();
|
||||
if (!nodes.containsKey(ID)) {
|
||||
nodes.put(ID,new VirtualNode(ID, scope));
|
||||
}
|
||||
return nodes.get(ID);
|
||||
}
|
||||
|
||||
/**
|
||||
* Assigns the initial set of nodes to the manager.
|
||||
* @param nodes the set of nodes
|
||||
*/
|
||||
public static void setNodes(Map<String, VirtualNode> nodes) {
|
||||
VirtualNodeManager.nodes = nodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks the set of node, must be called before any usage of <code>nodes</code> to check if it has been initialized
|
||||
*/
|
||||
private static void checkNodes(){
|
||||
if (nodes == null)
|
||||
nodes = new HashMap<String, VirtualNode>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,105 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.deployment.resources;
|
||||
|
||||
|
||||
public class Dependency {
|
||||
|
||||
protected Service service = new Service();
|
||||
|
||||
protected String name;
|
||||
|
||||
protected String version;
|
||||
|
||||
/**
|
||||
* @return the service
|
||||
*/
|
||||
public Service getService() {
|
||||
return service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param service the service to set
|
||||
*/
|
||||
public void setService(Service service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version the version to set
|
||||
*/
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((service == null) ? 0 : service.hashCode());
|
||||
result = prime * result + ((version == null) ? 0 : version.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
final Dependency other = (Dependency) obj;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (service == null) {
|
||||
if (other.service != null)
|
||||
return false;
|
||||
} else if (!service.equals(other.service))
|
||||
return false;
|
||||
if (version == null) {
|
||||
if (other.version != null)
|
||||
return false;
|
||||
} else if (!version.equals(other.version))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Dependency [name=" + name
|
||||
+ ", version=" + version
|
||||
+ ", service=" + service + "]";
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,58 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.deployment.resources;
|
||||
|
||||
/**
|
||||
* A package deployed by a Deployer service
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class DeployedDependency extends Dependency {
|
||||
|
||||
protected String host = "";
|
||||
|
||||
protected String status = "";
|
||||
|
||||
protected String message = "";
|
||||
|
||||
/**
|
||||
* @return the host
|
||||
*/
|
||||
public String getHost() {
|
||||
return host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param host the host to set
|
||||
*/
|
||||
public void setHost(String host) {
|
||||
this.host = host;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the status
|
||||
*/
|
||||
public String getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param status the status to set
|
||||
*/
|
||||
public void setStatus(String status) {
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the message
|
||||
*/
|
||||
public String getMessage() {
|
||||
return message;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param message the message to set
|
||||
*/
|
||||
public void setMessage(String message) {
|
||||
this.message = message;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,151 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.deployment.resources;
|
||||
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ServiceItem;
|
||||
|
||||
/**
|
||||
* A GCUBE service
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class Service {
|
||||
|
||||
protected String clazz;
|
||||
|
||||
protected String name;
|
||||
|
||||
protected String version;
|
||||
|
||||
/** the gHN on which the servie is expected to be deployed */
|
||||
protected String GHN = null;
|
||||
|
||||
|
||||
public Service(String serviceClass, String serviceName, String serviceVersion) {
|
||||
this.setClazz(serviceClass);
|
||||
this.setName(serviceName);
|
||||
this.setVersion(serviceVersion);
|
||||
}
|
||||
|
||||
public Service() {}
|
||||
|
||||
public static Service fromServiceItem(ServiceItem item) {
|
||||
Service s = new Service();
|
||||
s.setClazz(item.getServiceClass());
|
||||
s.setName(item.getServiceName());
|
||||
s.setVersion(item.getServiceVersion());
|
||||
if ((item.getGHN() != null) && (item.getGHN().compareToIgnoreCase("")!=0))
|
||||
s.setGHN(item.getGHN());
|
||||
return s;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the clazz
|
||||
*/
|
||||
public String getClazz() {
|
||||
return clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param clazz the class to set
|
||||
*/
|
||||
public void setClazz(String clazz) {
|
||||
this.clazz = clazz;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the name
|
||||
*/
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param name the name to set
|
||||
*/
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the version
|
||||
*/
|
||||
public String getVersion() {
|
||||
return version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param version the version to set
|
||||
*/
|
||||
public void setVersion(String version) {
|
||||
this.version = version;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the gHNID
|
||||
*/
|
||||
public String getGHN() {
|
||||
return GHN;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param ghn the gHN to set
|
||||
*/
|
||||
public void setGHN(String ghn) {
|
||||
GHN = ghn;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#hashCode()
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((clazz == null) ? 0 : clazz.hashCode());
|
||||
result = prime * result + ((name == null) ? 0 : name.hashCode());
|
||||
result = prime * result + ((version == null) ? 0 : version.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#equals(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Service other = (Service) obj;
|
||||
if (clazz == null) {
|
||||
if (other.clazz != null)
|
||||
return false;
|
||||
} else if (!clazz.equals(other.clazz))
|
||||
return false;
|
||||
if (name == null) {
|
||||
if (other.name != null)
|
||||
return false;
|
||||
} else if (!name.equals(other.name))
|
||||
return false;
|
||||
if (version == null) {
|
||||
if (other.version != null)
|
||||
return false;
|
||||
} else if (!version.equals(other.version))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Object#toString()
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Service [class=" + clazz
|
||||
+ ", name=" + name
|
||||
+ ", version=" + version + "]";
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,69 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.operators;
|
||||
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.AddResourcesParameters;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ResourceList;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ServiceList;
|
||||
|
||||
/**
|
||||
* A Resources Operator that coordinates the adding of resources to the scope
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class AddResourcesOperator extends Operator {
|
||||
|
||||
protected final GCUBELog logger = new GCUBELog(this, ServiceContext.getContext());
|
||||
|
||||
private AddResourcesParameters resourceList;
|
||||
|
||||
private OperatorConfig configuration;
|
||||
|
||||
/**
|
||||
* Creates a new operator to manage the input resource list
|
||||
*
|
||||
* @param scopeState
|
||||
* @param target
|
||||
* @param operationID
|
||||
*/
|
||||
public AddResourcesOperator(OperatorConfig configuration, AddResourcesParameters resourceList){
|
||||
this.resourceList = resourceList;
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public void exec() throws Exception {
|
||||
// deploy the services, if any
|
||||
ServiceList services = resourceList.getServices();
|
||||
if ((services == null) || (services.getService() == null) || (services.getService().length == 0)) {
|
||||
logger.warn("The list of services to deploy is empty");
|
||||
} else {
|
||||
try {
|
||||
new DeployServiceOperator(configuration, services, ACTION.ADD).run();
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to activate the deployment of the given service(s)", e);
|
||||
throw new Exception("Unable to activate the deployment of the given service(s)", e);
|
||||
}
|
||||
}
|
||||
|
||||
//add the resources to the PublishedScopeResource, if any
|
||||
ResourceList resources = resourceList.getResources();
|
||||
if ((resources == null) || (resources.getResource() == null) || (resources.getResource().length == 0))
|
||||
logger.warn("The list of resource to add is empty");
|
||||
else {
|
||||
try {
|
||||
new ScopedResourceManagerOperator(configuration, resources, ACTION.ADD).run();
|
||||
}catch (Exception e) {
|
||||
logger.error("Unable to manage the given resource(s)", e);
|
||||
throw new Exception("Unable to manage the given resource(s)", e);
|
||||
}
|
||||
}
|
||||
//save the session
|
||||
this.configuration.session.save();
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,169 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.operators;
|
||||
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEServiceQuery;
|
||||
import org.gcube.common.core.resources.GCUBEHostingNode;
|
||||
import org.gcube.common.core.resources.GCUBEService;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.scope.GCUBEScope.Type;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ServiceItem;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ServiceList;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.brokerage.BrokerConnector;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Service;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STATUS;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session.OPERATION;
|
||||
|
||||
/**
|
||||
* A Deployer Operator that contacts the Deployer Services on the target nodes asking for the package deployment
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class DeployServiceOperator extends Operator {
|
||||
|
||||
/** Object logger */
|
||||
protected final GCUBELog logger=new GCUBELog(this);
|
||||
|
||||
private ServiceList services;
|
||||
|
||||
private OperatorConfig configuration;
|
||||
|
||||
public DeployServiceOperator(OperatorConfig configuration, ServiceList services, ACTION action) {
|
||||
this.services = services;
|
||||
this.configuration = configuration;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public void exec() throws Exception {
|
||||
|
||||
this.configuration.session.save();
|
||||
|
||||
Set<ScopedDeployedService> servicesToDeploy = new HashSet<ScopedDeployedService>();
|
||||
Set<ScopedResource> servicesToUndeploy = new HashSet<ScopedResource>();
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
|
||||
for (ServiceItem serviceitem : services.getService()) {
|
||||
String serviceID = null;
|
||||
try {
|
||||
//retrieve the service ID from the IS
|
||||
GCUBEServiceQuery query = client.getQuery(GCUBEServiceQuery.class);
|
||||
query.addGenericCondition("$result/Profile/Name/string() eq '"+serviceitem.getServiceName()+
|
||||
"' and $result/Profile/Class/string() eq '"+ serviceitem.getServiceClass() +"'");
|
||||
List<GCUBEService> profiles = client.execute(query, this.configuration.scope);
|
||||
if ((profiles == null) || (profiles.size() == 0)) {
|
||||
logger.error("Failed to find the service");
|
||||
continue;
|
||||
}
|
||||
logger.debug("Retrieved service ID " + profiles.get(0).getID() );
|
||||
serviceID = profiles.get(0).getID();
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to retrieve the service ID from the IS ",e );
|
||||
continue;
|
||||
}
|
||||
//build the related scoped resource
|
||||
ScopedDeployedService service = (ScopedDeployedService) ScopedResourceFactory.newResource(serviceID, GCUBEService.TYPE, this.configuration.scope);
|
||||
service.setSourceServiceName(Service.fromServiceItem(serviceitem));
|
||||
try {
|
||||
if (this.action == ACTION.ADD) {
|
||||
service.findResource();//resolve the service deps
|
||||
if (service.isSuccess())
|
||||
servicesToDeploy.add(service);
|
||||
} else {
|
||||
service.setCallbackID(this.configuration.session.getId());
|
||||
servicesToUndeploy.add(service);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.warn("Failed to find the service",e);
|
||||
}
|
||||
this.configuration.session.addResource(service);
|
||||
this.configuration.session.addService(service); //for the specific service section
|
||||
}
|
||||
//create the Deployment Plan with the Resource Broker
|
||||
if ((this.action == ACTION.ADD) && this.allocate(servicesToDeploy)) {
|
||||
Set<ScopedResource> resourcesToAdd = new HashSet<ScopedResource>();
|
||||
for (ScopedDeployedService service : servicesToDeploy) {
|
||||
if (service.getStatus() != STATUS.LOST) {
|
||||
service.setCallbackID(this.configuration.session.getId());
|
||||
resourcesToAdd.add(service);
|
||||
if (this.configuration.scope.getType() == Type.VRE) {
|
||||
//add also the target gHN to the scope
|
||||
ScopedResource ghn = ScopedResourceFactory.newResource(service.getTargetGHNID(), GCUBEHostingNode.TYPE, this.configuration.scope);
|
||||
resourcesToAdd.add(ghn);
|
||||
this.configuration.session.addResource(ghn);
|
||||
}
|
||||
}
|
||||
}
|
||||
//add the services to the ScopeState (if any)
|
||||
if(servicesToDeploy.size() > 0) {
|
||||
this.configuration.scopeState.addResources(resourcesToAdd);
|
||||
final GCUBEScope tscope = this.configuration.scope;
|
||||
final Session tsession = this.configuration.session;
|
||||
//periodically check if the feedback has to be sent to the broker
|
||||
new Thread() {
|
||||
@Override
|
||||
public void run() {
|
||||
while (true) {
|
||||
try { Thread.sleep(5000);
|
||||
} catch (InterruptedException e) {}
|
||||
//logger.trace("ServiceOperator is checking if the session is closed");
|
||||
if ((tsession.isReportClosed()
|
||||
&& ((tsession.getOperation()==OPERATION.AddResources)
|
||||
|| (tsession.getOperation()==OPERATION.UpdateResources)
|
||||
|| (tsession.getOperation()==OPERATION.Create)))) {
|
||||
try {
|
||||
BrokerConnector.getBroker(tscope).sendFeedback(tsession);
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to send the feedback to the Broker", e);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}.start();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
//remove the services from the ScopeState (if any)
|
||||
if(servicesToUndeploy.size() > 0)
|
||||
this.configuration.scopeState.removeResources(servicesToUndeploy);
|
||||
|
||||
this.configuration.session.save();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Contacts the broker in order to allocate the given services
|
||||
* @param servicesToDeploy the services to be deployed
|
||||
* @return true if each service is correctly allocated, false otherwise
|
||||
*/
|
||||
private boolean allocate(Set<ScopedDeployedService> servicesToDeploy) {
|
||||
try {
|
||||
if (servicesToDeploy.size() > 0) {
|
||||
BrokerConnector.getBroker(this.configuration.scope).makePlan(this.configuration.session, servicesToDeploy, services.getGHN());
|
||||
this.configuration.session.reportBrokerWork(true, "The Deployment Plan was successfully created");
|
||||
return true;
|
||||
} else {
|
||||
logger.warn("The Broker was not contacted. After the dependency resolution phase, there is nothing to deploy");
|
||||
this.configuration.session.reportBrokerWork(false, "The Broker was not contacted. After the dependency resolution phase, there is nothing to deploy");
|
||||
return true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.error("An error occurred when interacting with the broker", e);
|
||||
this.configuration.session.reportBrokerWork(false, "An error occurred when interacting with the broker " + e.getMessage());
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,49 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.operators;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STATUS;
|
||||
|
||||
/**
|
||||
*
|
||||
* Dispose the entire scope
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class DisposeScopeOperator extends Operator {
|
||||
|
||||
protected final GCUBELog logger = new GCUBELog(this, ServiceContext.getContext());
|
||||
|
||||
private OperatorConfig configuration;
|
||||
|
||||
public DisposeScopeOperator(OperatorConfig configuration) {
|
||||
this.configuration = configuration;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void exec() throws Exception {
|
||||
//exclude from the resources to remove the Services' resources. This is because we also have the
|
||||
//related Running Instances in the list, and we will eventually undeploy them (if # scopes ==1)
|
||||
Set<ScopedResource> resources = new HashSet<ScopedResource>();
|
||||
for (ScopedResource resource : this.configuration.scopeState.getAllResources()) {
|
||||
if ((resource.getType().compareTo(ScopedDeployedService.TYPE) != 0)
|
||||
&& (resource.getStatus() != STATUS.UNPUBLISHED)
|
||||
&& (resource.getStatus() != STATUS.LOST)
|
||||
&& (resource.getStatus() != STATUS.REMOVED)){
|
||||
resources.add(resource);
|
||||
this.configuration.session.addResource(resource);
|
||||
}
|
||||
}
|
||||
|
||||
configuration.scopeState.removeResources(resources);
|
||||
//TODO: should we also undeploy the RM itself?
|
||||
|
||||
this.configuration.session.save();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.operators;
|
||||
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
|
||||
/**
|
||||
*
|
||||
* Base class for manager's operators
|
||||
* .
|
||||
* A manage operator is devoted to execute certain assigned tasks.
|
||||
* The {@link #exec()} method is asynchronously called
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public abstract class Operator {
|
||||
|
||||
protected final GCUBELog logger=new GCUBELog(this.getClass());
|
||||
|
||||
protected ACTION action;
|
||||
|
||||
protected OperatorConfig configuration;
|
||||
|
||||
public enum ACTION {ADD,REMOVE}
|
||||
|
||||
public final void run() {
|
||||
//new Thread() {
|
||||
// public void run() {
|
||||
try {
|
||||
Operator.this.exec();
|
||||
} catch (Exception e) {
|
||||
logger.error("The operator was unable to manage the request",e);
|
||||
}
|
||||
// }
|
||||
//}.start();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Executes the operator's tasks
|
||||
*
|
||||
* @throws Exception if any of the tasks fails
|
||||
*/
|
||||
public abstract void exec() throws Exception;
|
||||
|
||||
}
|
|
@ -0,0 +1,28 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.operators;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ScopeState;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.Session;
|
||||
|
||||
/**
|
||||
* Basic configuration for every {@link Operator}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class OperatorConfig {
|
||||
|
||||
public final Session session;
|
||||
|
||||
public final GCUBEScope scope;
|
||||
|
||||
public final ScopeState scopeState;
|
||||
|
||||
public OperatorConfig(Session report, ScopeState scopeState, GCUBEScope ... scope) {
|
||||
this.session = report;
|
||||
this.scopeState = scopeState;
|
||||
this.scope = (scope!=null && scope.length >0)? scope[0] : ServiceContext.getContext().getScope();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.operators;
|
||||
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.RemoveResourcesParameters;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ResourceList;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ServiceList;
|
||||
|
||||
/**
|
||||
* A Resources Operator that coordinates the removal of resources from the scope
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class RemoveResourcesOperator extends Operator {
|
||||
|
||||
protected final GCUBELog logger = new GCUBELog(this, ServiceContext.getContext());
|
||||
|
||||
private OperatorConfig configuration;
|
||||
|
||||
private RemoveResourcesParameters resourceList;
|
||||
|
||||
public RemoveResourcesOperator(OperatorConfig configuration, RemoveResourcesParameters resourceList) {
|
||||
this.configuration = configuration;
|
||||
this.resourceList = resourceList;
|
||||
}
|
||||
|
||||
public void exec() throws Exception {
|
||||
|
||||
// undeploy the services, if any
|
||||
ServiceList services = resourceList.getServices();
|
||||
if ((services == null) || (services.getService() == null) || (services.getService().length == 0)) {
|
||||
logger.warn("The list of services to undeploy is empty");
|
||||
} else {
|
||||
try {
|
||||
new DeployServiceOperator(configuration, services, ACTION.REMOVE).run();
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to activate the undeployment of the given service(s)", e);
|
||||
throw new Exception("Unable to activate the undeployment of the given service(s)", e);
|
||||
}
|
||||
}
|
||||
|
||||
//removes the resources from the PublishedScopeResource, if any
|
||||
ResourceList resources = resourceList.getResources();
|
||||
if ((resources == null) || (resources.getResource().length == 0))
|
||||
logger.warn("The list of resource to add is empty");
|
||||
else {
|
||||
try {
|
||||
new ScopedResourceManagerOperator(configuration, resources, ACTION.REMOVE).run();
|
||||
}catch (Exception e) {
|
||||
logger.error("Unable to manage the given resource(s)", e);
|
||||
throw new Exception("Unable to manage the given resource(s)", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,59 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.operators;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ResourceItem;
|
||||
import org.gcube.vremanagement.resourcemanager.stubs.resourcemanager.ResourceList;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
|
||||
|
||||
/**
|
||||
* Add and remove list of {@link ScopedResource}s to/from a given scope
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class ScopedResourceManagerOperator extends Operator {
|
||||
|
||||
|
||||
private ResourceList resources;
|
||||
|
||||
public ScopedResourceManagerOperator(OperatorConfig configuration, ResourceList resources, ACTION action) {
|
||||
this.configuration = configuration;
|
||||
this.resources = resources;
|
||||
this.action = action;
|
||||
}
|
||||
|
||||
public void exec() throws Exception {
|
||||
|
||||
Set<ScopedResource> toadd = new HashSet<ScopedResource>();
|
||||
Set<ScopedResource> toremove = new HashSet<ScopedResource>();
|
||||
ScopedResource sresource = null;
|
||||
for (ResourceItem resource : this.resources.getResource()) {
|
||||
try {
|
||||
sresource = ScopedResourceFactory.newResource(resource.getID(), resource.getType(), this.configuration.scope);
|
||||
if (this.action == ACTION.ADD) {
|
||||
logger.info("Adding resource " + sresource.getId() + " (" + sresource.getType() + ") to scope " + this.configuration.scope.toString());
|
||||
toadd.add(sresource);
|
||||
} else if (this.action == ACTION.REMOVE) {
|
||||
logger.info("Removing resource " + sresource.getId() + " (" + sresource.getType() + ") from scope " + this.configuration.scope.toString());
|
||||
toremove.add(sresource);
|
||||
}
|
||||
|
||||
//add the resource item to the session
|
||||
this.configuration.session.addResource(sresource);
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to manage the resource",e);
|
||||
}
|
||||
}
|
||||
if(toadd.size() > 0)
|
||||
configuration.scopeState.addResources(toadd);
|
||||
if(toremove.size() > 0)
|
||||
configuration.scopeState.removeResources(toremove);
|
||||
|
||||
this.configuration.session.save();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources;
|
||||
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.resources.GCUBECS;
|
||||
import org.gcube.common.core.resources.GCUBECSInstance;
|
||||
import org.gcube.common.core.resources.GCUBECollection;
|
||||
import org.gcube.common.core.resources.GCUBEExternalRunningInstance;
|
||||
import org.gcube.common.core.resources.GCUBEGenericResource;
|
||||
import org.gcube.common.core.resources.GCUBEMCollection;
|
||||
import org.gcube.common.core.resources.GCUBEResource;
|
||||
import org.gcube.common.core.resources.GCUBERuntimeResource;
|
||||
import org.gcube.common.core.resources.GCUBEService;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.common.core.informationsystem.client.AtomicCondition;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient;
|
||||
import org.gcube.common.core.informationsystem.client.ISTemplateQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBECSInstanceQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBECSQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBECollectionQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEExternalRIQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEGenericResourceQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEMCollectionQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBERuntimeResourceQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEServiceQuery;
|
||||
import org.gcube.common.core.informationsystem.publisher.ISPublisher;
|
||||
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Models a generic scoped {@link GCUBEResource}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class ScopedAnyResource extends ScopedResource {
|
||||
|
||||
@XStreamOmitField
|
||||
GCUBEResource profile = null;
|
||||
|
||||
@XStreamOmitField
|
||||
@SuppressWarnings("unchecked")
|
||||
Class profileClass = null;
|
||||
|
||||
protected ScopedAnyResource(String id, String type, GCUBEScope scope) {
|
||||
super(id, type, scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the profile of the Scoped Resource
|
||||
* @throws Exception if the resource was not found
|
||||
*/
|
||||
@Override
|
||||
@SuppressWarnings({ "unchecked", "rawtypes"})
|
||||
protected void find() throws Exception {
|
||||
try {
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
Class query = null;
|
||||
if (this.type.compareToIgnoreCase(GCUBECollection.TYPE) == 0) {query = GCUBECollectionQuery.class; profileClass = GCUBECollection.class;}
|
||||
else if (this.type.compareToIgnoreCase(GCUBEMCollection.TYPE) == 0) {query = GCUBEMCollectionQuery.class; profileClass = GCUBEMCollection.class;}
|
||||
else if (this.type.compareToIgnoreCase(GCUBEGenericResource.TYPE) == 0) {query = GCUBEGenericResourceQuery.class; profileClass = GCUBEGenericResource.class;}
|
||||
else if (this.type.compareToIgnoreCase(GCUBEExternalRunningInstance.TYPE) == 0) {query = GCUBEExternalRIQuery.class; profileClass = GCUBEExternalRunningInstance.class;}
|
||||
else if (this.type.compareToIgnoreCase(GCUBECS.TYPE) == 0) {query = GCUBECSQuery.class; profileClass = GCUBECS.class;}
|
||||
else if (this.type.compareToIgnoreCase(GCUBECSInstance.TYPE) == 0) {query = GCUBECSInstanceQuery.class; profileClass = GCUBECSInstance.class;}
|
||||
else if (this.type.compareToIgnoreCase(GCUBEService.TYPE) == 0) {query = GCUBEServiceQuery.class; profileClass = GCUBEService.class;}
|
||||
else if (this.type.compareToIgnoreCase(GCUBERuntimeResource.TYPE) == 0) {query = GCUBERuntimeResourceQuery.class; profileClass = GCUBERuntimeResource.class;}
|
||||
else throw new Exception("Unknown resource type: " + this.type);
|
||||
|
||||
ISTemplateQuery realquery = (ISTemplateQuery) client.getQuery(query);
|
||||
realquery.addAtomicConditions(new AtomicCondition("//ID",this.id));
|
||||
List <GCUBEResource> profiles = client.execute(realquery, GCUBEScope.getScope(this.scope));
|
||||
if ((profiles != null) && (profiles.size() > 0))
|
||||
this.profile = profiles.get(0);
|
||||
else
|
||||
// obviously, in the case of adding, the resource is not in the current scope, therefore we look upstairs (the enclosing scope)
|
||||
this.profile = (GCUBEResource) client.execute(realquery, GCUBEScope.getScope(this.scope).getEnclosingScope()).get(0);
|
||||
} catch (Exception e) {
|
||||
throw new Exception("unable to find the target resource (ID=" + id + "). Possible cause: " + e.getMessage(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void addToScope() throws ResourceNotFound, Exception {
|
||||
this.findResource();
|
||||
getLogger().debug("Adding scope to resource profile");
|
||||
try {
|
||||
profile.addScope(this.getScope());
|
||||
//republish the resource
|
||||
ISPublisher publisher = GHNContext.getImplementation(ISPublisher.class);
|
||||
publisher.updateGCUBEResource(this.profile, ServiceContext.getContext().getScope(), ServiceContext.getContext());
|
||||
//republish also in the infrastructure scope, if needed
|
||||
if (ServiceContext.getContext().getScope().getType() == GCUBEScope.Type.VO) {
|
||||
if (this.profile.getScopes().values().contains(ServiceContext.getContext().getScope().getEnclosingScope())) {
|
||||
publisher.updateGCUBEResource(this.profile, ServiceContext.getContext().getScope().getEnclosingScope(), ServiceContext.getContext());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.noHopeForMe("Failed to add the scope ("+ this.getScope()+") to resource " + this.getId(), e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFromScope() throws ResourceNotFound, Exception {
|
||||
this.findResource();
|
||||
getLogger().debug("Removing scope from resource profile");
|
||||
try {
|
||||
profile.removeScope(this.getScope());
|
||||
//republish the resource
|
||||
ISPublisher publisher = GHNContext.getImplementation(ISPublisher.class);
|
||||
publisher.updateGCUBEResource(this.profile, ServiceContext.getContext().getScope(), ServiceContext.getContext());
|
||||
//republish also in the infrastructure scope, if needed
|
||||
if (ServiceContext.getContext().getScope().getType() == GCUBEScope.Type.VO) {
|
||||
if (this.profile.getScopes().values().contains(ServiceContext.getContext().getScope().getEnclosingScope())) {
|
||||
publisher.updateGCUBEResource(this.profile, ServiceContext.getContext().getScope().getEnclosingScope(), ServiceContext.getContext());
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.noHopeForMe("Failed to remove the scope ("+ this.getScope()+") from resource " + this.getId(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,397 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.resources.GCUBEService;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.vremanagement.deployer.stubs.common.PackageInfo;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.SoftwareGatewayRequest;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Dependency;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Service;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.operators.Operator.ACTION;
|
||||
|
||||
/**
|
||||
*
|
||||
* Models a scoped {@link GCUBEService}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class ScopedDeployedService extends ScopedResource {
|
||||
|
||||
public static final String TYPE = GCUBEService.TYPE;
|
||||
|
||||
/** Target port-type name. */
|
||||
protected static final String REPOSITORY_ENDPOINT = "gcube/vremanagement/softwarerepository/SoftwareRepository";
|
||||
|
||||
/** Target service name. */
|
||||
protected static final String REPOSITORY_NAME = "SoftwareRepository";
|
||||
|
||||
/** Target service class. */
|
||||
protected static final String REPOSITORY_CLASS = "VREManagement";
|
||||
|
||||
/** Timeout in millisecs for the channel with the Software Repository instance */
|
||||
protected static final int TIMEOUT = 600000;
|
||||
|
||||
/** resolved dependencies */
|
||||
private List<Dependency> resolved = new ArrayList<Dependency>();
|
||||
|
||||
/** missing dependency */
|
||||
private List<Dependency> missing = new ArrayList<Dependency>();
|
||||
|
||||
/** the packages deployed for this service*/
|
||||
private Map <String, List<Dependency>> node2packages = new HashMap<String, List<Dependency>>();
|
||||
|
||||
/** the packages deployed for this service*/
|
||||
private Map <String, List<Dependency>> node2missing = new HashMap<String, List<Dependency>>();
|
||||
|
||||
private Service service;
|
||||
|
||||
private String lastActivityOnGHN;
|
||||
|
||||
//the target ghn(s)
|
||||
private List<VirtualNode> virtualNodes = new ArrayList<VirtualNode>();
|
||||
|
||||
/** maps node with the scope used when deploying there */
|
||||
private Map<String, String> node2scope = new HashMap<String, String>();
|
||||
|
||||
/** maps RI id with the ghn id (where the instance is deployed on*/
|
||||
private Map<String, String> ri2ghn = new HashMap<String, String>();
|
||||
|
||||
protected ScopedDeployedService(String id, GCUBEScope scope) {
|
||||
super(id, TYPE, scope);
|
||||
}
|
||||
|
||||
public void setSourceServiceName(Service service) {
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
public Service getSourceService() {
|
||||
return this.service;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of resolved dependencies when the deployment was performed
|
||||
* on a specific node
|
||||
*
|
||||
* @param ghnid the ID of the node
|
||||
* @return the resolved dependencies
|
||||
*/
|
||||
public List<Dependency> getResolvedDependencies(String ghnid) {
|
||||
if (node2packages.get(ghnid) == null)
|
||||
return Collections.emptyList();
|
||||
return Collections.unmodifiableList(node2packages.get(ghnid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of resolved dependencies to be used in the next deployment
|
||||
*
|
||||
* @return the resolved dependencies
|
||||
*/
|
||||
public List<Dependency> getLastResolvedDependencies() {
|
||||
return this.resolved;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of resolved dependencies to be used in the next deployment
|
||||
*
|
||||
* @param dependencies the resolved dependencies
|
||||
*/
|
||||
public void setResolvedDependencies(List<Dependency> dependencies) {
|
||||
this.resolved = dependencies;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of missing dependencies when the deployment was performed
|
||||
* on a specific node
|
||||
*
|
||||
* @param ghnid the ID of the node
|
||||
* @return the missing dependencies
|
||||
*/
|
||||
public List<Dependency> getMissingDependencies(String ghnid) {
|
||||
if (node2missing.get(ghnid) == null)
|
||||
return Collections.emptyList();
|
||||
return Collections.unmodifiableList(node2missing.get(ghnid));
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of missing dependencies for the last (failed) deployment
|
||||
*
|
||||
* @return the missing dependencies
|
||||
*/
|
||||
public List<Dependency> getLastMissingDependencies() {
|
||||
return this.missing;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the list of missing dependencies for the next deployment
|
||||
*
|
||||
* @param dependencies the missign dependencies
|
||||
*/
|
||||
public void setMissingDependencies(List<Dependency> dependencies) {
|
||||
///this.getLogger().trace("Setting missing deps " + dependencies.size());
|
||||
missing= dependencies;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void find() throws Exception {
|
||||
//looks for the service and its deps in the Software Repository
|
||||
SoftwareGatewayRequest request = new SoftwareGatewayRequest();
|
||||
request.addService(this);
|
||||
this.setErrorMessage(""); //empty any previous message
|
||||
try {
|
||||
request.send();
|
||||
if (this.resolved.size() == 0) {
|
||||
this.success = false;
|
||||
this.setErrorMessage("Invalid list of dependecies retrieved from the Software Repository");
|
||||
} else if (this.missing.size() > 0) {//ops, some deps are missing!
|
||||
this.success = false;
|
||||
this.setErrorMessage("The service cannot be deployed due to one or more missing dependencies: " + this.missing);
|
||||
} else {
|
||||
this.success = true;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
this.success= false;
|
||||
this.setErrorMessage("Unable to resolve the list of dependencies for this service " + e.getMessage());
|
||||
getLogger().error("Unable to resolve the list of deps for " + this.service, e);
|
||||
throw new Exception("Unable to resolve the list of dependencies for " + this.service, e);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addToScope() throws ResourceNotFound, Exception {
|
||||
logger.trace("This service belongs to " + this.scope);
|
||||
if (!this.isSuccess()) {
|
||||
this.noHopeForMe(this.getErrorMessage(),new Exception());
|
||||
}
|
||||
|
||||
if ((this.lastActivityOnGHN == null) || (this.lastActivityOnGHN.compareTo("")==0)) {
|
||||
this.noHopeForMe("Unable to find a suitable target gHN where to deploy the service",new Exception());
|
||||
}
|
||||
this.action = ACTION.ADD;
|
||||
this.setErrorMessage(""); //empty any previous message
|
||||
Exception lastException = null;
|
||||
//deploy the service
|
||||
List<VirtualNode> nodesToRemove = new ArrayList<VirtualNode>();
|
||||
for (VirtualNode node : this.virtualNodes) {
|
||||
try {
|
||||
node.deploy(this.getScope());
|
||||
//store packages for future undeployment and reporting purposes
|
||||
List<Dependency> resolvedPackages = new ArrayList<Dependency>();
|
||||
for (Dependency dep : this.resolved)
|
||||
resolvedPackages.add(dep);
|
||||
node2packages.put(node.getID(), resolvedPackages);
|
||||
//store missing packages for reporting purposes
|
||||
List<Dependency> missingPackages = new ArrayList<Dependency>();
|
||||
for (Dependency dep : this.missing)
|
||||
missingPackages.add(dep);
|
||||
if (node2missing == null) {
|
||||
logger.trace("node2missing is null");
|
||||
node2missing = new HashMap<String, List<Dependency>>(); // this is here for backwards compatibility
|
||||
}
|
||||
node2missing.put(node.getID(), missingPackages);
|
||||
} catch (Exception e) {
|
||||
nodesToRemove.add(node);
|
||||
logger.error("Failed to deploy on " + node.getID(), e);
|
||||
logger.info("Virtual Node " + node.toString() + " will be removed from the queue");
|
||||
lastException=e;
|
||||
}
|
||||
|
||||
}
|
||||
this.missing.clear();
|
||||
this.resolved.clear();
|
||||
|
||||
if (nodesToRemove.size() > 0 ) {
|
||||
this.virtualNodes.removeAll(nodesToRemove);
|
||||
this.noHopeForMe("Unable to contact the target gHN ("+ this.lastActivityOnGHN +") where to deploy the service",lastException);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void removeFromScope() throws ResourceNotFound, Exception {
|
||||
logger.trace("This service belongs to " + this.scope);
|
||||
if (!this.isSuccess()) {
|
||||
//TODO: could we undeploy static packages here?
|
||||
this.noHopeForMe(this.getErrorMessage(),new Exception());
|
||||
}
|
||||
|
||||
if ((this.lastActivityOnGHN == null) || (this.lastActivityOnGHN.compareTo("")==0)) {
|
||||
this.noHopeForMe("Unable to find a valid target gHN where to undeploy the service", new Exception());
|
||||
}
|
||||
this.setErrorMessage(""); //empty any previous message
|
||||
//undeploy the service from all the virtual nodes where it was deployed (if any)
|
||||
this.action = ACTION.REMOVE;
|
||||
try {
|
||||
for (VirtualNode node : this.virtualNodes) {
|
||||
try {
|
||||
if (node2scope.containsKey(node.getID()))
|
||||
node.undeploy(GCUBEScope.getScope(node2scope.get(node.getID())));
|
||||
else
|
||||
node.undeploy(this.getScope()); //try the service's scope
|
||||
} catch (Exception e) {
|
||||
this.noHopeForMe("Failed to undeploy from "+ node ,e);
|
||||
}
|
||||
}
|
||||
this.virtualNodes.clear();
|
||||
} catch (Exception e) {
|
||||
this.noHopeForMe("Unable to contact the target gHN ("+ this.lastActivityOnGHN +") where to undeploy the service, deployer says" + e.getMessage() ,e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the undeployment of all the instances of this service from scope
|
||||
*
|
||||
* @throws Exception if the operation fails
|
||||
*/
|
||||
public void scheduleUndeploy() {
|
||||
for (VirtualNode node : this.virtualNodes)
|
||||
scheduleUndeploy(node);
|
||||
}
|
||||
|
||||
/**
|
||||
* Schedules the undeployment of an instance of this service from the node
|
||||
*
|
||||
* @param node the node from where to undeploy the service
|
||||
* @throws Exception if the operation fails
|
||||
*/
|
||||
public void scheduleUndeploy(VirtualNode node) {
|
||||
getLogger().info("Scheduling undeployment of service "+ this.service+ " from GHN " + this.lastActivityOnGHN);
|
||||
//notify the node to operate in the scope previously used for the deployment
|
||||
this.checkNode2Scope();
|
||||
if (node2scope.containsKey(node.getID())) //it has to be in, but it couldn't if the service was deployed from a previous (version < 1.1)RM instance
|
||||
node.setWorkingScope(GCUBEScope.getScope(node2scope.get(node.getID())));
|
||||
//prepare the input list of packagesToAdd for that GHN
|
||||
List<Dependency> deps = node2packages.get(node.getID());
|
||||
if (deps == null)
|
||||
return;
|
||||
Set<PackageInfo> packages = new HashSet<PackageInfo>();
|
||||
for (int i = 0; i < deps.size(); i++) {
|
||||
PackageInfo p = new PackageInfo();
|
||||
p.setServiceName(deps.get(i).getService().getName());
|
||||
p.setServiceClass(deps.get(i).getService().getClazz());
|
||||
p.setServiceVersion(deps.get(i).getService().getVersion());
|
||||
p.setVersion(deps.get(i).getVersion());
|
||||
p.setName(deps.get(i).getName());
|
||||
getLogger().trace("Adding Package to undeployment request: " + deps.get(i));
|
||||
packages.add(p);
|
||||
}
|
||||
node.setPackagesToRemove(packages);
|
||||
this.lastActivityOnGHN = node.getID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Undeploys any instances of this service from the given gHN
|
||||
*
|
||||
* @param lastActivityOnGHN the id of the gHN from where to undeploy the service
|
||||
* @throws Exception
|
||||
*/
|
||||
public void removeFromScope(String ghnID) throws VirtualNode.NoGHNFoundException, Exception {
|
||||
logger.trace("This service belongs to " + this.scope);
|
||||
this.action = ACTION.REMOVE;
|
||||
for (VirtualNode node : this.virtualNodes)
|
||||
if (node.getID().compareToIgnoreCase(ghnID) == 0) {
|
||||
checkNode2Scope();
|
||||
if (node2scope.containsKey(ghnID))
|
||||
node.undeploy(GCUBEScope.getScope(node2scope.get(ghnID)));
|
||||
else
|
||||
node.undeploy(this.getScope()); //try the service's scope
|
||||
this.virtualNodes.remove(node);
|
||||
return;
|
||||
}
|
||||
this.noHopeForMe("Unable to find the gHN with id " + this.lastActivityOnGHN +
|
||||
" to undeploy the instance of the " + this.service, new VirtualNode.NoGHNFoundException(""));
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the GHN where the service will be deployed
|
||||
*
|
||||
* @param node the target GHN
|
||||
*/
|
||||
public void setTargetGHN(VirtualNode node) {
|
||||
getLogger().info("Using GHN " + node.getID() + " for " + this);
|
||||
|
||||
Set<PackageInfo> packages = new HashSet<PackageInfo>();
|
||||
//prepare the input list of packagesToAdd for that GHN
|
||||
List<Dependency> deps = this.resolved;
|
||||
for (int i = 0; i < deps.size(); i++) {
|
||||
PackageInfo p = new PackageInfo();
|
||||
p.setServiceName(deps.get(i).getService().getName());
|
||||
p.setServiceClass(deps.get(i).getService().getClazz());
|
||||
p.setServiceVersion(deps.get(i).getService().getVersion());
|
||||
p.setVersion(deps.get(i).getVersion());
|
||||
p.setName(deps.get(i).getName()); //packageName
|
||||
getLogger().trace("Adding Package to deployment request: " + deps.get(i));
|
||||
packages.add(p);
|
||||
}
|
||||
node.setPackagesToAdd(packages);
|
||||
this.checkNode2Scope();//for backward compatibility (version <= 1.1)
|
||||
node2scope.put(node.getID(), node.getWorkingScope().toString());
|
||||
this.virtualNodes.add(node);
|
||||
this.lastActivityOnGHN = node.getID();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the target gHN
|
||||
* @return the ID of the target gHN
|
||||
*/
|
||||
public String getTargetGHNID() {
|
||||
return lastActivityOnGHN; //this.virtualNodes.size() > 0 ? this.virtualNodes.get(0).getID() : "";
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the ID of the target gHN
|
||||
* @return the ID of the target gHN
|
||||
*/
|
||||
public String getTargetGHN() {
|
||||
return this.virtualNodes.size() > 0 ? this.virtualNodes.get(0).getID() : "";
|
||||
}
|
||||
|
||||
|
||||
public void setRIonGHN(String ri, String ghn) {
|
||||
this.ri2ghn.put(ri, ghn);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the callback ID from now on for all the service's operations
|
||||
* @param id the callback ID
|
||||
*/
|
||||
public void setCallbackID(String id) {
|
||||
for (VirtualNode node : this.virtualNodes)
|
||||
node.setCallbackID(id);
|
||||
|
||||
}
|
||||
/**
|
||||
* Gets the list of {@link VirtualNode}s where the service is actually deployed within this scope
|
||||
* @return the list of {@link VirtualNode}s
|
||||
*/
|
||||
public List<VirtualNode> getNodes() {
|
||||
return this.virtualNodes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of times the resource is searched in the IS before to declare it lost
|
||||
* @return the number of attempts to do
|
||||
*/
|
||||
@Override
|
||||
protected int getMaxFindAttempts(){
|
||||
return 3;
|
||||
}
|
||||
|
||||
private void checkNode2Scope(){
|
||||
//this is for backward compatibility, if the obj is loaded from an old serialization
|
||||
//node2scope could not be initialized
|
||||
if (this.node2scope == null)
|
||||
this.node2scope = new HashMap<String, String>();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,129 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.axis.message.addressing.Address;
|
||||
import org.apache.axis.message.addressing.EndpointReferenceType;
|
||||
import org.gcube.common.core.contexts.GCUBERemotePortTypeContext;
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.informationsystem.client.AtomicCondition;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient.ISUnsupportedQueryException;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEGHNQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBERIQuery;
|
||||
import org.gcube.common.core.resources.GCUBEHostingNode;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.vremanagement.ghnmanager.stubs.AddScopeInputParams;
|
||||
import org.gcube.common.vremanagement.ghnmanager.stubs.GHNManagerPortType;
|
||||
import org.gcube.common.vremanagement.ghnmanager.stubs.service.GHNManagerServiceAddressingLocator;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
|
||||
/**
|
||||
* Models a scoped {@link GCUBEHostingNode}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class ScopedGHN extends ScopedResource {
|
||||
|
||||
public static final String TYPE = GCUBEHostingNode.TYPE;
|
||||
|
||||
private String nodename = "";
|
||||
|
||||
private transient EndpointReferenceType ghnEpr;
|
||||
|
||||
protected ScopedGHN(String id, GCUBEScope scope) {
|
||||
super(id, TYPE, scope);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void addToScope() throws ResourceNotFound, Exception {
|
||||
if (this.ghnEpr == null)
|
||||
this.findResource();
|
||||
//contact the GHNManager to add the GHN to the given scope
|
||||
EndpointReferenceType endpoint = new EndpointReferenceType();
|
||||
try {
|
||||
endpoint.setAddress(new Address("http://"+ this.nodename +"/wsrf/services/gcube/common/vremanagement/GHNManager"));
|
||||
GHNManagerServiceAddressingLocator locator = new GHNManagerServiceAddressingLocator();
|
||||
GHNManagerPortType pt = GCUBERemotePortTypeContext.getProxy(locator.getGHNManagerPortTypePort(endpoint),
|
||||
ServiceContext.getContext().getScope().getEnclosingScope(), ServiceContext.getContext());
|
||||
AddScopeInputParams params = new AddScopeInputParams();
|
||||
params.setScope(this.scope.toString());
|
||||
params.setMap(""); //eventually, set here the new Service Map
|
||||
pt.addScope(params);
|
||||
|
||||
} catch (Exception e) {
|
||||
this.noHopeForMe("Failed to add GHN to scope " + scope.toString(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void find() throws Exception {
|
||||
ISClient client = null;
|
||||
GCUBEGHNQuery query = null;
|
||||
try {
|
||||
client = GHNContext.getImplementation(ISClient.class);
|
||||
query = client.getQuery(GCUBEGHNQuery.class);
|
||||
query.addAtomicConditions(new AtomicCondition("/ID/text()", this.id));
|
||||
} catch (Exception e) {
|
||||
throw new Exception("unable to query of the target GHN (ID=" + this.id + ")", e);
|
||||
}
|
||||
try {
|
||||
List<GCUBEHostingNode> hostingNodes = client.execute(query, ServiceContext.getContext().getScope());
|
||||
this.nodename = hostingNodes.get(0).getNodeDescription().getName();
|
||||
this.hostedOn = nodename;
|
||||
this.ghnEpr = this.loadGHNmanager(hostingNodes.get(0).getID(), client, ServiceContext.getContext().getScope());
|
||||
} catch (Exception e) {
|
||||
//try in the enclosing scope
|
||||
try {
|
||||
List<GCUBEHostingNode> hostingNodes = client.execute(query, ServiceContext.getContext().getScope().getEnclosingScope());
|
||||
this.nodename = hostingNodes.get(0).getNodeDescription().getName();
|
||||
this.hostedOn = nodename;
|
||||
this.ghnEpr = this.loadGHNmanager(hostingNodes.get(0).getID(), client,ServiceContext.getContext().getScope().getEnclosingScope());
|
||||
} catch (Exception ei) {
|
||||
throw new Exception("unable to find the target GHN (ID=" + this.id + ")", e);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void removeFromScope() throws ResourceNotFound, Exception {
|
||||
if (this.ghnEpr == null)
|
||||
this.findResource();
|
||||
//EndpointReferenceType endpoint = new EndpointReferenceType();
|
||||
try {
|
||||
//endpoint.setAddress(new Address("http://"+ this.nodename +"/wsrf/services/gcube/common/vremanagement/GHNManager"));
|
||||
GHNManagerServiceAddressingLocator locator = new GHNManagerServiceAddressingLocator();
|
||||
GHNManagerPortType pt = GCUBERemotePortTypeContext.getProxy(locator.getGHNManagerPortTypePort(this.ghnEpr),
|
||||
ServiceContext.getContext().getScope().getEnclosingScope(), ServiceContext.getContext());
|
||||
pt.removeScope(this.scope.toString());
|
||||
} catch (Exception e) {
|
||||
this.noHopeForMe("Failed to remove GHN from scope " + scope.toString(), e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for the GHN manager's endpoint to contact
|
||||
* @param id the identifier of the gHN
|
||||
* @param client the ISClient instance to use
|
||||
* @param scope
|
||||
* @return the endpoint reference of gHNManager's portType to contact
|
||||
* @throws Exception if the search fails
|
||||
*/
|
||||
private EndpointReferenceType loadGHNmanager(String id, ISClient client, GCUBEScope scope) throws Exception {
|
||||
//looks for the GHN manager's endpoint to contact
|
||||
GCUBERIQuery riquery = client.getQuery(GCUBERIQuery.class);
|
||||
riquery.addAtomicConditions(new AtomicCondition("//GHN/@UniqueID", id),
|
||||
new AtomicCondition("//ServiceClass", "VREManagement"),
|
||||
new AtomicCondition("//ServiceName", "GHNManager"));
|
||||
List<GCUBERunningInstance> results = client.execute(riquery,scope);
|
||||
return results.get(0).getAccessPoint().getEndpoint("gcube/common/vremanagement/GHNManager");
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,332 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources;
|
||||
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.gcube.common.core.resources.GCUBEResource;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.operators.Operator.ACTION;
|
||||
import com.thoughtworks.xstream.annotations.XStreamOmitField;
|
||||
|
||||
/**
|
||||
* An abstract model for a scoped {@link GCUBEResource}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public abstract class ScopedResource {
|
||||
|
||||
/** Object getLogger() */
|
||||
@XStreamOmitField
|
||||
protected GCUBELog logger;
|
||||
|
||||
/** the resource identifier*/
|
||||
protected String id;
|
||||
|
||||
/** the resource type */
|
||||
protected String type;
|
||||
|
||||
/** where the resource is hosted on, it makes sense for RI, GHN*/
|
||||
protected String hostedOn = "";
|
||||
|
||||
/** result of the last operation performed on the resource */
|
||||
protected boolean success;
|
||||
|
||||
/** the error message, if any, from the last operation */
|
||||
protected String errorMessage = "";
|
||||
|
||||
protected String scope;
|
||||
|
||||
/** the last action performed on the resource*/
|
||||
protected ACTION action;
|
||||
|
||||
/** Last modification time stamp*/
|
||||
protected Date lastModificationTime;
|
||||
|
||||
/** Last modification time stamp*/
|
||||
protected Date jointTime;
|
||||
|
||||
/** the current status of the resource */
|
||||
protected STATUS status;
|
||||
|
||||
/** resource's legal statuses */
|
||||
public static enum STATUS {
|
||||
CREATED() {public List<STATUS> previous() {return Collections.emptyList();}},
|
||||
ADDREQUESTED() {public List<STATUS> previous() {return Collections.unmodifiableList(Arrays.asList(CREATED));}},
|
||||
ADDED() {public List<STATUS> previous() {return Collections.unmodifiableList(Arrays.asList(ADDREQUESTED));}},
|
||||
PUBLISHED() {public List<STATUS> previous() {return Collections.unmodifiableList(Arrays.asList(ADDED));}},
|
||||
REMOVEREQUESTED() {public List<STATUS> previous() {return Collections.unmodifiableList(Arrays.asList(ADDED, PUBLISHED));}},
|
||||
REMOVED() {public List<STATUS> previous() {return Collections.unmodifiableList(Arrays.asList(REMOVEREQUESTED));}},
|
||||
UNPUBLISHED () {public List<STATUS> previous() {return Collections.unmodifiableList(Arrays.asList(REMOVED));}},
|
||||
LOST () {public List<STATUS> previous() {return Collections.unmodifiableList(Arrays.asList(REMOVED,REMOVEREQUESTED,ADDED,PUBLISHED,CREATED,UNPUBLISHED));}};
|
||||
|
||||
abstract public List<STATUS> previous();
|
||||
}
|
||||
|
||||
public ScopedResource(String id, String type, GCUBEScope scope) {
|
||||
this.id = id;
|
||||
this.type = type;
|
||||
this.scope = scope.toString();
|
||||
this.status = STATUS.CREATED;
|
||||
}
|
||||
|
||||
/**
|
||||
* Custom
|
||||
*
|
||||
* @throws ResourceNotFound if it is impossible to locate the resource
|
||||
*/
|
||||
protected abstract void find() throws Exception;;
|
||||
|
||||
/**
|
||||
* Looks for the resource in the infrastructure
|
||||
*
|
||||
* @throws ResourceNotFound if it is impossible to locate the resource
|
||||
*/
|
||||
public synchronized void findResource() throws ResourceNotFound {
|
||||
this.setErrorMessage(""); //empty any previous message
|
||||
int max_attempts = this.getMaxFindAttempts(); //try to find the resource 5 times
|
||||
int i = 0;
|
||||
while (true) {
|
||||
try {
|
||||
this.find();
|
||||
this.success = true;
|
||||
break;
|
||||
} catch (Exception e) {
|
||||
logger.warn("Can't find resource "+ this + " on the IS");
|
||||
if (i++ <= max_attempts) {
|
||||
logger.warn("try again in 5 secs");
|
||||
try {Thread.sleep(5000);} catch (InterruptedException e1) {}
|
||||
continue;
|
||||
}
|
||||
else {
|
||||
this.noHopeForMe("Can't find resource "+ this + " on the IS", new ResourceNotFound(e));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void doAction(ACTION action) throws ResourceNotFound, Exception {
|
||||
this.action = action;
|
||||
switch (action) {
|
||||
case ADD: this.addToScope(); this.setJointTime(Calendar.getInstance().getTime()); this.success= true; break;
|
||||
case REMOVE: this.removeFromScope(); this.success= true; break;
|
||||
default: break;
|
||||
}
|
||||
this.setChanged();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the resource to the scope
|
||||
* @throws Exception if the operation fails
|
||||
* @throws ResourceNotFound if the resource does not exist in the infrastructure
|
||||
*/
|
||||
protected abstract void addToScope() throws ResourceNotFound, Exception;
|
||||
|
||||
|
||||
/**
|
||||
* Removes the resource from the scope
|
||||
* @throws Exception if the operation fails
|
||||
* @throws ResourceNotFound if the resource does not exist in the infrastructure
|
||||
*/
|
||||
protected abstract void removeFromScope() throws ResourceNotFound, Exception;
|
||||
|
||||
|
||||
/**
|
||||
* @return the resource ID
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the resource type
|
||||
*/
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the scope
|
||||
*/
|
||||
public final GCUBEScope getScope() {
|
||||
return GCUBEScope.getScope(this.scope);
|
||||
}
|
||||
|
||||
protected final void setScope(GCUBEScope scope) {
|
||||
this.scope = scope.toString();
|
||||
}
|
||||
/**
|
||||
* @return the action
|
||||
*/
|
||||
public ACTION getAction() {
|
||||
return action;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the errorMessage
|
||||
*/
|
||||
public String getErrorMessage() {
|
||||
return errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param errorMessage the errorMessage to set
|
||||
*/
|
||||
public void setErrorMessage(String errorMessage) {
|
||||
this.success = false;
|
||||
this.errorMessage = errorMessage;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the time the resource joined the scope
|
||||
* @param time the new joint time
|
||||
*/
|
||||
public void setJointTime(Date time) {
|
||||
this.jointTime = time;
|
||||
|
||||
}
|
||||
|
||||
private void setChanged() {
|
||||
this.setLastModificationTime(Calendar.getInstance().getTime());
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the success
|
||||
*/
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the node on which the Scope is hosted
|
||||
*/
|
||||
public String getHostedOn() {
|
||||
return hostedOn;
|
||||
}
|
||||
|
||||
public void setHostedON(String hostedOn) {
|
||||
this.hostedOn = hostedOn;
|
||||
}
|
||||
|
||||
public Date getJointTime() {
|
||||
if (jointTime == null)
|
||||
jointTime = Calendar.getInstance().getTime();
|
||||
return jointTime;
|
||||
}
|
||||
|
||||
public Date getLastModificationTime() {
|
||||
if (lastModificationTime == null)
|
||||
this.setChanged();
|
||||
return lastModificationTime;
|
||||
}
|
||||
|
||||
private void setLastModificationTime(Date lastModificationTime) {
|
||||
this.lastModificationTime = lastModificationTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the status
|
||||
*/
|
||||
public STATUS getStatus() {
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param status the status to set
|
||||
*/
|
||||
public synchronized void setStatus(STATUS status) {
|
||||
getLogger().trace(this.toString()+ ": status set to " + status);
|
||||
this.status = status;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of times the resource is searched in the IS before to declare it lost
|
||||
* @return
|
||||
*/
|
||||
protected int getMaxFindAttempts(){
|
||||
return 5;
|
||||
}
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
ScopedResource other = (ScopedResource) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null)
|
||||
return false;
|
||||
} else if (!id.equals(other.id))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gives up the operation on the resource
|
||||
* @param message the error message to return
|
||||
* @param e the exception that generates the hopeless
|
||||
* @throws E the source exception
|
||||
*/
|
||||
protected <E extends Exception> void noHopeForMe(String message, E e) throws E {
|
||||
getLogger().error(this.toString() +": Unable to manage the resource " + message ,e);
|
||||
this.setStatus(STATUS.LOST);
|
||||
this.success = false;
|
||||
this.setErrorMessage(message);
|
||||
throw e;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Resource [id=" + id
|
||||
+ ", type=" + type
|
||||
+ ", timestamp=" + lastModificationTime
|
||||
+ ", scope=" + scope
|
||||
+ ", status=" + status
|
||||
+ " hostedOn=" + hostedOn + "]";
|
||||
}
|
||||
|
||||
|
||||
protected GCUBELog getLogger() {
|
||||
if (this.logger == null)
|
||||
logger=new GCUBELog(this);
|
||||
return logger;
|
||||
}
|
||||
|
||||
/** Unable to find the resource in the infrastructure*/
|
||||
public class ResourceNotFound extends Exception {
|
||||
public ResourceNotFound(String message) {super(message);}
|
||||
|
||||
public ResourceNotFound(Exception e) {
|
||||
super(e);
|
||||
}
|
||||
|
||||
private static final long serialVersionUID = -6111206113583291172L;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,85 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources;
|
||||
|
||||
import org.gcube.common.core.resources.GCUBEHostingNode;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.resources.GCUBEService;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ScopeState;
|
||||
|
||||
public class ScopedResourceFactory {
|
||||
|
||||
protected static GCUBELog logger = new GCUBELog(ScopedResourceFactory.class);
|
||||
|
||||
private static ScopeState scopeState = null;
|
||||
|
||||
public static void setResourceList(final ScopeState list) {
|
||||
scopeState = list;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link ScopedResource}
|
||||
*
|
||||
* @param id the gCube Resource identifier
|
||||
* @param type the resource type
|
||||
* @param scope the {@link GCUBEScope} assigned to the resource
|
||||
* @return the resource
|
||||
*/
|
||||
public static ScopedResource newResource(String id, String type, GCUBEScope scope) throws Exception {
|
||||
|
||||
if (scopeState != null) {
|
||||
if (scopeState.containsResource(id)) {
|
||||
logger.trace("Taking resource " + id + " from the scope state");
|
||||
scopeState.getResource(id).setScope(scope);
|
||||
return scopeState.getResource(id);
|
||||
}
|
||||
}
|
||||
if ((id == null) || (id.compareTo("") == 0))
|
||||
throw new Exception("invalid resource id specified");
|
||||
|
||||
if ((type == null) || (type.compareTo("") == 0))
|
||||
throw new Exception("invalid resource type specified");
|
||||
|
||||
ScopedResource sresource = null;
|
||||
logger.trace("Creating a new resource " + id + "");
|
||||
if (type.compareToIgnoreCase(GCUBEHostingNode.TYPE) == 0)
|
||||
sresource = new ScopedGHN(id, scope);
|
||||
else if (type.compareToIgnoreCase(GCUBERunningInstance.TYPE) == 0)
|
||||
sresource = new ScopedRunningInstance(id, scope);
|
||||
else if (type.compareToIgnoreCase(GCUBEService.TYPE) == 0)
|
||||
sresource = new ScopedDeployedService(id, scope);
|
||||
else
|
||||
sresource = new ScopedAnyResource(id, type, scope);
|
||||
|
||||
return sresource;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the service that originates the RI, if any
|
||||
* @param scopedRunningInstance
|
||||
* @return the service
|
||||
*/
|
||||
public static ScopedDeployedService getRelatedService(
|
||||
ScopedRunningInstance scopedRunningInstance) throws ServiceNotFoundException {
|
||||
for (ScopedResource resource : scopeState.getResourcesByType(ScopedDeployedService.TYPE)) {
|
||||
if (resource == null) continue;
|
||||
try {
|
||||
ScopedDeployedService service = (ScopedDeployedService)resource;
|
||||
if ((service.getSourceService().getClazz().compareToIgnoreCase(scopedRunningInstance.getSourceServiceClass())==0)
|
||||
&& (service.getSourceService().getName().compareToIgnoreCase(scopedRunningInstance.getSourceServiceName())==0)) {
|
||||
logger.debug("Source service found for RI " + scopedRunningInstance);
|
||||
return service;
|
||||
}
|
||||
}catch (Exception e ) {
|
||||
logger.warn("An error occurred when looking for the source service for RI "+ scopedRunningInstance + ", error message: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
logger.error("Unable to find a source service for " + scopedRunningInstance);
|
||||
throw new ServiceNotFoundException();
|
||||
}
|
||||
|
||||
/** Service not found exception, it occurs when a RI was not deployed by this RM instance*/
|
||||
public static class ServiceNotFoundException extends Exception {
|
||||
private static final long serialVersionUID = 3904279081090871340L;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,234 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources;
|
||||
|
||||
import java.io.StringReader;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.axis.message.addressing.EndpointReferenceType;
|
||||
import org.gcube.common.core.contexts.GCUBERemotePortTypeContext;
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.informationsystem.client.AtomicCondition;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient;
|
||||
import org.gcube.common.core.informationsystem.client.QueryParameter;
|
||||
import org.gcube.common.core.informationsystem.client.XMLResult;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEGHNQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEGenericQuery;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBERIQuery;
|
||||
import org.gcube.common.core.resources.GCUBEHostingNode;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.vremanagement.ghnmanager.stubs.GHNManagerPortType;
|
||||
import org.gcube.common.vremanagement.ghnmanager.stubs.ScopeRIParams;
|
||||
import org.gcube.common.vremanagement.ghnmanager.stubs.service.GHNManagerServiceAddressingLocator;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory.ServiceNotFoundException;
|
||||
|
||||
/**
|
||||
* A scoped {@link GCUBERunningInstance}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class ScopedRunningInstance extends ScopedResource {
|
||||
|
||||
public static final String TYPE = GCUBERunningInstance.TYPE;
|
||||
|
||||
private String hostingNodeName = "";
|
||||
|
||||
/** data of the service from which the RI was generated */
|
||||
private ServiceData sourceService = new ServiceData();;
|
||||
|
||||
/** ghn ID of the node hosting the RI */
|
||||
private String hostedOnID = "";
|
||||
|
||||
/** Scopes the instance belongs to */
|
||||
private List<String> scopes;
|
||||
|
||||
private transient EndpointReferenceType ghnEpr;
|
||||
|
||||
protected ScopedRunningInstance(String id, GCUBEScope scope, String ... hostedOn) {
|
||||
super(id, TYPE, scope);
|
||||
if ((hostedOn != null) && (hostedOn.length > 0))
|
||||
this.hostedOn = hostedOn[0];
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void find() throws Exception {
|
||||
//looks for the RI to manage
|
||||
try {
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
//we cannot use here the GCUBERunningInstanceQuery because it returns only ready instances,
|
||||
//we need to find a RI, no matter in which state it is
|
||||
GCUBEGenericQuery query = client.getQuery("GCUBEResourceQuery");
|
||||
query.addParameters(new QueryParameter("FILTER", "$result/ID/text()/string() eq \""+id+"\""),
|
||||
new QueryParameter ("RESULT", "$result"));
|
||||
List<XMLResult> results = client.execute(query, ServiceContext.getContext().getScope());
|
||||
//query.addAtomicConditions(new AtomicCondition("/ID/text()", id));
|
||||
|
||||
if (results == null || results.size() == 0) {
|
||||
results = client.execute(query, ServiceContext.getContext().getScope().getEnclosingScope());
|
||||
if (results == null || results.size() == 0) {
|
||||
throw new Exception("unable to find target RI "+ this);
|
||||
}
|
||||
}
|
||||
|
||||
GCUBERunningInstance profile = GHNContext.getImplementation(GCUBERunningInstance.class);
|
||||
profile.load(new StringReader(results.get(0).evaluate("/").get(0)));
|
||||
this.sourceService = new ServiceData();
|
||||
this.sourceService.serviceID = profile.getServiceID();
|
||||
this.sourceService.serviceClass = profile.getServiceClass();
|
||||
this.sourceService.serviceName = profile.getServiceName();
|
||||
this.hostedOnID = profile.getGHNID();
|
||||
this.scopes = new ArrayList<String>();
|
||||
for (GCUBEScope scope : profile.getScopes().values())
|
||||
this.scopes.add(scope.getName());
|
||||
} catch (Exception e) {
|
||||
throw new Exception("unable to find the target RI " + this,e);
|
||||
}
|
||||
|
||||
//looks for the GHN to contact
|
||||
try {
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
GCUBEGHNQuery query = client.getQuery(GCUBEGHNQuery.class);
|
||||
query.addAtomicConditions(new AtomicCondition("/ID/text()", this.hostedOnID));
|
||||
List<GCUBEHostingNode> hostingNode = client.execute(query, ServiceContext.getContext().getScope());
|
||||
this.hostingNodeName = hostingNode.get(0).getNodeDescription().getName();
|
||||
this.ghnEpr = this.loadGHNmanager(hostingNode.get(0).getID(), client);
|
||||
this.hostedOn = hostingNodeName;
|
||||
} catch (Exception e) {
|
||||
this.noHopeForMe("unable to find the hosting GHN (ID=" + this.hostedOnID + ")", new ResourceNotFound(e));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the RI to the scope
|
||||
*
|
||||
* @throws Exception if it is not possible to add the resource
|
||||
*/
|
||||
@Override
|
||||
protected void addToScope() throws ResourceNotFound, Exception {
|
||||
if (this.hostingNodeName.compareToIgnoreCase("") == 0)
|
||||
this.findResource();
|
||||
try {
|
||||
GHNManagerServiceAddressingLocator locator = new GHNManagerServiceAddressingLocator();
|
||||
GHNManagerPortType pt = GCUBERemotePortTypeContext.getProxy(locator.getGHNManagerPortTypePort(this.ghnEpr),
|
||||
ServiceContext.getContext().getScope(), ServiceContext.getContext());
|
||||
ScopeRIParams params = new ScopeRIParams();
|
||||
params.setClazz(this.sourceService.serviceClass);
|
||||
params.setName(this.sourceService.serviceName);
|
||||
params.setScope(this.scope);
|
||||
pt.addRIToScope(params);
|
||||
} catch (Exception e) {
|
||||
this.setStatus(STATUS.LOST);
|
||||
this.success = false;
|
||||
this.setErrorMessage("Failed to add RunningInstance to scope " + scope);
|
||||
getLogger().error("Failed to add RunningInstance to scope " + scope, e);
|
||||
throw new Exception("Failed to add RunningInstance to scope " + scope);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes the RI from the scope
|
||||
*
|
||||
* @throws Exception if it is not possible to remove the resource
|
||||
*/
|
||||
@Override
|
||||
protected void removeFromScope() throws ResourceNotFound,ServiceNotFoundException, Exception {
|
||||
this.findResource();
|
||||
try {
|
||||
GHNManagerServiceAddressingLocator locator = new GHNManagerServiceAddressingLocator();
|
||||
GHNManagerPortType pt = GCUBERemotePortTypeContext.getProxy(locator.getGHNManagerPortTypePort(this.ghnEpr),
|
||||
ServiceContext.getContext().getScope(), ServiceContext.getContext());
|
||||
ScopeRIParams params = new ScopeRIParams();
|
||||
params.setClazz(this.sourceService.serviceClass);
|
||||
params.setName(this.sourceService.serviceName);
|
||||
params.setScope(this.scope);
|
||||
pt.removeRIFromScope(params);
|
||||
} catch (Exception e) {
|
||||
this.noHopeForMe("Failed to remove RunningInstance from scope " + scope.toString() +" "+ e.getMessage(),e);
|
||||
}
|
||||
}
|
||||
|
||||
protected String getSourceServiceClass() {
|
||||
return this.sourceService.serviceClass;
|
||||
}
|
||||
|
||||
protected String getSourceServiceName() {
|
||||
return this.sourceService.serviceName;
|
||||
}
|
||||
|
||||
public boolean isUndeployNeeded() throws ResourceNotFound {
|
||||
try {
|
||||
this.findResource();
|
||||
} catch (ResourceNotFound e) {
|
||||
this.noHopeForMe("Failed to remove RunningInstance from scope " + scope.toString() +". Can't find the related service to undeploy "+ e.getMessage(),e);
|
||||
}
|
||||
if (this.scopes.size() == 1) {
|
||||
getLogger().info(this + " joins only this scope: it's going to be undeployed");
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the ID of the gHN hosting the instance
|
||||
*/
|
||||
public String getHostedOnID() {
|
||||
return hostedOnID;
|
||||
}
|
||||
|
||||
public void reportFailureOnSourceService(String message, Exception e) {
|
||||
try {
|
||||
this.noHopeForMe(message, e);
|
||||
} catch (Exception e1) {
|
||||
getLogger().error(this + "An error has been reported from outside when managing the source service", e1);
|
||||
}
|
||||
}
|
||||
|
||||
public void wasSuccessful() {
|
||||
this.success = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Number of times the resource is searched in the IS before to declare it lost
|
||||
* @return the number of attempts to do
|
||||
*/
|
||||
@Override
|
||||
protected int getMaxFindAttempts(){
|
||||
return 40;
|
||||
}
|
||||
|
||||
/**
|
||||
* Looks for the GHN manager's endpoint to contact
|
||||
* @param id the identifier of the gHN
|
||||
* @param client the ISClient instance to use
|
||||
* @return the endpoint reference of gHNManager's portType to contact
|
||||
* @throws Exception if the search fails
|
||||
*/
|
||||
private EndpointReferenceType loadGHNmanager(String id, ISClient client) throws Exception {
|
||||
//looks for the GHN manager's endpoint to contact
|
||||
GCUBERIQuery riquery = client.getQuery(GCUBERIQuery.class);
|
||||
riquery.addAtomicConditions(new AtomicCondition("//GHN/@UniqueID", id),
|
||||
new AtomicCondition("//ServiceClass", "VREManagement"),
|
||||
new AtomicCondition("//ServiceName", "GHNManager"));
|
||||
List<GCUBERunningInstance> results = client.execute(riquery,ServiceContext.getContext().getScope());
|
||||
return results.get(0).getAccessPoint().getEndpoint("gcube/common/vremanagement/GHNManager");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* Groups some service data
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
class ServiceData {
|
||||
String serviceID;
|
||||
String serviceName;
|
||||
String serviceClass;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,259 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources.types;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* A thread-safe Map with multiple keys allowing multiple values per key
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class MultiKeysMap<K1, K2, V> implements Iterable<V> {
|
||||
|
||||
private List<V> values = Collections.synchronizedList(new LinkedList<V>());
|
||||
|
||||
private List<WrappedValue> wrappedValues = Collections.synchronizedList(new LinkedList<WrappedValue>());
|
||||
|
||||
private Map<K1, HashSet<V>> k1values = Collections.synchronizedMap(new HashMap<K1, HashSet<V>>());
|
||||
|
||||
private Map<K2, HashSet<V>> k2values = Collections.synchronizedMap(new HashMap<K2, HashSet<V>>());
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public Iterator<V> iterator() {
|
||||
return values.iterator();
|
||||
}
|
||||
|
||||
/**
|
||||
* Associates the specified value with the two keys
|
||||
*
|
||||
* @param key1 the value's primary key
|
||||
* @param key2 the value's secondary key
|
||||
* @param value the value
|
||||
*/
|
||||
public void put(K1 key1, K2 key2, V value) {
|
||||
WrappedValue wrappedValue = this.new WrappedValue(value);
|
||||
wrappedValue.addKey1(key1);
|
||||
wrappedValue.addKey2(key2);
|
||||
if (wrappedValues.contains(wrappedValue))
|
||||
wrappedValues.remove(wrappedValue);
|
||||
wrappedValues.add(wrappedValue);
|
||||
if (values.contains(value))
|
||||
values.remove(value);
|
||||
values.add(value);
|
||||
//add the value index to k1values
|
||||
if (!k1values.containsKey(key1))
|
||||
k1values.put(key1, new HashSet<V>());
|
||||
k1values.get(key1).add(value);
|
||||
//add the value index to k2values
|
||||
if (!k2values.containsKey(key2))
|
||||
k2values.put(key2, new HashSet<V>());
|
||||
k2values.get(key2).add(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* removes the given values and its keys from the map
|
||||
* @param value
|
||||
*/
|
||||
public void removeValue(V value) {
|
||||
values.remove(value);
|
||||
WrappedValue wvalue = wrappedValues.get(this.wrappedIndexOf(value));
|
||||
|
||||
k1values.get(wvalue.key1).remove(value);
|
||||
if (k1values.get(wvalue.key1).isEmpty())
|
||||
k1values.remove(wvalue.key1);
|
||||
|
||||
k2values.get(wvalue.key2).remove(value);
|
||||
if (k2values.get(wvalue.key2).isEmpty())
|
||||
k2values.remove(wvalue.key2);
|
||||
|
||||
wrappedValues.remove(wvalue);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the values associated to the primary key
|
||||
*
|
||||
* @param key the key of type K1
|
||||
*/
|
||||
public void removeValuesByPrimaryKey(K1 key) {
|
||||
Set<V> valuesToRemove = k1values.get(key);
|
||||
if (valuesToRemove == null)
|
||||
return;
|
||||
Iterator<V> iterator = valuesToRemove.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
V value = iterator.next();
|
||||
values.remove(value);
|
||||
if (value == null) {
|
||||
continue;
|
||||
}
|
||||
WrappedValue wvalue = wrappedValues.get(this.wrappedIndexOf(value));
|
||||
k2values.get(wvalue.key2).remove(value);
|
||||
if (k2values.get(wvalue.key2).isEmpty())
|
||||
k2values.remove(wvalue.key2);
|
||||
wrappedValues.remove(wvalue);
|
||||
}
|
||||
|
||||
k1values.remove(key);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Removes all the values associated to the secondary key
|
||||
*
|
||||
* @param key the key of type K2
|
||||
*/
|
||||
public void removeValuesBySecondaryKey(K2 key) {
|
||||
Set<V> valuesToRemove = k2values.get(key);
|
||||
if (valuesToRemove == null)
|
||||
return;
|
||||
Iterator<V> iterator = valuesToRemove.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
V value = iterator.next();
|
||||
values.remove(value);
|
||||
if (value == null) {
|
||||
return;
|
||||
}
|
||||
WrappedValue wvalue = wrappedValues.get(this.wrappedIndexOf(value));
|
||||
k1values.get(wvalue.key1).remove(value);
|
||||
if (k1values.get(wvalue.key1).isEmpty())
|
||||
k1values.remove(wvalue.key1);
|
||||
wrappedValues.remove(wvalue);
|
||||
}
|
||||
|
||||
k2values.remove(key);
|
||||
}
|
||||
|
||||
|
||||
|
||||
private int wrappedIndexOf(V value) {
|
||||
int index = 0;
|
||||
if (value==null)
|
||||
return -1;
|
||||
for (WrappedValue wvalue : wrappedValues) {
|
||||
if (wvalue.equals(value))
|
||||
return index;
|
||||
index++;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the values to which this map maps the specified primary key
|
||||
*
|
||||
* @param key key whose associated values are to be returned
|
||||
* @return the values to which this map maps the specified primary key
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<V> getValuesByPrimaryKey(K1 key) {
|
||||
return k1values.get(key) == null? (Set<V>)Collections.emptySet(): k1values.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the values to which this map maps the specified primary key
|
||||
* @param key key whose associated values are to be returned
|
||||
* @return @return the values to which this map maps the specified secondary key
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<V> getValuesBySecondaryKey(K2 key) {
|
||||
return k2values.get(key) == null? (Set<V>)Collections.emptySet(): k2values.get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set view of the primary keys contained in this map
|
||||
*
|
||||
* @return a set view of the primary keys contained in this map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<K1> primaryKeySet() {
|
||||
return k1values.keySet() == null? (Set<K1>)Collections.emptySet(): k1values.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a set view of the secondary keys contained in this map
|
||||
*
|
||||
* @return a set view of the secondary keys contained in this map
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<K2> secondaryKeySet() {
|
||||
return k2values.keySet() == null? (Set<K2>)Collections.emptySet(): k2values.keySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a collection view of the values contained in this map
|
||||
*
|
||||
* @return a collection view of the values contained in this map
|
||||
*/
|
||||
public Collection<V> values() {
|
||||
return Collections.unmodifiableCollection(values);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all mapping from this maps
|
||||
*/
|
||||
public void clean () {
|
||||
values.clear();
|
||||
wrappedValues.clear();
|
||||
k1values.clear();
|
||||
k2values.clear();
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* Internal Map object
|
||||
*
|
||||
* It maps a value V to both its primary and secondary key
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
class WrappedValue {
|
||||
|
||||
V value;
|
||||
K1 key1;
|
||||
K2 key2;
|
||||
WrappedValue(V value) { this.value = value;}
|
||||
void addKey1(K1 key) {this.key1=key;}
|
||||
void addKey2(K2 key) {this.key2=key;}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return ((value == null) ? 0 : value.hashCode());
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() == obj.getClass()) {
|
||||
WrappedValue other = (WrappedValue) obj;
|
||||
if ((this.value == null) && (other.value == null)) {
|
||||
return true;
|
||||
} else if (this.value.equals(other.value)) {
|
||||
return true;
|
||||
}
|
||||
} else { //check if obj is the wrapped object
|
||||
if (this.value.equals(obj)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,173 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.state.GCUBEWSResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNodeManager;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.observers.Executor;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.observers.Publisher;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.observers.Serializer;
|
||||
import org.globus.wsrf.NoSuchResourceException;
|
||||
|
||||
/**
|
||||
* The ResourceManager's stateful resource
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class InstanceState extends GCUBEWSResource {
|
||||
|
||||
final protected GCUBEScope scope = ServiceContext.getContext().getInstance().getScopes().values().iterator().next();
|
||||
|
||||
protected ScopeState scopeState;
|
||||
|
||||
/** session id -> session map*/
|
||||
static Map<String, Session> id2session = Collections.synchronizedMap(new HashMap<String, Session>());;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
protected void initialise(Object... params) throws Exception {
|
||||
scopeState = new ScopeState();
|
||||
try {
|
||||
logger.info("Initializing the instance state from the local file system...");
|
||||
Serializer.load(scopeState, scope);
|
||||
//synch IS list w/ scopeState
|
||||
this.getPublishedScopeResource().loadFromLocalState(scopeState); //it's already done by the Publisher observer?
|
||||
} catch (IOException io) {
|
||||
logger.warn("The local serialized scope state is not available");
|
||||
logger.info("Loading the instance state from the IS...");
|
||||
if (this.getPublishedScopeResource().load()) {
|
||||
logger.info("Instance state harvested from the IS");
|
||||
scopeState.initialize(scope, scope.getName(), GHNContext.getContext().isSecurityEnabled());
|
||||
//synch scopeState w/ IS list
|
||||
this.getPublishedScopeResource().to(scopeState);
|
||||
} else {
|
||||
logger.info("Empty instance state created");
|
||||
//we assume that if we are running on a secure ghn, we are in a secure Scope
|
||||
scopeState.initialize(scope, scope.getName(), GHNContext.getContext().isSecurityEnabled());
|
||||
this.getPublishedScopeResource().loadFromLocalState(scopeState);
|
||||
|
||||
}
|
||||
scopeState.getRawScopeState().data.put("NODES", new HashMap<String, VirtualNode>());
|
||||
}
|
||||
ScopedResourceFactory.setResourceList(scopeState);
|
||||
VirtualNodeManager.setNodes((Map<String, VirtualNode>) scopeState.getRawScopeState().data.get("NODES"));
|
||||
this.registerObservers();
|
||||
//let's notify the observers about the current scope state
|
||||
new Thread() {
|
||||
/* (non-Javadoc)
|
||||
* @see java.lang.Thread#run()
|
||||
*/
|
||||
@Override
|
||||
public void run() {
|
||||
scopeState.notifyObservers();
|
||||
}
|
||||
|
||||
}.start();
|
||||
|
||||
}
|
||||
|
||||
private void registerObservers() {
|
||||
//register the observers
|
||||
scopeState.addObserver(new Executor());
|
||||
scopeState.addObserver(new Publisher());
|
||||
scopeState.addObserver(new Serializer());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the RP <em>ManagedScope</em>
|
||||
*
|
||||
* @return the scope managed by this instance
|
||||
*/
|
||||
synchronized public GCUBEScope getManagedScope () {
|
||||
return this.scope;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the {@link Session}
|
||||
*
|
||||
* @param id the session ID
|
||||
* @return the session
|
||||
* @throws IOException
|
||||
*/
|
||||
public Session getSession(String id) throws IOException {
|
||||
if (! id2session.containsKey(id))
|
||||
id2session.put(id, Session.load(id));
|
||||
return id2session.get(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the string representation of a {@link Session}
|
||||
*
|
||||
* @param id the session ID
|
||||
* @return the string representation of the session
|
||||
* @throws IOException
|
||||
*/
|
||||
public String getSerializedSession(String id) throws IOException {
|
||||
return Session.loadAsString(id);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds a new {@link Session} to the service's state
|
||||
*
|
||||
* @param session the session to add
|
||||
*/
|
||||
public void addSession(Session session) {
|
||||
this.getResourceList().setLastSession(session);
|
||||
id2session.put(session.getId(), session);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the {@link PublishedScopeResource}
|
||||
*
|
||||
* @return the {@link PublishedScopeResource}
|
||||
* @throws NoSuchResourceException
|
||||
*/
|
||||
public PublishedScopeResource getPublishedScopeResource() throws NoSuchResourceException {
|
||||
try {
|
||||
return PublishedScopeResource.getResource(this.scope);
|
||||
} catch (Exception e) {
|
||||
logger.warn("Unable to get the PublishedScopeResource", e);
|
||||
throw new NoSuchResourceException();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the list of {@link ScopedResource}s
|
||||
* @return the list of scoped resources
|
||||
*/
|
||||
public ScopeState getResourceList() {
|
||||
return scopeState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Disposes the current scope
|
||||
*/
|
||||
public void dispose() {
|
||||
Set<ScopedResource> allResources = new HashSet<ScopedResource>();
|
||||
for (ScopedResource resource : this.scopeState.getAllResources()) {
|
||||
allResources.add(resource);
|
||||
}
|
||||
//remove all resources
|
||||
this.scopeState.removeResources(allResources);
|
||||
|
||||
//TODO: unpublish the published scope resource
|
||||
|
||||
//TODO: undeploy myself?
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,56 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state;
|
||||
|
||||
import java.text.DateFormat;
|
||||
import java.text.ParseException;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* Transforms from {@link Date} to a valid string representation for the <em>xs:dateAndTime</em> XML Schema data type and vice versa.
|
||||
* It can be used to write/read a {@link Date} object to/from a profile.
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public final class ProfileDate {
|
||||
|
||||
static final DateFormat dateAndTime = new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ssZ");
|
||||
|
||||
/**
|
||||
* Transforms the input {@link Date} in a valid string representation for the <em>xs:dateAndTime</em> XML Schema data type
|
||||
* @param date the {@link Date} object to tranform
|
||||
* @return the {@link String} object
|
||||
*/
|
||||
public static synchronized String toXMLDateAndTime(Date date) {
|
||||
String formatted = dateAndTime.format(date);
|
||||
StringBuilder toXS = new StringBuilder();
|
||||
toXS.append(formatted.substring(0, formatted.length()-2));
|
||||
toXS.append(":");
|
||||
toXS.append(formatted.substring(formatted.length()-2, formatted.length()));
|
||||
return toXS.toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Transforms the input <em>xs:dateAndTime</em> representation in a {@link Date} object
|
||||
* @param date the string representation of <em>xs:dateAndTime</em> (e.g. " 2009-05-12T16:46:03+02:00 ")
|
||||
* @return the {@link Date} object
|
||||
* @throws ParseException if the input date is not in an valid format
|
||||
*/
|
||||
public static synchronized Date fromXMLDateAndTime(String date) throws ParseException {
|
||||
|
||||
//the test is for backward compatibility, to read the old profiles that have no time zone in the dateAndTime fields
|
||||
Pattern p = Pattern.compile("^.*T\\d{2}:\\d{2}:\\d{2}$"); //ends with 'T'HH:mm:ss
|
||||
if (p.matcher(date).matches()) {
|
||||
return new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss").parse(date);
|
||||
} else {
|
||||
StringBuilder toDate = new StringBuilder();
|
||||
toDate.append(date.substring(0, date.length()-3));
|
||||
toDate.append(date.substring(date.length()-2, date.length()));
|
||||
return dateAndTime.parse(toDate.toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,622 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.IOException;
|
||||
import java.io.StringReader;
|
||||
import java.io.StringWriter;
|
||||
import java.text.ParseException;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STATUS;
|
||||
import org.gcube.common.core.contexts.GHNContext;
|
||||
import org.gcube.common.core.informationsystem.client.AtomicCondition;
|
||||
import org.gcube.common.core.informationsystem.client.ISClient;
|
||||
import org.gcube.common.core.informationsystem.client.queries.GCUBEGenericResourceQuery;
|
||||
import org.gcube.common.core.informationsystem.publisher.ISPublisher;
|
||||
import org.gcube.common.core.resources.GCUBEGenericResource;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.scope.GCUBEScope.Type;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.kxml2.io.KXmlParser;
|
||||
import org.kxml2.io.KXmlSerializer;
|
||||
|
||||
/**
|
||||
* The scope resource published in the IS
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class PublishedScopeResource {
|
||||
|
||||
protected GCUBELog logger = new GCUBELog(this);
|
||||
|
||||
private GCUBEGenericResource resource;
|
||||
|
||||
private PublishedResourceList publishedResourceList;
|
||||
|
||||
private GCUBEScope scope;
|
||||
|
||||
private static final String NS ="";
|
||||
|
||||
private String creator = "", designer = "", service = "";
|
||||
|
||||
private Date startTime = null, endTime = null;
|
||||
|
||||
private boolean securityEnabled = false;
|
||||
|
||||
private boolean loaded = false;
|
||||
|
||||
private boolean dismissed =false;
|
||||
|
||||
private static Map<GCUBEScope,PublishedScopeResource> cache = new HashMap<GCUBEScope, PublishedScopeResource>();;
|
||||
|
||||
public void reload() throws Exception {
|
||||
try {
|
||||
publishedResourceList = new PublishedResourceList();
|
||||
this.load();
|
||||
//this.store();//to make sure we have locally the latest resource
|
||||
} catch (Exception e) {
|
||||
logger.error("Failed to reload the Scope Resource");
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
// make it private to avoid explicit creation of VREscope objects
|
||||
private PublishedScopeResource(GCUBEScope scope) throws Exception{
|
||||
this.scope = scope;
|
||||
publishedResourceList = new PublishedResourceList();
|
||||
//get the service EPR from the RI profile
|
||||
this.service = ServiceContext.getContext().getInstance().getAccessPoint().getRunningInstanceInterfaces().getEndpoint().get(0).getValue();
|
||||
// get the resource implementation
|
||||
try {
|
||||
this.resource = GHNContext.getImplementation(GCUBEGenericResource.class);
|
||||
} catch (Exception e) {
|
||||
throw new Exception("Unable to create resource to publish for " + scope.toString());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the current Scope Resource
|
||||
* @param scope the scope of the resource to load
|
||||
* @return the PublishedScopeResource
|
||||
*/
|
||||
public static PublishedScopeResource getResource(GCUBEScope scope) throws Exception {
|
||||
if (! cache.containsKey(scope))
|
||||
cache.put(scope, new PublishedScopeResource(scope));
|
||||
return cache.get(scope);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a resource to PublishedScopeResource
|
||||
*
|
||||
* @param resource
|
||||
* @throws Exception
|
||||
*/
|
||||
public void addResource(ScopedResource resource) throws Exception {
|
||||
this.publishedResourceList.add(resource.getId(), resource.getType(),resource.getJointTime(), resource.getHostedOn());
|
||||
resource.setStatus(STATUS.PUBLISHED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a resource from the PublishedScopeResource
|
||||
*
|
||||
* @param resource
|
||||
* @throws Exception
|
||||
*/
|
||||
public void removeResource(ScopedResource resource) throws Exception {
|
||||
this.publishedResourceList.remove(resource.getId(), resource.getType());
|
||||
resource.setStatus(STATUS.UNPUBLISHED);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of the PublishedScopeResource
|
||||
* @throws IOException
|
||||
*/
|
||||
public String toString() {
|
||||
try {
|
||||
this.resource.setBody(this.prepareBody());
|
||||
StringWriter ret = new StringWriter();
|
||||
this.resource.store(ret);
|
||||
return ret.toString();
|
||||
} catch (Exception e) { logger.error("Invalid Scope Resource serialization",e); return "";}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the scope
|
||||
*/
|
||||
public GCUBEScope getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the type of the scope.
|
||||
*
|
||||
* @return the type.
|
||||
*/
|
||||
public Type getType() {
|
||||
return scope.getType();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets a scope option
|
||||
*
|
||||
* @param name
|
||||
* the option name
|
||||
* @param value
|
||||
* the option value
|
||||
* @throws Exception
|
||||
* @throws ParseException
|
||||
*/
|
||||
public void setOption(String name, String value)
|
||||
throws Exception {
|
||||
if (value == null)
|
||||
return;
|
||||
|
||||
try {
|
||||
if (name.compareToIgnoreCase("DESIGNER") == 0) {
|
||||
// the designer's DN
|
||||
this.designer = value;
|
||||
} else if (name.compareToIgnoreCase("CREATOR") == 0) {
|
||||
// the creator's DN
|
||||
this.creator = value;
|
||||
} else if (name.compareToIgnoreCase("ENDTIME") == 0) {
|
||||
// the time at which the scope will be dismissed
|
||||
this.endTime = ProfileDate.fromXMLDateAndTime(value);
|
||||
} else if (name.compareToIgnoreCase("STARTTIME") == 0) {
|
||||
// the time this scope was created
|
||||
this.startTime = ProfileDate.fromXMLDateAndTime(value);
|
||||
} else if (name.compareToIgnoreCase("DESCRIPTION") == 0) {
|
||||
// the scope description
|
||||
this.resource.setDescription(value);
|
||||
} else if (name.compareToIgnoreCase("DISPLAYNAME") == 0) {
|
||||
// the name to display (the unique name is the qualified scope)
|
||||
this.resource.setName(value);
|
||||
} else if (name.compareToIgnoreCase("SECURITYENABLED") == 0) {
|
||||
// the name to display (the unique name is the qualified scope)
|
||||
this.securityEnabled = Boolean.valueOf(value);
|
||||
} else
|
||||
throw new UnknownScopeOptionException();
|
||||
} catch (ParseException e) {
|
||||
throw new Exception ("Unable to parse option " + name);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Publishes the {@link PublishedScopeResource} into the IS
|
||||
*/
|
||||
public synchronized void publish() throws Exception {
|
||||
if (this.dismissed) return;
|
||||
this.resource.setBody(this.prepareBody());
|
||||
logger.trace("Publishing Scope Resource: \n" + this.toString());
|
||||
//this.store();
|
||||
ISPublisher publisher = GHNContext.getImplementation(ISPublisher.class);
|
||||
if (this.loaded) {
|
||||
publisher.updateGCUBEResource(this.resource, this.scope, ServiceContext.getContext());
|
||||
}
|
||||
else {
|
||||
publisher.registerGCUBEResource(this.resource, this.scope, ServiceContext.getContext());
|
||||
this.loaded = true;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dismisses the {@link PublishedScopeResource} from the IS and the scope
|
||||
*/
|
||||
public synchronized void dismiss() throws Exception {
|
||||
this.resource.setBody(this.prepareBody());
|
||||
logger.trace("Unpublishing Scope Resource: \n" + this.toString());
|
||||
//this.store();
|
||||
ISPublisher publisher = GHNContext.getImplementation(ISPublisher.class);
|
||||
publisher.removeGCUBEResource(this.resource.getID(), this.resource.getType(), this.scope, ServiceContext.getContext());
|
||||
this.dismissed = true;
|
||||
}
|
||||
|
||||
private String prepareBody() throws IOException {
|
||||
StringWriter body = new StringWriter(); // serialises to a temporary writer first
|
||||
KXmlSerializer serializer = new KXmlSerializer();
|
||||
serializer.setOutput(body);
|
||||
try {
|
||||
serializer.startDocument("UTF-8", true);
|
||||
serializer.startTag(NS,"Scope").text(scope.toString()).endTag(NS,"Scope");
|
||||
serializer.startTag(NS,"Service").text(this.service).endTag(NS,"Service");
|
||||
serializer.startTag(NS,"Creator").text(this.getCreator()).endTag(NS,"Creator");
|
||||
serializer.startTag(NS,"Designer").text(this.getDesigner()).endTag(NS,"Designer");
|
||||
if (this.startTime == null)
|
||||
this.startTime = Calendar.getInstance().getTime();
|
||||
serializer.startTag(NS,"StartTime").text(ProfileDate.toXMLDateAndTime(this.startTime)).endTag(NS,"StartTime");
|
||||
if (this.endTime != null)
|
||||
serializer.startTag(NS,"EndTime").text(ProfileDate.toXMLDateAndTime(this.endTime)).endTag(NS,"EndTime");
|
||||
serializer.startTag(NS,"SecurityEnabled").text(String.valueOf(this.securityEnabled)).endTag(NS,"SecurityEnabled");
|
||||
publishedResourceList.store(serializer);
|
||||
} catch (Exception e) {
|
||||
logger.error("The Scope Resource does not have a valid serialisation", e);
|
||||
throw new IOException("The Scope Resource does not have a valid serialisation");
|
||||
}
|
||||
finally {
|
||||
body.close();
|
||||
}
|
||||
return body.toString();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the creator
|
||||
*/
|
||||
public String getCreator() {
|
||||
return (creator != null) ? creator : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the designer
|
||||
*/
|
||||
public String getDesigner() {
|
||||
return (designer != null)? designer : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the description
|
||||
*/
|
||||
public String getDescription() {
|
||||
return (this.resource.getDescription() != null)? this.resource.getDescription() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the display name
|
||||
*/
|
||||
public String getDisplayName() {
|
||||
return (this.resource.getName() != null) ? this.resource.getName() : "";
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the startTime
|
||||
*/
|
||||
public Date getStartTime() {
|
||||
return startTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the endTime
|
||||
*/
|
||||
public Date getEndTime() {
|
||||
return endTime;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the securityEnabled
|
||||
*/
|
||||
public boolean isSecurityEnabled() {
|
||||
return securityEnabled;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Loads from the <em>Body</em> element the resource information
|
||||
* @param body the <em>Body</em> of the generic resource
|
||||
* @throws Exception if the element is not valid or well formed
|
||||
*/
|
||||
private void parseBody(String body) throws Exception {
|
||||
KXmlParser parser = new KXmlParser();
|
||||
parser.setInput(new BufferedReader(new StringReader(body)));
|
||||
loop: while (true) {
|
||||
try {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("Creator")) this.creator = parser.nextText();
|
||||
else if (parser.getName().equals("Designer")) this.designer = parser.nextText();
|
||||
else if (parser.getName().equals("EndTime")) this.endTime = ProfileDate.fromXMLDateAndTime(parser.nextText());
|
||||
else if (parser.getName().equals("StartTime")) this.startTime = ProfileDate.fromXMLDateAndTime(parser.nextText());
|
||||
//else if (parser.getName().equals("DisplayName")) this.display = parser.nextText();
|
||||
else if (parser.getName().equals("SecurityEnabled")) this.securityEnabled = Boolean.valueOf(parser.nextText());
|
||||
else if (parser.getName().equals(PublishedResourceList.RESOURCES_ELEMENT)) publishedResourceList.load(parser);
|
||||
else parser.nextText();//just skip the text
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: break loop;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Exception ("Unable to parse the PublishedScopeResource body");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the scope resource from the IS
|
||||
* @param resource the resource to load
|
||||
*
|
||||
* @return true if the resource is successfully loaded, false otherwise
|
||||
*/
|
||||
protected boolean load() {
|
||||
|
||||
try {
|
||||
ISClient client = GHNContext.getImplementation(ISClient.class);
|
||||
GCUBEGenericResourceQuery query = client.getQuery(GCUBEGenericResourceQuery.class);
|
||||
query.addAtomicConditions(new AtomicCondition("//SecondaryType", determineSecondaryType()),
|
||||
new AtomicCondition("//Body/Scope", scope.toString()));
|
||||
//logger.trace(query.toString());
|
||||
List<GCUBEGenericResource> results = client.execute(query, scope);
|
||||
if ((results != null) && (results.size() > 0)) {
|
||||
this.resource = results.get(0);
|
||||
this.parseBody(this.resource.getBody());
|
||||
this.loaded = true;
|
||||
logger.trace("Resource loaded from the IS: \n" + this.toString());
|
||||
return true;
|
||||
} else
|
||||
logger.warn("Unable to load the resource for "+ this.scope.toString() + " from the IS");
|
||||
} catch (Exception e) {logger.warn("Published resource for "+ this.scope.toString()+ " does not exist on the IS yet", e);}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Determines the secondary type of the scope resource
|
||||
*
|
||||
* @return the secondary type
|
||||
*/
|
||||
private String determineSecondaryType() {
|
||||
if (this.scope.getType() == Type.VRE)
|
||||
return GCUBEGenericResource.SECONDARYTYPE_VRE;
|
||||
else if (this.scope.getType() == Type.VO)
|
||||
return GCUBEGenericResource.SECONDARYTYPE_VO;
|
||||
else
|
||||
return GCUBEGenericResource.SECONDARYTYPE_INFRASTRUCTURE;
|
||||
}
|
||||
|
||||
|
||||
public boolean loaded() {
|
||||
return this.loaded;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills the input {@link ScopeState} with the actual content of the {@link PublishedResourceList}
|
||||
*
|
||||
* @param scopeState the list to fill
|
||||
*/
|
||||
public void to(ScopeState scopeState) {
|
||||
logger.debug("To: Filling the local scope state with the published state");
|
||||
scopeState.addResources(publishedResourceList.asScopedResouces());
|
||||
scopeState.setDesigner(this.getDesigner());
|
||||
scopeState.setManager(this.getCreator());
|
||||
scopeState.setSecurity(this.isSecurityEnabled());
|
||||
scopeState.changeDescription(this.getDescription());
|
||||
scopeState.setEndTime(this.endTime);
|
||||
logger.trace("Setting the scope state to " + ProfileDate.toXMLDateAndTime(this.startTime));
|
||||
scopeState.setStartTime(this.startTime);
|
||||
logger.trace("Scope state set to:" + ProfileDate.toXMLDateAndTime(scopeState.getStartTime()));
|
||||
scopeState.setName(this.getDisplayName());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Fills this {@link PublishedResourceList} with the content of the input {@link ScopeState}
|
||||
*
|
||||
* @param scopeState the list to load
|
||||
* @throws Exception if the load fails
|
||||
*/
|
||||
public synchronized void loadFromLocalState(ScopeState scopeState) throws Exception {
|
||||
logger.debug("LoadFromLocalState: Loading the published state from the local scope state");
|
||||
//reloading is needed in order to reuse the resource ID and
|
||||
//to avoid to cancel the old Generic Resource from the IS (plus reusing any other information do not overridden)
|
||||
this.reload();
|
||||
publishedResourceList = new PublishedResourceList();//empty the scopeState
|
||||
this.synchBasicInfo(scopeState);
|
||||
for(ScopedResource resource : scopeState.getAllResources())
|
||||
this.addResource(resource);
|
||||
|
||||
//initialise some resource's fields
|
||||
if (this.scope.getType() == Type.VRE)
|
||||
this.resource.setSecondaryType(GCUBEGenericResource.SECONDARYTYPE_VRE);
|
||||
else if (this.scope.getType() == Type.VO)
|
||||
this.resource.setSecondaryType("VO");
|
||||
else
|
||||
this.resource.setSecondaryType("INFRASTRUCTURE");
|
||||
|
||||
this.resource.addScope(this.scope);
|
||||
|
||||
// force the first serialization of Body
|
||||
this.toString();
|
||||
|
||||
}
|
||||
/**
|
||||
* Synchronizes this {@link PublishedResourceList} with the content of the input {@link ScopeState}
|
||||
*
|
||||
* @param scopeState the list to synchronize with
|
||||
* @throws Exception if the synchronization fails
|
||||
*/
|
||||
public synchronized void synchWithLocalState(ScopeState scopeState) throws Exception {
|
||||
logger.debug("SynchWithLocalState: Synch the published state from the scope state");
|
||||
for(ScopedResource resource : scopeState.getAllResources()) {
|
||||
switch (resource.getStatus()) {
|
||||
case ADDED: this.addResource(resource); break;
|
||||
case REMOVED: this.removeResource(resource); break;
|
||||
case LOST: this.removeResource(resource); break;
|
||||
//in the other statuses, the resource is just ignored
|
||||
}
|
||||
}
|
||||
|
||||
this.synchBasicInfo(scopeState);
|
||||
}
|
||||
|
||||
private void synchBasicInfo(ScopeState scopeState) throws Exception {
|
||||
logger.debug("Synchronizing basic info to publish");
|
||||
this.setOption("CREATOR",scopeState.getManager());
|
||||
this.setOption("DESIGNER",scopeState.getDesigner());
|
||||
this.setOption("DESCRIPTION",scopeState.getDescription());
|
||||
this.setOption("DISPLAYNAME",scopeState.getName());
|
||||
//here we directly assign the values, don't want to format/unformat them via setOption()
|
||||
this.endTime = scopeState.getEndTime();
|
||||
this.startTime = scopeState.getStartTime();
|
||||
this.securityEnabled = scopeState.isSecurityEnabled();
|
||||
|
||||
}
|
||||
|
||||
/** InvalidVREOption exception */
|
||||
public static class UnknownScopeOptionException extends Exception {
|
||||
private static final long serialVersionUID = 1L;
|
||||
}
|
||||
|
||||
/**
|
||||
* List of resources forming the {@link PublishedScopeResource}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
class PublishedResourceList {
|
||||
|
||||
private Set<Item> resources = Collections.synchronizedSet(new HashSet<Item>());
|
||||
|
||||
private static final String RESOURCES_ELEMENT = "ScopedRescources";
|
||||
|
||||
private static final String RESOURCE_ELEMENT = "ScopedRescource";
|
||||
|
||||
class Item {
|
||||
protected String id;
|
||||
protected String type;
|
||||
protected String hostedOn;
|
||||
protected Date timestamp;
|
||||
|
||||
protected Item(String id, String value, Date timestamp, String ... hostedOn) {
|
||||
this.id = id;
|
||||
this.type = value;
|
||||
this.timestamp = timestamp;
|
||||
this.hostedOn = (hostedOn!=null && hostedOn.length>0) ? hostedOn[0] : null;
|
||||
}
|
||||
|
||||
protected Item(String id, String value, String ... hostedOn) {
|
||||
this(id, value, null, hostedOn);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
final int prime = 31;
|
||||
int result = 1;
|
||||
result = prime * result + ((id == null) ? 0 : id.hashCode());
|
||||
result = prime * result
|
||||
+ ((type == null) ? 0 : type.hashCode());
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (this == obj)
|
||||
return true;
|
||||
if (obj == null)
|
||||
return false;
|
||||
if (getClass() != obj.getClass())
|
||||
return false;
|
||||
final Item other = (Item) obj;
|
||||
if (id == null) {
|
||||
if (other.id != null)
|
||||
return false;
|
||||
} else if (!id.equals(other.id))
|
||||
return false;
|
||||
if (type == null) {
|
||||
if (other.type != null)
|
||||
return false;
|
||||
} else if (!type.equals(other.type))
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
void add(String id, String type, Date time, String ... hostedOn) {resources.add(new Item(id, type, time, hostedOn));}
|
||||
|
||||
void remove(String id, String type) {resources.remove(new Item(id, type)); }
|
||||
|
||||
Set<ScopedResource> asScopedResouces() {
|
||||
Set<ScopedResource> temp = new HashSet<ScopedResource>();
|
||||
for (Item item : resources) {
|
||||
ScopedResource resource;
|
||||
try {
|
||||
resource = ScopedResourceFactory.newResource(item.id, item.type, scope);
|
||||
resource.setJointTime(item.timestamp);
|
||||
if ((item.hostedOn != null) && (item.hostedOn.compareTo("") != 0))
|
||||
resource.setHostedON(item.hostedOn);
|
||||
temp.add(resource);
|
||||
} catch (Exception e) {
|
||||
logger.error("Can't build the resource",e);
|
||||
}
|
||||
|
||||
}
|
||||
return temp;
|
||||
|
||||
}
|
||||
|
||||
int getSize() {return resources.size();}
|
||||
/**
|
||||
* Stores the resources in the given serializer
|
||||
* @param serializer the serializer
|
||||
* @throws IOException if the storage fails
|
||||
*/
|
||||
void store(KXmlSerializer serializer) throws IOException {
|
||||
serializer.startTag(PublishedScopeResource.NS, RESOURCES_ELEMENT);
|
||||
for (Item item : resources) {
|
||||
serializer.startTag(PublishedScopeResource.NS, RESOURCE_ELEMENT);
|
||||
serializer.startTag(PublishedScopeResource.NS, "ResourceID").text(item.id).endTag(PublishedScopeResource.NS, "ResourceID");
|
||||
serializer.startTag(PublishedScopeResource.NS, "ResourceType").text(item.type).endTag(PublishedScopeResource.NS, "ResourceType");
|
||||
if ((item.hostedOn != null) && (item.hostedOn.compareTo("") != 0))
|
||||
serializer.startTag(PublishedScopeResource.NS, "HostedOn").text(item.hostedOn).endTag(PublishedScopeResource.NS, "HostedOn");
|
||||
if (item.timestamp != null)
|
||||
serializer.startTag(PublishedScopeResource.NS, "JointTime").text(ProfileDate.toXMLDateAndTime(item.timestamp)).endTag(PublishedScopeResource.NS, "JointTime");
|
||||
serializer.endTag(PublishedScopeResource.NS, RESOURCE_ELEMENT);
|
||||
}
|
||||
serializer.endTag(PublishedScopeResource.NS, RESOURCES_ELEMENT);
|
||||
}
|
||||
|
||||
/**
|
||||
* Parses the <em>Resources</em> element
|
||||
* @param parser the parser
|
||||
* @throws Exception if the element is not valid or well formed
|
||||
*/
|
||||
void load(KXmlParser parser) throws Exception {
|
||||
loop: while (true) {
|
||||
try {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals(RESOURCE_ELEMENT)) {
|
||||
String id=null, type=null, hostedOn=null;
|
||||
Date time = null;
|
||||
innerloop: while (true) {
|
||||
switch (parser.next()) {
|
||||
case KXmlParser.START_TAG:
|
||||
if (parser.getName().equals("ResourceID")) id=parser.nextText();
|
||||
else if (parser.getName().equals("ResourceType")) type=parser.nextText();
|
||||
else if (parser.getName().equals("HostedOn")) hostedOn=parser.nextText();
|
||||
else if (parser.getName().equals("JointTime")) time=ProfileDate.fromXMLDateAndTime(parser.nextText());
|
||||
else parser.nextText();
|
||||
break;
|
||||
case KXmlParser.END_TAG: if (parser.getName().equals(RESOURCE_ELEMENT)){this.add(id, type, time, hostedOn);break innerloop;}
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: throw new Exception ("Parsing failed at " + RESOURCE_ELEMENT);
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
case KXmlParser.END_TAG: if (parser.getName().equals(RESOURCES_ELEMENT)) break loop;
|
||||
break;
|
||||
case KXmlParser.END_DOCUMENT: throw new Exception ("Failed to parse at " + RESOURCES_ELEMENT);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
throw new Exception ("Failed to parse at Resources");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,55 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.types.MultiKeysMap;
|
||||
|
||||
/**
|
||||
*
|
||||
* The scope state.
|
||||
*
|
||||
* While {@link ScopeState} incorporates the behavior of a scope state, this separate and
|
||||
* minimal class contains only the core information to serialize and nothing else.
|
||||
* This way, the serialized data are separated from the state behavior, by minimizing
|
||||
* the need of future changes in the state class.
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class RawScopeState {
|
||||
|
||||
/** the scope this state belongs to*/
|
||||
protected String scope;
|
||||
|
||||
/** the list of resources */
|
||||
protected MultiKeysMap<String, String, ScopedResource> resources;
|
||||
|
||||
//Open structure for information to store. By using it, we will avoid to broke XSTREAM serialization
|
||||
//when we need to add more information to the class
|
||||
/** any data belonging the state worthy to be serialized*/
|
||||
protected Map<String, Object> data;
|
||||
|
||||
protected RawScopeState () {}
|
||||
|
||||
/**
|
||||
* Initializes the state
|
||||
* @param scope the scope this state belongs to
|
||||
*/
|
||||
protected void initialize(final GCUBEScope scope) {
|
||||
resources = new MultiKeysMap<String, String, ScopedResource>();
|
||||
data = new HashMap<String, Object>();
|
||||
this.scope = scope.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the scope this state belongs to
|
||||
*/
|
||||
public GCUBEScope getScope() {
|
||||
return GCUBEScope.getScope(this.scope);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,21 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state;
|
||||
|
||||
import org.gcube.common.core.contexts.GCUBEStatefulPortTypeContext;
|
||||
import org.gcube.common.core.state.GCUBEWSHome;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.StatefulPortTypeContext;
|
||||
|
||||
/**
|
||||
*
|
||||
* Home for stateful resource
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class ResourceManagerHome extends GCUBEWSHome {
|
||||
|
||||
@Override
|
||||
public GCUBEStatefulPortTypeContext getPortTypeContext() {
|
||||
return StatefulPortTypeContext.getContext();
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,329 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state;
|
||||
|
||||
import java.util.Calendar;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.Observable;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STATUS;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.observers.Serializer;
|
||||
|
||||
/**
|
||||
*
|
||||
* A list of scoped resources
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class ScopeState extends Observable {
|
||||
|
||||
protected GCUBELog logger = new GCUBELog(this);
|
||||
|
||||
/** last operation performed on the list*/
|
||||
protected OPERATION lastOperationPerformed;
|
||||
|
||||
public enum OPERATION {CREATED, LOADED, TOBEMANAGED, PUBLISHED, SERIALIZED, EXECUTED};
|
||||
|
||||
private RawScopeState rawState;
|
||||
|
||||
private Session report;
|
||||
|
||||
protected ScopeState() {}
|
||||
|
||||
protected void initialize(GCUBEScope scope, String name, boolean securityEnabled, String ... description) {
|
||||
rawState = new RawScopeState();
|
||||
rawState.initialize(scope);
|
||||
this.rawState.data.put("NAME", name);
|
||||
this.lastOperationPerformed = OPERATION.CREATED;
|
||||
if (!this.rawState.data.containsKey("STARTTIME"))
|
||||
this.rawState.data.put("STARTTIME", Calendar.getInstance().getTime());
|
||||
this.rawState.data.put("ENDTIME", null);
|
||||
if ((! this.rawState.data.containsKey("DESCRIPTION")) && (description.length > 0))
|
||||
this.rawState.data.put("DESCRIPTION", description[0]);
|
||||
this.rawState.data.put("SECURITYENABLED",securityEnabled);
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scope manager identity
|
||||
* @param manager the manager
|
||||
*/
|
||||
public synchronized void setManager(String manager) {
|
||||
this.rawState.data.put("MANAGER", manager);
|
||||
this.notifyObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the scope designer identity
|
||||
* @param manager the manager
|
||||
*/
|
||||
public synchronized void setDesigner(String designer) {
|
||||
this.rawState.data.put("DESIGNER", designer);
|
||||
this.notifyObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the scope description
|
||||
*
|
||||
* @param description the description
|
||||
*/
|
||||
public synchronized void changeDescription (String description) {
|
||||
this.rawState.data.put("DESCRIPTION", description);
|
||||
this.notifyObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a new resources to the list
|
||||
* @param newresources the resources to add
|
||||
*/
|
||||
public synchronized void addResources(Set<ScopedResource> newresources) {
|
||||
for (ScopedResource resource : newresources) {
|
||||
//if (resource.getStatus() != STATUS.PUBLISHED)//no need to manage it again
|
||||
resource.setStatus(STATUS.ADDREQUESTED);
|
||||
if (rawState.resources.primaryKeySet().contains(resource.getId()))
|
||||
rawState.resources.removeValuesByPrimaryKey(resource.getId());
|
||||
rawState.resources.put(resource.getId(), resource.getType(), resource);
|
||||
}
|
||||
this.setLastOperationPerformed(OPERATION.TOBEMANAGED);
|
||||
this.notifyObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets resources of the given type
|
||||
*
|
||||
* @param type the type to filter
|
||||
* @return the collection of resources
|
||||
*/
|
||||
public synchronized Set<ScopedResource> getResourcesByType(String type) {
|
||||
return rawState.resources.getValuesBySecondaryKey(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the resource with the given id
|
||||
*
|
||||
* @param id the resource identified
|
||||
* @return the resource
|
||||
*/
|
||||
public synchronized ScopedResource getResource(String id) {
|
||||
return (ScopedResource) rawState.resources.getValuesByPrimaryKey(id).iterator().next();
|
||||
}
|
||||
|
||||
public boolean containsResource(String id) {
|
||||
return rawState.resources.primaryKeySet().contains(id);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all the resource of the given type
|
||||
*
|
||||
* @param type the type of resources to remove
|
||||
*/
|
||||
public synchronized void removeAllResourcesByType(String type) {
|
||||
for (ScopedResource resource : rawState.resources.getValuesBySecondaryKey(type)) {
|
||||
resource.setStatus(STATUS.REMOVEREQUESTED);
|
||||
rawState.resources.put(resource.getId(), resource.getType(), resource);//TODO: is needed?
|
||||
}
|
||||
this.setLastOperationPerformed(OPERATION.TOBEMANAGED);
|
||||
this.notifyObservers();
|
||||
rawState.resources.removeValuesBySecondaryKey(type);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the resources from the scope
|
||||
*
|
||||
* @param oldresources the resources to remove
|
||||
*
|
||||
*/
|
||||
public synchronized void removeResources(Set<ScopedResource> oldresources) {
|
||||
//resources must be in the state in order to be removed :-)
|
||||
//this is to prevent service's unconscious cleanup..
|
||||
for (ScopedResource resource : oldresources) {
|
||||
resource.setStatus(STATUS.REMOVEREQUESTED);
|
||||
rawState.resources.put(resource.getId(), resource.getType(), resource);
|
||||
if (resource.getType().compareToIgnoreCase(ScopedDeployedService.TYPE) == 0) {
|
||||
((ScopedDeployedService) resource).setCallbackID(this.getLastReport().getId());
|
||||
((ScopedDeployedService) resource).scheduleUndeploy();
|
||||
}
|
||||
}
|
||||
this.setLastOperationPerformed(OPERATION.TOBEMANAGED);
|
||||
this.notifyObservers(); //let the obs do their work before to remove the resources
|
||||
for (ScopedResource resource : oldresources) {
|
||||
logger.debug("Removing resource " + resource+ " from the scope state");
|
||||
if (resource.getStatus() == STATUS.UNPUBLISHED) {
|
||||
rawState.resources.removeValuesByPrimaryKey(resource.getId());
|
||||
logger.debug("...removed");
|
||||
} else {
|
||||
logger.warn("Resource " + resource + " is still PUBLISHED in the scope state, can't be removed");
|
||||
}
|
||||
}
|
||||
|
||||
this.notifyObservers(); //notify about the physical removal(s)
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the resource from the state, no matter about its actual status
|
||||
* @param resources
|
||||
*/
|
||||
public synchronized void forceResourceRemoval(Set<ScopedResource> resources) {
|
||||
for (ScopedResource resource : resources) {
|
||||
logger.debug("Removing resource " + resources+ " from the scope state");
|
||||
rawState.resources.removeValuesByPrimaryKey(resource.getId());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Empty the list of resources
|
||||
*/
|
||||
protected synchronized void removeAllResources() {
|
||||
for (ScopedResource resource : rawState.resources.values())
|
||||
resource.setStatus(STATUS.REMOVEREQUESTED);
|
||||
this.setLastOperationPerformed(OPERATION.TOBEMANAGED);
|
||||
this.notifyObservers();
|
||||
rawState.resources.clean();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the resource's scope
|
||||
*
|
||||
* @return the scope
|
||||
*/
|
||||
public GCUBEScope getScope() {
|
||||
return rawState.getScope();
|
||||
}
|
||||
|
||||
public synchronized void notifyObservers(Object whatschanged) {
|
||||
// Otherwise it won't propagate changes
|
||||
setChanged();
|
||||
super.notifyObservers(whatschanged);
|
||||
}
|
||||
|
||||
public synchronized void notifyObservers() {
|
||||
// Otherwise it won't propagate changes
|
||||
setChanged();
|
||||
super.notifyObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the {@link ScopedResource}s
|
||||
*
|
||||
* @return all the {@link ScopedResource}s
|
||||
*/
|
||||
public synchronized Collection<ScopedResource> getAllResources() {
|
||||
return Collections.unmodifiableCollection(rawState.resources.values());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scope manager
|
||||
* @return the scope manger
|
||||
*/
|
||||
public String getManager() {
|
||||
return (String) this.rawState.data.get("MANAGER");
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the scope designer
|
||||
* @return the scope designer
|
||||
*/
|
||||
public String getDesigner() {
|
||||
return (String) this.rawState.data.get("DESIGNER");
|
||||
}
|
||||
|
||||
public String getDescription() {
|
||||
return (String) this.rawState.data.get("DESCRIPTION");
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
|
||||
return (String) this.rawState.data.get("NAME");
|
||||
}
|
||||
|
||||
|
||||
public Date getEndTime() {
|
||||
return (Date) this.rawState.data.get("ENDTIME");
|
||||
}
|
||||
|
||||
public Date getStartTime() {
|
||||
return (Date) this.rawState.data.get("STARTTIME");
|
||||
}
|
||||
|
||||
public boolean isSecurityEnabled() {
|
||||
return (Boolean) this.rawState.data.get("SECURITYENABLED");
|
||||
}
|
||||
|
||||
public void setEndTime(Date endTime) {
|
||||
this.rawState.data.put("ENDTIME", endTime);
|
||||
this.notifyObservers();
|
||||
}
|
||||
|
||||
public void setStartTime(Date startTime) {
|
||||
logger.trace("setStartTime: Start time " + ProfileDate.toXMLDateAndTime(startTime));
|
||||
this.rawState.data.put("STARTTIME", startTime);
|
||||
this.notifyObservers();
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.rawState.data.put("NAME", name);
|
||||
this.notifyObservers();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the the last operation performed on the list
|
||||
*/
|
||||
public OPERATION getLastOperationPerformed() {
|
||||
return lastOperationPerformed;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param operation the last operation performed on the list
|
||||
*/
|
||||
public synchronized void setLastOperationPerformed(OPERATION operation) {
|
||||
this.lastOperationPerformed = operation;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Gets the {@link RawScopeState}
|
||||
* @return the raw state
|
||||
*/
|
||||
public RawScopeState getRawScopeState() {
|
||||
return rawState;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new {@link RawScopeState}
|
||||
* it usually invoked at deserialization time, see {@link Serializer#load(ScopeState, GCUBEScope)}
|
||||
* @param state
|
||||
*/
|
||||
public void setRawScopeState(RawScopeState state) {
|
||||
this.rawState = state;
|
||||
|
||||
}
|
||||
|
||||
public void setSecurity(boolean securityEnabled) {
|
||||
this.rawState.data.put("SECURITYENABLED",securityEnabled);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the last active {@link Session}
|
||||
* @return the session
|
||||
*/
|
||||
public Session getLastReport() {
|
||||
return this.report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the last active {@link Session}
|
||||
* @param session the session
|
||||
*/
|
||||
public void setLastSession(Session report) {
|
||||
this.report = report;
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,463 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileReader;
|
||||
import java.io.FileWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.Serializable;
|
||||
import java.io.StringWriter;
|
||||
import java.util.Calendar;
|
||||
import java.util.Collections;
|
||||
import java.util.GregorianCalendar;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.DeployerReport;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.DeployerReport.DeployedRunningInstance;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.Dependency;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.resources.DeployedDependency;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STATUS;
|
||||
import org.kxml2.io.KXmlSerializer;
|
||||
|
||||
/**
|
||||
* Session for each service operation.
|
||||
* It holds all the information related to the activities performed to
|
||||
* satisfy the caller's request.
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class Session implements Serializable {
|
||||
|
||||
protected final GCUBELog logger = new GCUBELog(this, ServiceContext.getContext());
|
||||
|
||||
final static String NS = "";
|
||||
|
||||
/** */
|
||||
private static final long serialVersionUID = 1180822699138069365L;
|
||||
|
||||
private static final String reportDir = "reports";
|
||||
|
||||
/** report last update timestamp */
|
||||
private Calendar lastUpdate = new GregorianCalendar();
|
||||
|
||||
private String id = "";
|
||||
|
||||
private OPERATION operation;
|
||||
|
||||
private GCUBEScope scope = null;
|
||||
|
||||
private boolean brokerWasSuccessful, brokerReportAvailable = false;
|
||||
|
||||
private String brokerMessage = "";
|
||||
|
||||
/** ghn id -> deployer report map*/
|
||||
private Map<String, DeployerReport> node2report = Collections.synchronizedMap(new HashMap<String, DeployerReport>());
|
||||
|
||||
/** Status of a dependency resolver request */
|
||||
public enum DEPSTATUS {SUCCESS, FAILED};
|
||||
|
||||
public enum OPERATION {Create, AddResources, UpdateResources, RemoveResources, Dispose};
|
||||
|
||||
private Set<ScopedDeployedService> services = Collections.synchronizedSet(new HashSet<ScopedDeployedService>());
|
||||
|
||||
private Set<ScopedResource> resources = Collections.synchronizedSet(new HashSet<ScopedResource>());
|
||||
|
||||
/** the instances deployed by the services included in this report*/
|
||||
private Set<DeployedRunningInstance> instances = new HashSet<DeployedRunningInstance>();
|
||||
|
||||
private String deploymentPlan;
|
||||
|
||||
/** internally used by {@link Session#loadAsString(String)}*/
|
||||
private Session () {}
|
||||
|
||||
/**
|
||||
* Builds a new empty report
|
||||
* @param id the session ID assigned to the operation
|
||||
*/
|
||||
public Session(String id, OPERATION operation, GCUBEScope ... scope) {
|
||||
this.id = id;
|
||||
this.operation = operation;
|
||||
if ((scope == null)|| (scope[0] == null))
|
||||
this.scope = ServiceContext.getContext().getInstance().getScopes().values().iterator().next();
|
||||
else
|
||||
this.scope = scope[0];
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a Deployer Report to the Resource Report
|
||||
* @param report the string representation of the report, as sent by a Deployer service
|
||||
* @throws Exception if a problem in the report parsing occurs
|
||||
*/
|
||||
synchronized public void addGHNReport(DeployerReport report) throws Exception {
|
||||
node2report.put(report.getGHNID(), report);
|
||||
this.lastUpdate = new GregorianCalendar();
|
||||
}
|
||||
|
||||
synchronized public void addResource(ScopedResource resource) {
|
||||
this.resources.add(resource);
|
||||
this.lastUpdate = new GregorianCalendar();
|
||||
}
|
||||
|
||||
synchronized public void addService(ScopedDeployedService service) {
|
||||
this.services.add(service);
|
||||
this.lastUpdate = new GregorianCalendar();
|
||||
}
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public String toXML() throws IOException {
|
||||
StringWriter report = new StringWriter(); // serialises to a temporary writer first
|
||||
KXmlSerializer serializer = new KXmlSerializer();
|
||||
serializer.setOutput(report);
|
||||
//serializer.setProperty(XmlSerializer, "\t");
|
||||
try {
|
||||
serializer.startDocument("UTF-8", true);
|
||||
serializer.startTag(NS,"ResourceReport");
|
||||
serializer.startTag(NS,"ID").text(this.id).endTag(NS, "ID");
|
||||
serializer.startTag(NS,"Status").text(this.isReportClosed()?"CLOSED" :"OPEN").endTag(NS, "Status");
|
||||
serializer.startTag(NS,"Operation").text(this.operation.toString()).endTag(NS, "Operation");
|
||||
serializer.startTag(NS,"LastUpdate").text(ProfileDate.toXMLDateAndTime(this.lastUpdate.getTime())).endTag(NS,"LastUpdate");
|
||||
serializer.startTag(NS,"TargetScope").text(this.scope.toString()).endTag(NS,"TargetScope");
|
||||
|
||||
//resources section
|
||||
serializer.startTag(NS,"Resources");
|
||||
for (ScopedResource resource : resources) {
|
||||
serializer.startTag(NS,"Resource");
|
||||
serializer.startTag(NS,"ID").text(resource.getId()).endTag(NS,"ID");
|
||||
serializer.startTag(NS,"Type").text(resource.getType()).endTag(NS,"Type");
|
||||
if (resource.isSuccess()) {
|
||||
if (this.operation == OPERATION.AddResources)
|
||||
serializer.startTag(NS,"Status").text("ADDED").endTag(NS,"Status");
|
||||
else
|
||||
serializer.startTag(NS,"Status").text("REMOVED").endTag(NS,"Status");
|
||||
//serializer.startTag(NS,"ErrorDescription").text("-").endTag(NS,"ErrorDescription");
|
||||
} else {
|
||||
serializer.startTag(NS,"Status").text("FAILED").endTag(NS,"Status");
|
||||
serializer.startTag(NS,"ErrorDescription").text(resource.getErrorMessage()).endTag(NS,"ErrorDescription");
|
||||
}
|
||||
serializer.endTag(NS,"Resource");
|
||||
}
|
||||
|
||||
serializer.endTag(NS,"Resources");
|
||||
//broker section
|
||||
if (brokerReportAvailable) {
|
||||
serializer.startTag(NS,"DeploymentPlanCreation");
|
||||
serializer.startTag(NS,"Status").text(this.brokerWasSuccessful?"SUCCESS":"FAILED").endTag(NS, "Status");
|
||||
serializer.startTag(NS,"Message").text(this.brokerMessage).endTag(NS, "Message");
|
||||
serializer.endTag(NS,"DeploymentPlanCreation");
|
||||
}
|
||||
//services
|
||||
serializer.startTag(NS,"Services");
|
||||
for (ScopedDeployedService service : this.services) {
|
||||
serializer.startTag(NS,"Service");
|
||||
serializer.startTag(NS,"ID").text(service.getId()).endTag(NS, "ID");
|
||||
serializer.startTag(NS,"Class").text(service.getSourceService().getClazz()).endTag(NS, "Class");
|
||||
serializer.startTag(NS,"Name").text(service.getSourceService().getName()).endTag(NS, "Name");
|
||||
serializer.startTag(NS,"Version").text(service.getSourceService().getVersion()).endTag(NS, "Version");
|
||||
if (((this.operation == OPERATION.AddResources) ||(this.operation == OPERATION.Create))
|
||||
&& (service.getStatus() != STATUS.LOST) && (this.brokerWasSuccessful)) {
|
||||
if ( (service.getMissingDependencies(service.getTargetGHNID()).size() > 0) || (service.getErrorMessage().length() > 0) ) {
|
||||
serializer.startTag(NS,"DependenciesResolutionStatus").text(DEPSTATUS.FAILED.name()).endTag(NS, "DependenciesResolutionStatus");
|
||||
serializer.startTag(NS,"DeployedOn").text("not deployed").endTag(NS, "DeployedOn");
|
||||
serializer.startTag(NS,"ErrorDescription").text(service.getErrorMessage()).endTag(NS, "ErrorDescription");
|
||||
}else {
|
||||
serializer.startTag(NS,"DependenciesResolutionStatus").text(DEPSTATUS.SUCCESS.name()).endTag(NS, "DependenciesResolutionStatus");
|
||||
serializer.startTag(NS,"DeployedOn").text(service.getTargetGHNID()).endTag(NS, "DeployedOn");
|
||||
serializer.startTag(NS,"ErrorDescription").text("-").endTag(NS, "ErrorDescription");
|
||||
}
|
||||
serializer.startTag(NS,"DependenciesResolution");
|
||||
//resolved dependencies
|
||||
serializer.startTag(NS,"ResolvedDependencies");
|
||||
for (Dependency dep : service.getResolvedDependencies(service.getTargetGHNID())) {
|
||||
serializer.startTag(NS,"Dependency");
|
||||
serializer.startTag(NS,"ServiceClass").text(dep.getService().getClazz()).endTag(NS, "ServiceClass");
|
||||
serializer.startTag(NS,"ServiceName").text(dep.getService().getName()).endTag(NS, "ServiceName");
|
||||
serializer.startTag(NS,"ServiceVersion").text(dep.getService().getVersion()).endTag(NS, "ServiceVersion");
|
||||
serializer.startTag(NS,"PackageName").text(dep.getName()).endTag(NS, "PackageName");
|
||||
serializer.startTag(NS,"PackageVersion").text(dep.getVersion()).endTag(NS, "PackageVersion");
|
||||
serializer.endTag(NS,"Dependency");
|
||||
}
|
||||
serializer.endTag(NS,"ResolvedDependencies");
|
||||
//missing dependencies
|
||||
serializer.startTag(NS,"MissingDependencies");
|
||||
for (Dependency dep : service.getMissingDependencies(service.getTargetGHNID())) {
|
||||
serializer.startTag(NS,"Dependency");
|
||||
serializer.startTag(NS,"ServiceClass").text(dep.getService().getClazz()).endTag(NS, "ServiceClass");
|
||||
serializer.startTag(NS,"ServiceName").text(dep.getService().getName()).endTag(NS, "ServiceName");
|
||||
serializer.startTag(NS,"ServiceVersion").text(dep.getService().getVersion()).endTag(NS, "ServiceVersion");
|
||||
serializer.startTag(NS,"PackageName").text(dep.getName()).endTag(NS, "PackageName");
|
||||
serializer.startTag(NS,"PackageVersion").text(dep.getVersion()).endTag(NS, "PackageVersion");
|
||||
serializer.endTag(NS,"Dependency");
|
||||
}
|
||||
serializer.endTag(NS,"MissingDependencies");
|
||||
serializer.endTag(NS,"DependenciesResolution");
|
||||
}
|
||||
//add the deployment report if it is available
|
||||
String reportID = service.getTargetGHNID();
|
||||
if (this.operation == OPERATION.AddResources)
|
||||
serializer.startTag(NS,"DeploymentActivity");
|
||||
else
|
||||
serializer.startTag(NS,"UndeploymentActivity");
|
||||
if (node2report.keySet().contains(reportID)) {
|
||||
serializer.startTag(NS,"GHN");
|
||||
serializer.startTag(NS,"ID").text(service.getTargetGHNID()).endTag(NS, "ID");
|
||||
serializer.startTag(NS,"Host").text(node2report.get(reportID).getHost()).endTag(NS,"Host");
|
||||
serializer.startTag(NS,"LastReportReceivedOn").text(ProfileDate.toXMLDateAndTime(node2report.get(reportID).getLastUpdate())).endTag(NS,"LastReportReceivedOn");
|
||||
serializer.startTag(NS,"LastReportReceived");
|
||||
serializer.startTag(NS,"Status").text(node2report.get(reportID).getStatus()).endTag(NS, "Status");
|
||||
this.addGHNReport(serializer, node2report.get(reportID), service);
|
||||
serializer.endTag(NS, "LastReportReceived");
|
||||
serializer.endTag(NS,"GHN");
|
||||
DeployedRunningInstance instance = this.getInstanceForService(service);
|
||||
if ((this.operation == OPERATION.AddResources)
|
||||
|| (this.operation == OPERATION.Create)){
|
||||
if (instance != null) {
|
||||
serializer.startTag(NS,"RelatedRunningInstance");
|
||||
if (instance.isAlive())
|
||||
serializer.startTag(NS, "ID").text(instance.getRIID()).endTag(NS, "ID");
|
||||
serializer.startTag(NS,"Status").text(instance.isAlive()? "SUCCESS" : "FAILED").endTag(NS,"Status");
|
||||
serializer.startTag(NS,"Message").text(instance.getMessage()).endTag(NS,"Message");
|
||||
serializer.endTag(NS,"RelatedRunningInstance");
|
||||
|
||||
} else if (node2report.get(reportID).getStatus().compareToIgnoreCase("CLOSED") == 0 ) {
|
||||
serializer.startTag(NS,"RelatedRunningInstance");
|
||||
serializer.startTag(NS,"Status").text("FAILED").endTag(NS,"Status");
|
||||
serializer.startTag(NS,"Message").text("The Deployer service did not detect any new instance of this service on the target gHN").endTag(NS,"Message");
|
||||
serializer.endTag(NS,"RelatedRunningInstance");
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (service.isSuccess() && (this.brokerReportAvailable))
|
||||
serializer.text("The report is still not available for this service");
|
||||
else
|
||||
serializer.text("No report");
|
||||
}
|
||||
if (this.operation == OPERATION.AddResources) {
|
||||
serializer.endTag(NS,"DeploymentActivity");
|
||||
}
|
||||
else
|
||||
serializer.endTag(NS,"UndeploymentActivity");
|
||||
|
||||
serializer.endTag(NS,"Service");
|
||||
}
|
||||
serializer.endTag(NS,"Services");
|
||||
serializer.endTag(NS,"ResourceReport");
|
||||
serializer.endDocument();
|
||||
}
|
||||
catch (Exception e) {
|
||||
logger.error("The Resource Report does not have a valid serialisation", e);
|
||||
throw new IOException("The Resource Report does not have a valid serialisation "+ e.getMessage());
|
||||
}
|
||||
finally {
|
||||
report.close();
|
||||
}
|
||||
return report.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the deployed instance (if any) for the given service
|
||||
* @param service the service
|
||||
* @return the instance or null if no instances was found
|
||||
*/
|
||||
private DeployedRunningInstance getInstanceForService(ScopedDeployedService service) {
|
||||
for (DeployedRunningInstance instance : this.instances) {
|
||||
if ( (instance.getServiceClass().compareToIgnoreCase(service.getSourceService().getClazz()) == 0)
|
||||
&& (instance.getServiceName().compareToIgnoreCase(service.getSourceService().getName()) == 0)) {
|
||||
return instance;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the lastUpdate
|
||||
*/
|
||||
public Calendar getLastUpdate() {
|
||||
return lastUpdate;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the resource report identifier
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the scope this report belongs to
|
||||
*/
|
||||
public GCUBEScope getScope() {
|
||||
return scope;
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the report on the local file system
|
||||
*
|
||||
* @throws IOException if the saving fails
|
||||
*/
|
||||
synchronized public void save() throws IOException {
|
||||
FileWriter file = new FileWriter(getReportFile(this.id));
|
||||
file.write(this.toXML());
|
||||
file.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the report from the file system
|
||||
*
|
||||
* @param id the report ID
|
||||
* @return the report
|
||||
* @throws IOException if the report does not have a valid serialization
|
||||
*/
|
||||
protected static Session load(String id) throws IOException {
|
||||
Session report = new Session();
|
||||
// load the report from its serialization
|
||||
|
||||
return report;
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the report from the file system
|
||||
*
|
||||
* @param id the report ID
|
||||
* @return the string representation of the report
|
||||
* @throws IOException if the report does not have a valid serialization
|
||||
*/
|
||||
protected static String loadAsString(String id) throws IOException {
|
||||
|
||||
// load the report serialization
|
||||
|
||||
File f = getReportFile(id);
|
||||
if (! f.exists())
|
||||
throw new IOException("Unable to find a serialized report with ID=" + id);
|
||||
|
||||
BufferedReader br = new BufferedReader(new FileReader(f));
|
||||
StringBuilder report = new StringBuilder();
|
||||
String s;
|
||||
while((s = br.readLine()) != null) {
|
||||
report.append(s);
|
||||
}
|
||||
|
||||
br.close();
|
||||
return report.toString();
|
||||
}
|
||||
|
||||
private static File getReportFile(String id) throws IOException {
|
||||
return new File(ServiceContext.getContext().getConfigurationFileAbsolutePath(reportDir) + File.separator + id + ".xml");
|
||||
|
||||
}
|
||||
|
||||
private void addGHNReport(KXmlSerializer serializer, DeployerReport report, ScopedDeployedService service) throws Exception {
|
||||
serializer.startTag(NS, "Packages");
|
||||
for (DeployedDependency dep: report.getDependencies()) {
|
||||
if (this.isDepOfService(dep, service, report.getGHNID())) {
|
||||
serializer.startTag(NS,"Package");
|
||||
serializer.startTag(NS,"ServiceClass").text(dep.getService().getClazz()).endTag(NS, "ServiceClass");
|
||||
serializer.startTag(NS,"ServiceName").text(dep.getService().getName()).endTag(NS, "ServiceName");
|
||||
serializer.startTag(NS,"ServiceVersion").text(dep.getService().getVersion()).endTag(NS, "ServiceVersion");
|
||||
serializer.startTag(NS,"PackageName").text(dep.getName()).endTag(NS, "PackageName");
|
||||
serializer.startTag(NS,"PackageVersion").text(dep.getVersion()).endTag(NS, "PackageVersion");
|
||||
serializer.startTag(NS,"Status").text(dep.getStatus()).endTag(NS, "Status");
|
||||
serializer.startTag(NS,"Message").text(dep.getMessage()).endTag(NS, "Message");
|
||||
serializer.endTag(NS,"Package");
|
||||
}
|
||||
}
|
||||
serializer.endTag(NS, "Packages");
|
||||
|
||||
}
|
||||
|
||||
public synchronized void reportBrokerWork(boolean wasSuccessful, String brokerMessage) {
|
||||
this.brokerReportAvailable = true;
|
||||
this.brokerWasSuccessful = wasSuccessful;
|
||||
this.brokerMessage = brokerMessage;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds newly deployed instances to the report. These instances are reported to be activated by the Deployer following a deployment
|
||||
* request
|
||||
*
|
||||
* @param instances the new instances
|
||||
*/
|
||||
public void addDeployedInstances(Set<DeployedRunningInstance> instances) {
|
||||
if ((instances == null) || (instances.size() == 0))
|
||||
return;
|
||||
this.instances.addAll(instances);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if a dependency belongs to a specific service
|
||||
* @param dep the dependency to check
|
||||
* @param service the potential owner service
|
||||
* @return true if the dependency belongs the service
|
||||
*/
|
||||
private boolean isDepOfService(DeployedDependency dep, ScopedDeployedService service,String targetGHNID) {
|
||||
for (Dependency resolvedDependency : service.getResolvedDependencies(targetGHNID)) {
|
||||
if (dep.equals((Dependency)resolvedDependency)) return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks whether the report is closed or no
|
||||
* @return true if the report is closed, false otherwise
|
||||
*/
|
||||
public boolean isReportClosed() {
|
||||
|
||||
for ( ScopedResource resource : this.resources) {
|
||||
if ((resource.getStatus() == STATUS.ADDREQUESTED) || (resource.getStatus() == STATUS.REMOVEREQUESTED))
|
||||
return false;//the resource still need to be managed
|
||||
}
|
||||
|
||||
for (ScopedDeployedService service : this.services) {
|
||||
String reportID = service.getTargetGHNID();
|
||||
if (service.isSuccess() && (this.brokerWasSuccessful)) {
|
||||
//check the availability of the report and its status
|
||||
if (! node2report.keySet().contains(reportID)) {
|
||||
return false;
|
||||
} else if (node2report.get(reportID).getStatus().compareToIgnoreCase("CLOSED") != 0){
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public Set<ScopedDeployedService> getServices() {
|
||||
return this.services;
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets all the GHN reports received
|
||||
* @return a map where the key is the GHN ID and the value is the related report
|
||||
*/
|
||||
public Map<String, DeployerReport> getAllGHNReports() {
|
||||
return node2report;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the {@link OPERATION} related to this report
|
||||
*/
|
||||
public OPERATION getOperation() {
|
||||
return operation;
|
||||
}
|
||||
|
||||
public void setDeploymentPlan(String plan) {
|
||||
this.deploymentPlan = plan;
|
||||
}
|
||||
|
||||
public String getDeploymentPlan() throws IOException {
|
||||
if (this.deploymentPlan == null)
|
||||
throw new IOException("No Deployment Plan is available");
|
||||
return this.deploymentPlan;
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,154 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state.observers;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNodeManager;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode.NoGHNFoundException;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.operators.Operator.ACTION;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedRunningInstance;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.ResourceNotFound;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STATUS;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory.ServiceNotFoundException;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ScopeState;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ScopeState.OPERATION;
|
||||
|
||||
/**
|
||||
*
|
||||
* Performs management operations on {@link ScopedResource}s depending on their {@link STATUS}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class Executor extends ScopeObserver {
|
||||
|
||||
@Override
|
||||
protected void scopeChanged(ScopeState scopeState) {
|
||||
if (scopeState.getLastOperationPerformed() == OPERATION.EXECUTED)
|
||||
return; //nothing to manage
|
||||
boolean managed = false;
|
||||
//RIs have to be managed first
|
||||
//if a gHN is removed from a scope, the hosted RI are automatically removed too by gCore and
|
||||
//this has to be avoided, otherwise the removeFromScope will not find them at removing time
|
||||
Map<String, List<ScopedDeployedService>> toRemoveFromNode = new HashMap<String,List<ScopedDeployedService>>();
|
||||
Set<ScopedResource> toRemoveFromScope = new HashSet<ScopedResource>();
|
||||
Set<ScopedResource> toRemoveFromState = new HashSet<ScopedResource>();
|
||||
for (ScopedResource resource : scopeState.getResourcesByType(ScopedRunningInstance.TYPE)){
|
||||
switch (resource.getStatus()) {
|
||||
case ADDREQUESTED: this.addResourceToScope(resource); managed = true; break;
|
||||
case REMOVEREQUESTED:
|
||||
try {
|
||||
if (((ScopedRunningInstance)resource).isUndeployNeeded()) {
|
||||
String hostedOnID = ((ScopedRunningInstance)resource).getHostedOnID();
|
||||
try {
|
||||
if (! toRemoveFromNode.containsKey(hostedOnID))
|
||||
toRemoveFromNode.put(hostedOnID, new ArrayList<ScopedDeployedService>());
|
||||
ScopedDeployedService service = ScopedResourceFactory.getRelatedService((ScopedRunningInstance)resource);
|
||||
if (service.getNodes().size() > 1) {
|
||||
logger.debug("Removing " + service + " from node " + resource.getHostedOn());
|
||||
//there exist other instances of the service in the scope, we are going to remove only this one
|
||||
service.scheduleUndeploy(VirtualNodeManager.getNode(hostedOnID, resource.getScope()));
|
||||
service.setCallbackID(scopeState.getLastReport().getId());
|
||||
scopeState.getLastReport().addResource(service);
|
||||
scopeState.getLastReport().addService(service);
|
||||
toRemoveFromNode.get(hostedOnID).add(service);
|
||||
} else if (service.getNodes().size() == 1) {
|
||||
//remove the service from the whole scope, since the instance to remove is deployed only once
|
||||
logger.debug("Removing " + service + " from the scope");
|
||||
scopeState.getLastReport().addResource(service);
|
||||
scopeState.getLastReport().addService(service);
|
||||
toRemoveFromScope.add(service);
|
||||
} if (service.getNodes().size() < 0) {
|
||||
//what's that??
|
||||
((ScopedRunningInstance)resource).reportFailureOnSourceService("Can't find any node where the instance is deployed",new Exception("Can't find any node where the instance is deployed"));
|
||||
resource.setStatus(STATUS.LOST);
|
||||
toRemoveFromState.add(resource);
|
||||
}
|
||||
((ScopedRunningInstance)resource).wasSuccessful();
|
||||
resource.setStatus(STATUS.REMOVED);
|
||||
} catch (ServiceNotFoundException e) {
|
||||
((ScopedRunningInstance)resource).reportFailureOnSourceService("Unable to find the source service. It might not be deployed by this Resource Manager instance",e);
|
||||
resource.setStatus(STATUS.LOST);
|
||||
toRemoveFromState.add(resource);
|
||||
} catch (NoGHNFoundException e) {
|
||||
((ScopedRunningInstance)resource).reportFailureOnSourceService("Unable to find the hosting gHN, ID=" + hostedOnID,e);
|
||||
resource.setStatus(STATUS.LOST);
|
||||
toRemoveFromState.add(resource);
|
||||
}
|
||||
} else {
|
||||
this.removeResourceFromScope(resource);
|
||||
toRemoveFromState.add(resource);
|
||||
}
|
||||
} catch (ResourceNotFound e) {
|
||||
resource.setStatus(STATUS.LOST);
|
||||
}
|
||||
managed = true;break;
|
||||
}
|
||||
}
|
||||
//now we can manage all the rest of the resources
|
||||
for (ScopedResource resource : scopeState.getAllResources()) {
|
||||
switch (resource.getStatus()) {
|
||||
case ADDREQUESTED: this.addResourceToScope(resource); managed = true; break;
|
||||
case REMOVEREQUESTED: this.removeResourceFromScope(resource); toRemoveFromState.add(resource); managed = true;break;
|
||||
}
|
||||
}
|
||||
//notify the others for serialization and publication duties
|
||||
if (managed) {
|
||||
scopeState.setLastOperationPerformed(OPERATION.EXECUTED);
|
||||
scopeState.notifyObservers();
|
||||
}
|
||||
//if there are services to undeploy, redo the procedure for them
|
||||
for (String ghnid : toRemoveFromNode.keySet()) {
|
||||
for (ScopedDeployedService service : toRemoveFromNode.get(ghnid)) {
|
||||
try {
|
||||
service.removeFromScope(ghnid);
|
||||
} catch (Exception e) {
|
||||
logger.error("Unable to undeploy " + service + " from " + ghnid, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
//remove the services from the state or trigger the notifier to manage the service removed from specific nodes
|
||||
if (toRemoveFromScope.size() > 0 )
|
||||
scopeState.removeResources(toRemoveFromScope);
|
||||
else if (toRemoveFromNode.keySet().size() > 0)
|
||||
scopeState.notifyObservers();
|
||||
|
||||
//...and finally, a physical cleanup of the state
|
||||
scopeState.forceResourceRemoval(toRemoveFromState);
|
||||
}
|
||||
|
||||
|
||||
private void addResourceToScope(ScopedResource resource) {
|
||||
try {
|
||||
resource.doAction(ACTION.ADD);
|
||||
resource.setStatus(STATUS.ADDED);
|
||||
} catch (ResourceNotFound e) {
|
||||
//the resource does not exist..it will be removed from the internal state
|
||||
resource.setStatus(STATUS.REMOVED);
|
||||
} catch (Exception e) {
|
||||
resource.setStatus(STATUS.LOST);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private void removeResourceFromScope(ScopedResource resource) {
|
||||
|
||||
try {
|
||||
resource.doAction(ACTION.REMOVE);
|
||||
resource.setStatus(STATUS.REMOVED);
|
||||
} catch (ResourceNotFound e) {
|
||||
//tolerate this exception... anyway it will be removed from the internal state
|
||||
resource.setStatus(STATUS.REMOVED);
|
||||
} catch (Exception e) {
|
||||
//can't cope with this exception and don't know what to do
|
||||
resource.setStatus(STATUS.LOST);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -0,0 +1,42 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state.observers;
|
||||
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ProfileDate;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.PublishedScopeResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ScopeState;
|
||||
import static org.gcube.vremanagement.resourcemanager.impl.state.ScopeState.OPERATION;
|
||||
/**
|
||||
*
|
||||
* Synchronizes the resources' list with the IS
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class Publisher extends ScopeObserver {
|
||||
|
||||
|
||||
@Override
|
||||
protected void scopeChanged(ScopeState scopeState) {
|
||||
|
||||
if (scopeState.getLastOperationPerformed() == OPERATION.PUBLISHED)
|
||||
return; //no need to republish and loop on this
|
||||
|
||||
try {
|
||||
PublishedScopeResource resource = PublishedScopeResource.getResource(scopeState.getScope());
|
||||
try {
|
||||
logger.trace("PUBLISHER: Start time " + ProfileDate.toXMLDateAndTime(scopeState.getStartTime()));
|
||||
resource.synchWithLocalState(scopeState);
|
||||
resource.publish();
|
||||
scopeState.setLastOperationPerformed(OPERATION.PUBLISHED);
|
||||
scopeState.notifyObservers();//force to serialize after publishing (not nice, thought)
|
||||
} catch (Exception e) {
|
||||
logger.fatal("Can't publish the Scope Resource in the IS");
|
||||
throw e;
|
||||
}
|
||||
} catch (Exception e) {
|
||||
logger.fatal("An error occured in the resource's publishing", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -0,0 +1,41 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state.observers;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
import org.gcube.common.core.utils.logging.GCUBELog;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ScopeState;
|
||||
|
||||
/**
|
||||
*
|
||||
* Base observer for {@link ScopeState}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public abstract class ScopeObserver implements Observer {
|
||||
|
||||
protected GCUBELog logger = new GCUBELog(this.getClass());
|
||||
|
||||
public void update(Observable observed, Object arg) {
|
||||
|
||||
logger.trace(this.getClass().getSimpleName() + " Observer has been notified");
|
||||
ScopeState resources;
|
||||
|
||||
if (ScopeState.class.isAssignableFrom(observed.getClass()))
|
||||
resources = (ScopeState) observed;
|
||||
else
|
||||
throw new IllegalArgumentException("Can't manage the observed obj");
|
||||
|
||||
//notify subclasses
|
||||
this.scopeChanged(resources);
|
||||
}
|
||||
|
||||
/**
|
||||
* Manages the modified scope
|
||||
*
|
||||
* @param scopeState the scope
|
||||
*/
|
||||
protected abstract void scopeChanged(ScopeState scopeState);
|
||||
|
||||
}
|
|
@ -0,0 +1,121 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state.observers;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.Map;
|
||||
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.deployment.VirtualNode;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedAnyResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedGHN;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedRunningInstance;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.types.MultiKeysMap;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.RawScopeState;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.state.ScopeState;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
import com.thoughtworks.xstream.io.xml.QNameMap;
|
||||
import com.thoughtworks.xstream.io.xml.StaxDriver;
|
||||
import javax.xml.namespace.QName;
|
||||
|
||||
/**
|
||||
*
|
||||
* Serializer for {@link ScopeState}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class Serializer extends ScopeObserver {
|
||||
|
||||
public final static File persistentList = ServiceContext.getContext().getPersistentFile("ScopedResourceList.xml", true);
|
||||
private final static String namespace = "http://gcube-system.org/namespaces/resourcemanager/manager/xsd/state";
|
||||
|
||||
/**
|
||||
* Serializes the notified list on the file system
|
||||
* @param scopeState the list to serialize
|
||||
*/
|
||||
@Override
|
||||
protected synchronized void scopeChanged(final ScopeState scopeState) {
|
||||
try {
|
||||
store(scopeState);
|
||||
//scopeState.setLastOperationPerformed(OPERATION.SERIALIZED); //if we record this, the others observer manage the list with no need
|
||||
//we do not notify the others obs here, since the serialization does not imply any change in the list
|
||||
} catch (IOException e) {
|
||||
logger.fatal("Cannot serialize the resource's list", e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
public synchronized static void store(final ScopeState scopeState) throws IOException {
|
||||
|
||||
QNameMap qmap = new QNameMap();
|
||||
qmap.registerMapping(new QName(namespace, ""), RawScopeState.class);
|
||||
StaxDriver driver = new StaxDriver(qmap);
|
||||
driver.setRepairingNamespace(false);
|
||||
XStream stream = new XStream(driver);
|
||||
prepareStream(stream);
|
||||
|
||||
FileOutputStream fs = new FileOutputStream(persistentList);
|
||||
stream.toXML(scopeState.getRawScopeState(), fs);
|
||||
fs.close();
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads the list of {@link ScopedResource} from the local file system
|
||||
* @param the actual scope
|
||||
* @return the resource list, if any
|
||||
* @throws IOException if the list was not found on the file system
|
||||
*/
|
||||
public synchronized static void load(ScopeState scopeState, GCUBEScope scope) throws IOException {
|
||||
if (! persistentList.exists())
|
||||
throw new IOException();
|
||||
|
||||
//try to load the local list of resources
|
||||
QNameMap qmap = new QNameMap();
|
||||
qmap.registerMapping(new QName(namespace, ""), RawScopeState.class);
|
||||
StaxDriver driver = new StaxDriver(qmap);
|
||||
driver.setRepairingNamespace(false);
|
||||
XStream stream = new XStream(driver);
|
||||
prepareStream(stream);
|
||||
|
||||
RawScopeState state = (RawScopeState) stream.fromXML(new FileInputStream((persistentList)));
|
||||
|
||||
//a bit of sanity checks....
|
||||
if ((state == null) || (state.getScope() == null) || (state.getScope().getName().compareTo(scope.getName()) != 0))
|
||||
throw new IOException();
|
||||
|
||||
//inject the state
|
||||
scopeState.setRawScopeState(state);
|
||||
}
|
||||
|
||||
private static void prepareStream(XStream stream) {
|
||||
stream.processAnnotations(RawScopeState.class);
|
||||
stream.alias(RawScopeState.class.getSimpleName(), RawScopeState.class);
|
||||
|
||||
stream.processAnnotations(ScopedResource.class);
|
||||
stream.alias(ScopedResource.class.getSimpleName(), ScopedResource.class);
|
||||
|
||||
stream.alias(ScopedGHN.class.getSimpleName(), ScopedGHN.class);
|
||||
stream.processAnnotations(ScopedGHN.class);
|
||||
|
||||
stream.alias(ScopedRunningInstance.class.getSimpleName(), ScopedRunningInstance.class);
|
||||
stream.processAnnotations(ScopedRunningInstance.class);
|
||||
|
||||
stream.alias(ScopedDeployedService.class.getSimpleName(), ScopedDeployedService.class);
|
||||
stream.processAnnotations(ScopedDeployedService.class);
|
||||
|
||||
stream.alias(ScopedAnyResource.class.getSimpleName(), ScopedAnyResource.class);
|
||||
stream.processAnnotations(ScopedAnyResource.class);
|
||||
|
||||
stream.alias("ResourceList", MultiKeysMap.class);
|
||||
stream.alias("ResourceData", Map.class);
|
||||
stream.alias("Scope", GCUBEScope.class);
|
||||
stream.alias("ScopeType", GCUBEScope.Type.class);
|
||||
stream.alias("VirtualNode", VirtualNode.class);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,112 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.state;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.gcube.common.core.resources.GCUBEHostingNode;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
|
||||
import com.thoughtworks.xstream.XStream;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* JUnit test class for {@link ScopeState}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class ResourceListTest {
|
||||
|
||||
private static final String SCOPE = "/gcube/devsec";
|
||||
|
||||
private static final String NAME = "test-list";
|
||||
|
||||
private static final String DESCRIPTION = "This is a test for scoped resources";
|
||||
|
||||
private ScopeState list;
|
||||
|
||||
@Test
|
||||
public void initializeList(String name) {
|
||||
list = new ScopeState();
|
||||
list.initialize(GCUBEScope.getScope(SCOPE), NAME, false, DESCRIPTION);
|
||||
|
||||
}
|
||||
|
||||
protected void setUp() throws Exception {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void testAddResource()throws Exception {
|
||||
Set<ScopedResource> resourceToAdd = new HashSet<ScopedResource>();
|
||||
ScopedResource ghn = ScopedResourceFactory.newResource("ID1", GCUBEHostingNode.TYPE, GCUBEScope.getScope(SCOPE));
|
||||
resourceToAdd.add(ghn);
|
||||
list.addResources(resourceToAdd);
|
||||
Assert.assertEquals(1, list.getResourcesByType(ghn.getType()).size());
|
||||
ScopedResource ghn2 = ScopedResourceFactory.newResource("ID2", GCUBEHostingNode.TYPE, GCUBEScope.getScope(SCOPE));
|
||||
resourceToAdd.add(ghn2);
|
||||
list.addResources(resourceToAdd);
|
||||
Assert.assertEquals(2, list.getResourcesByType(ghn2.getType()).size());
|
||||
ScopedResource ri = ScopedResourceFactory.newResource("RI1", GCUBERunningInstance.TYPE, GCUBEScope.getScope(SCOPE));
|
||||
ri.setHostedON("node1.p:8080");
|
||||
resourceToAdd.add(ri);
|
||||
list.addResources(resourceToAdd);
|
||||
Assert.assertEquals(3, list.getResourcesByType(ri.getType()).size());
|
||||
}
|
||||
|
||||
public void testGetResourcesByType() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testChangeDescription() {
|
||||
list.changeDescription("This is a new description");
|
||||
}
|
||||
|
||||
public void testRemoveAllResourcesByType() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveResource() throws Exception {
|
||||
Set<ScopedResource> resourceToRemove = new HashSet<ScopedResource>();
|
||||
ScopedResource ghn = ScopedResourceFactory.newResource("ID1", GCUBEHostingNode.TYPE, GCUBEScope.getScope(SCOPE));
|
||||
resourceToRemove.add(ghn);
|
||||
list.removeResources(resourceToRemove);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCleanList() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
public void testAddObserver() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
public void testDeleteObserver() {
|
||||
fail("Not yet implemented");
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
protected void tearDown() throws Exception {
|
||||
XStream stream = new XStream();
|
||||
stream.processAnnotations(ScopeState.class);
|
||||
System.out.println(stream.toXML(list));
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,128 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources.types;
|
||||
|
||||
|
||||
import org.gcube.common.core.resources.GCUBEHostingNode;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
*
|
||||
* JUnit test for {@link MultiKeysMap}
|
||||
*
|
||||
* @author Manuele Simi (ISTI-CNR)
|
||||
*
|
||||
*/
|
||||
public class MultiKeysMapTest {
|
||||
|
||||
private MultiKeysMap<String, String, ScopedResource> map;
|
||||
|
||||
public MultiKeysMapTest(String name) {
|
||||
super(name);
|
||||
this.map = new MultiKeysMap<String, String, ScopedResource>();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPut() throws Exception {
|
||||
System.out.println("Adding resources test");
|
||||
System.out.println("Map before the method");
|
||||
printMap();
|
||||
ScopedResource ghn = ScopedResourceFactory.newResource("ID1", GCUBEHostingNode.TYPE, GCUBEScope.getScope("/gcube"));
|
||||
map.put(ghn.getId(), ghn.getType(), ghn);
|
||||
Assert.assertEquals(1, map.values().size());
|
||||
ScopedResource ghn2 = ScopedResourceFactory.newResource("ID2", GCUBEHostingNode.TYPE, GCUBEScope.getScope("/gcube"));
|
||||
map.put(ghn2.getId(), ghn2.getType(), ghn2);
|
||||
Assert.assertEquals(2, map.values().size());
|
||||
ScopedResource ri = ScopedResourceFactory.newResource("RI1", GCUBERunningInstance.TYPE, GCUBEScope.getScope("/gcube"));
|
||||
map.put(ri.getId(), ri.getType(), ri);
|
||||
Assert.assertEquals(3, map.values().size());
|
||||
System.out.println("Map after the method");
|
||||
printMap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveValuesByPrimaryKey() throws Exception {
|
||||
testPut();
|
||||
System.out.println("testRemoveValuesByPrimaryKey");
|
||||
map.removeValuesByPrimaryKey("ID2");
|
||||
System.out.println("Map after testRemoveValuesByPrimaryKey method");
|
||||
printMap();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemoveValue() throws Exception {
|
||||
ScopedResource ghn = ScopedResourceFactory.newResource("ID1", GCUBEHostingNode.TYPE, GCUBEScope.getScope("/gcube"));
|
||||
map.removeValue(ghn);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testRemoveValuesBySecondaryKey() throws Exception {
|
||||
ScopedResource ri = ScopedResourceFactory.newResource("RI1", GCUBERunningInstance.TYPE, GCUBEScope.getScope("/gcube"));
|
||||
map.removeValuesBySecondaryKey(ri.getType());
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testGetValuesByPrimaryKey() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetValuesBySecondaryKey() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPrimaryKeySet() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSecondaryKeySet() {
|
||||
fail("Not yet implemented");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testValues() {
|
||||
for (ScopedResource resource : map.values()) {
|
||||
System.out.println("Resource Value ID = " + resource.getId());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClean() {
|
||||
map.clean();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Test
|
||||
public void printMap() {
|
||||
System.out.println("Values by KEY1:");
|
||||
for (String key1 : map.primaryKeySet()) {
|
||||
for (ScopedResource resource : map.getValuesByPrimaryKey(key1))
|
||||
System.out.println( key1 + " ->" +resource.getId());
|
||||
}
|
||||
System.out.println("Values by KEY2:");
|
||||
for (String key2 : map.secondaryKeySet()) {
|
||||
for (ScopedResource resource : map.getValuesBySecondaryKey(key2))
|
||||
System.out.println( key2 + " ->" +resource.getId());
|
||||
}
|
||||
System.out.println("Values:");
|
||||
for (ScopedResource resource : map.values()) {
|
||||
System.out.println(resource.getId());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
package org.gcube.vremanagement.resourcemanager.impl.resources.types;
|
||||
|
||||
import java.util.Observable;
|
||||
import java.util.Observer;
|
||||
|
||||
|
||||
import org.gcube.common.core.resources.GCUBEHostingNode;
|
||||
import org.gcube.common.core.resources.GCUBERunningInstance;
|
||||
import org.gcube.common.core.scope.GCUBEScope;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResourceFactory;
|
||||
import org.gcube.vremanagement.resourcemanager.impl.resources.types.MultiKeysMap;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
|
||||
public class MultiKeysTester {
|
||||
|
||||
MultiKeysMap<String, String, ScopedResource> map;
|
||||
|
||||
@Test
|
||||
public void createMap() {
|
||||
this.map = new MultiKeysMap<String, String, ScopedResource>();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void addObserver() {
|
||||
this.createMap();
|
||||
//map.addObserver(new CollectionWatcher());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void populateMap() throws Exception {
|
||||
ScopedResource ghn = ScopedResourceFactory.newResource("ID1", GCUBEHostingNode.TYPE,GCUBEScope.getScope("/gcube"));
|
||||
map.put(ghn.getId(), ghn.getType(), ghn);
|
||||
ScopedResource ghn2 = ScopedResourceFactory.newResource("ID2", GCUBEHostingNode.TYPE, GCUBEScope.getScope("/gcube"));
|
||||
map.put(ghn2.getId(), ghn2.getType(), ghn2);
|
||||
ScopedResource ri = ScopedResourceFactory.newResource("RI1", GCUBERunningInstance.TYPE, GCUBEScope.getScope("/gcube"));
|
||||
map.put(ri.getId(), ri.getType(), ri);
|
||||
printMap(map);
|
||||
map.removeValuesBySecondaryKey(ri.getType());
|
||||
printMap(map);
|
||||
map.removeValue(ghn);
|
||||
printMap(map);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void printMap(MultiKeysMap<String, String, ScopedResource> map) {
|
||||
System.out.println("Values by KEY1:");
|
||||
for (String key1 : map.primaryKeySet()) {
|
||||
for (ScopedResource resource : map.getValuesByPrimaryKey(key1))
|
||||
System.out.println( key1 + " ->" +resource.getId());
|
||||
}
|
||||
System.out.println("Values by KEY2:");
|
||||
for (String key2 : map.secondaryKeySet()) {
|
||||
for (ScopedResource resource : map.getValuesBySecondaryKey(key2))
|
||||
System.out.println( key2 + " ->" +resource.getId());
|
||||
}
|
||||
System.out.println("Values:");
|
||||
for (ScopedResource resource : map.values()) {
|
||||
System.out.println(resource.getId());
|
||||
}
|
||||
}
|
||||
|
||||
public class CollectionWatcher implements Observer {
|
||||
|
||||
public void update(Observable o, Object arg) {
|
||||
System.out.println("Notified");
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,108 @@
|
|||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>resource-manager</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
<artifactId>resource-manager-stubs</artifactId>
|
||||
<name>Resource Manager Stubs</name>
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>gcf</artifactId>
|
||||
<version>[1.4.0-SNAPSHOT,1.5.0)</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-config</id>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<phase>process-resources</phase>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/META-INF</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${configDirectory}</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.gcube.tools</groupId>
|
||||
<artifactId>maven-service-plugin</artifactId>
|
||||
<configuration>
|
||||
<wsdls>
|
||||
<wsdl>
|
||||
<name>ResourceManager</name>
|
||||
<relativePackage>stubs.resourcemanager</relativePackage>
|
||||
<namespace>${namespace}</namespace>
|
||||
<additionalMappings>-Nhttp://gcube-system.org/common/vremanagement/types=${basepackage}.stubs.common</additionalMappings>
|
||||
</wsdl>
|
||||
</wsdls>
|
||||
</configuration>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>generate-stubs</id>
|
||||
<goals>
|
||||
<goal>stub-gen</goal>
|
||||
</goals>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.codehaus.mojo</groupId>
|
||||
<artifactId>build-helper-maven-plugin</artifactId>
|
||||
<version>1.7</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>add-source</id>
|
||||
<phase>process-sources</phase>
|
||||
<goals>
|
||||
<goal>add-source</goal>
|
||||
</goals>
|
||||
<configuration>
|
||||
<sources>
|
||||
<source>${basedir}/target/generated-sources/stubs</source>
|
||||
</sources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,85 @@
|
|||
<?xml version="1.0"?>
|
||||
<project
|
||||
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"
|
||||
xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">
|
||||
<modelVersion>4.0.0</modelVersion>
|
||||
|
||||
<parent>
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>resource-manager</artifactId>
|
||||
<version>1.2.0-SNAPSHOT</version>
|
||||
</parent>
|
||||
|
||||
<artifactId>resource-manager-test-suite</artifactId>
|
||||
|
||||
<name>Resource Manager test suite</name>
|
||||
|
||||
|
||||
<properties>
|
||||
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
|
||||
</properties>
|
||||
|
||||
<dependencies>
|
||||
|
||||
<!-- reactor dependencies -->
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.core</groupId>
|
||||
<artifactId>gcf</artifactId>
|
||||
<version>[1.4.0-SNAPSHOT,1.5.0)</version>
|
||||
<scope>provided</scope>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>resource-manager-stubs</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>org.gcube.resourcemanagement</groupId>
|
||||
<artifactId>resource-manager-service</artifactId>
|
||||
<version>${project.version}</version>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>junit</groupId>
|
||||
<artifactId>junit</artifactId>
|
||||
<version>4.8.2</version>
|
||||
<scope>test</scope>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
<plugins>
|
||||
|
||||
<plugin>
|
||||
<groupId>org.apache.maven.plugins</groupId>
|
||||
<artifactId>maven-resources-plugin</artifactId>
|
||||
<version>2.5</version>
|
||||
<executions>
|
||||
<execution>
|
||||
<id>copy-config</id>
|
||||
<goals>
|
||||
<goal>copy-resources</goal>
|
||||
</goals>
|
||||
<phase>process-resources</phase>
|
||||
<configuration>
|
||||
<outputDirectory>${project.build.outputDirectory}/META-INF</outputDirectory>
|
||||
<resources>
|
||||
<resource>
|
||||
<directory>${configDirectory}</directory>
|
||||
</resource>
|
||||
</resources>
|
||||
</configuration>
|
||||
</execution>
|
||||
</executions>
|
||||
</plugin>
|
||||
|
||||
</plugins>
|
||||
|
||||
</build>
|
||||
|
||||
</project>
|
|
@ -0,0 +1,302 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions name="ResourceManager"
|
||||
targetNamespace="http://gcube-system.org/namespaces/vremanagement/resourcemanager"
|
||||
xmlns="http://schemas.xmlsoap.org/wsdl/"
|
||||
xmlns:tns="http://gcube-system.org/namespaces/vremanagement/resourcemanager"
|
||||
xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/"
|
||||
xmlns:provider="http://gcube-system.org/namespaces/common/core/porttypes/GCUBEProvider"
|
||||
xmlns:coretypes="http://gcube-system.org/namespaces/common/core/types"
|
||||
xmlns:corefaults="http://gcube-system.org/namespaces/common/core/faults"
|
||||
xmlns:vretypes="http://gcube-system.org/common/vremanagement/types"
|
||||
xmlns:wsrlw="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceLifetime-1.2-draft-01.wsdl"
|
||||
xmlns:wsrp="http://docs.oasis-open.org/wsrf/2004/06/wsrf-WS-ResourceProperties-1.2-draft-01.xsd"
|
||||
xmlns:wsntw="http://docs.oasis-open.org/wsn/2004/06/wsn-WS-BaseNotification-1.2-draft-01.wsdl"
|
||||
xmlns:wsdlpp="http://www.globus.org/namespaces/2004/10/WSDLPreprocessor"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
<import namespace="http://gcube-system.org/namespaces/common/core/porttypes/GCUBEProvider" location="../gcube/common/core/providers/GCUBEProvider.wsdl"/>
|
||||
|
||||
<import namespace="http://gcube-system.org/namespaces/common/core/faults" location="../gcube/common/core/faults/GCUBEFaults.wsdl"/>
|
||||
|
||||
<import namespace="http://gcube-system.org/common/vremanagement/types" location="VREManagementTypes.wsdl"/>
|
||||
|
||||
|
||||
<!--============================================================
|
||||
|
||||
T Y P E S
|
||||
|
||||
============================================================-->
|
||||
<types>
|
||||
<xsd:schema targetNamespace="http://gcube-system.org/namespaces/vremanagement/resourcemanager"
|
||||
xmlns:tns="http://gcube-system.org/namespaces/vremanagement/resourcemanager"
|
||||
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
|
||||
|
||||
<xsd:import namespace="http://gcube-system.org/namespaces/common/core/types" schemaLocation="../gcube/common/core/types/GCUBETypes.xsd"/>
|
||||
<xsd:import namespace="http://gcube-system.org/common/vremanagement/types" schemaLocation="VREManagementTypes.xsd"/>
|
||||
|
||||
<xsd:simpleType name="resourceID">
|
||||
<xsd:restriction base="xsd:string" />
|
||||
</xsd:simpleType>
|
||||
|
||||
<xsd:element name="VOID">
|
||||
<xsd:complexType/>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="ServiceItem">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="ServiceClass" type="xsd:string"/>
|
||||
<xsd:element name="ServiceName" type="xsd:string"/>
|
||||
<xsd:element name="ServiceVersion" type="xsd:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="GHN" type="tns:resourceID" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="ServiceList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="service" type="tns:ServiceItem" minOccurs="1" maxOccurs="unbounded"/>
|
||||
<xsd:element name="GHN" type="tns:resourceID" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="ResourceItem">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="ID" type="tns:resourceID"/>
|
||||
<xsd:element name="Type" type="xsd:string"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:complexType name="ResourceList">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="resource" type="tns:ResourceItem" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="addResourcesParameters">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="services" type="tns:ServiceList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="resources" type="tns:ResourceList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="targetScope" type="coretypes:scope" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="removeResourcesParameters">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="services" type="tns:ServiceList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="resources" type="tns:ResourceList" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="targetScope" type="coretypes:scope" minOccurs="0" maxOccurs="1"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="sendReportParameters">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="callbackID" type="xsd:string"/>
|
||||
<xsd:element name="report" type="xsd:string"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:complexType name="ScopeOption">
|
||||
<xsd:sequence>
|
||||
<xsd:element name="name" type="xsd:string"/>
|
||||
<xsd:element name="value" type="xsd:string"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
|
||||
<xsd:element name="optionsParameters">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="ScopeOptionList" type="tns:ScopeOption" minOccurs="1" maxOccurs="unbounded"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="disposeScopeParameters">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="Name" type="coretypes:scope"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="createScopeParameters">
|
||||
<xsd:complexType>
|
||||
<xsd:sequence>
|
||||
<xsd:element name="Name" type="coretypes:scope"/>
|
||||
<xsd:element name="ServiceMap" type="xsd:string" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element ref="tns:optionsParameters"/>
|
||||
<xsd:element ref="tns:addResourcesParameters"/>
|
||||
</xsd:sequence>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
<xsd:element name="GHN" type="tns:resourceID"/>
|
||||
|
||||
<xsd:element name="reportID" type="xsd:string"/>
|
||||
|
||||
<xsd:element name="report" type="xsd:string"/>
|
||||
|
||||
<xsd:element name="InvalidScopeFaultType">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="corefaults:GCUBEUnrecoverableFault">
|
||||
<xsd:sequence/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="InvalidOptionsFaultType">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="corefaults:GCUBEUnrecoverableFault">
|
||||
<xsd:sequence/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="ResourcesCreationFaultType">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="corefaults:GCUBEUnrecoverableFault">
|
||||
<xsd:sequence/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="ResourcesRemovalFaultType">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="corefaults:GCUBEUnrecoverableFault">
|
||||
<xsd:sequence/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
<xsd:element name="NoSuchReportFaultType">
|
||||
<xsd:complexType>
|
||||
<xsd:complexContent>
|
||||
<xsd:extension base="corefaults:GCUBEUnrecoverableFault">
|
||||
<xsd:sequence/>
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
</xsd:element>
|
||||
|
||||
</xsd:schema>
|
||||
</types>
|
||||
|
||||
<!--============================================================
|
||||
|
||||
M E S S A G E S
|
||||
|
||||
============================================================-->
|
||||
|
||||
<message name="AddResourcesInputMessage">
|
||||
<part name="request" element="tns:addResourcesParameters"/>
|
||||
</message>
|
||||
<message name="ReportID">
|
||||
<part name="request" element="tns:reportID"/>
|
||||
</message>
|
||||
<message name="RemoveResourcesInputMessage">
|
||||
<part name="request" element="tns:removeResourcesParameters"/>
|
||||
</message>
|
||||
<message name="SendReportInputMessage">
|
||||
<part name="request" element="tns:sendReportParameters"/>
|
||||
</message>
|
||||
<message name="ChangeScopeOptionsInputMessage">
|
||||
<part name="request" element="tns:optionsParameters"/>
|
||||
</message>
|
||||
<message name="DisposeScopeInputMessage">
|
||||
<part name="request" element="tns:disposeScopeParameters"/>
|
||||
</message>
|
||||
<message name="CreateScopeInputMessage">
|
||||
<part name="request" element="tns:createScopeParameters"/>
|
||||
</message>
|
||||
<message name="GetReportInputMessage">
|
||||
<part name="request" element="tns:reportID"/>
|
||||
</message>
|
||||
<message name="GetReportResponseMessage">
|
||||
<part name="request" element="tns:report"/>
|
||||
</message>
|
||||
<message name="VoidMessage">
|
||||
<part name="response" element="tns:VOID"/>
|
||||
</message>
|
||||
<wsdl:message name="InvalidScopeFaultMessage">
|
||||
<part name="fault" element="tns:InvalidScopeFaultType"/>
|
||||
</wsdl:message>
|
||||
<wsdl:message name="InvalidOptionsFaultMessage">
|
||||
<part name="fault" element="tns:InvalidOptionsFaultType"/>
|
||||
</wsdl:message>
|
||||
<wsdl:message name="ResourcesCreationFaultMessage">
|
||||
<part name="fault" element="tns:ResourcesCreationFaultType"/>
|
||||
</wsdl:message>
|
||||
<wsdl:message name="ResourcesRemovalFaultMessage">
|
||||
<part name="fault" element="tns:ResourcesRemovalFaultType"/>
|
||||
</wsdl:message>
|
||||
<wsdl:message name="NoSuchReportFaultMessage">
|
||||
<part name="fault" element="tns:NoSuchReportFaultType"/>
|
||||
</wsdl:message>
|
||||
<!--============================================================
|
||||
|
||||
P O R T T Y P E
|
||||
|
||||
============================================================-->
|
||||
<portType name="ResourceManagerPortType"
|
||||
wsdlpp:extends="provider:GCUBEProvider">
|
||||
|
||||
<operation name="AddResources">
|
||||
<input message="tns:AddResourcesInputMessage"/>
|
||||
<output message="tns:ReportID"/>
|
||||
<fault name="fault" message="tns:ResourcesCreationFaultMessage"/>
|
||||
<fault name="fault1" message="tns:InvalidScopeFaultMessage"/>
|
||||
</operation>
|
||||
|
||||
<operation name="RemoveResources">
|
||||
<input message="tns:RemoveResourcesInputMessage"/>
|
||||
<output message="tns:ReportID"/>
|
||||
<fault name="fault" message="tns:ResourcesRemovalFaultMessage"/>
|
||||
<fault name="fault1" message="tns:InvalidScopeFaultMessage"/>
|
||||
</operation>
|
||||
|
||||
<operation name="ChangeScopeOptions">
|
||||
<input message="tns:ChangeScopeOptionsInputMessage"/>
|
||||
<output message="tns:VoidMessage"/>
|
||||
<fault name="fault" message="tns:InvalidOptionsFaultMessage"/>
|
||||
<fault name="fault1" message="tns:InvalidScopeFaultMessage"/>
|
||||
</operation>
|
||||
|
||||
<operation name="DisposeScope">
|
||||
<input message="tns:DisposeScopeInputMessage"/>
|
||||
<output message="tns:ReportID"/>
|
||||
<fault name="fault" message="tns:InvalidScopeFaultMessage"/>
|
||||
</operation>
|
||||
|
||||
<operation name="CreateScope">
|
||||
<input message="tns:CreateScopeInputMessage"/>
|
||||
<output message="tns:ReportID"/>
|
||||
<fault name="fault1" message="tns:InvalidScopeFaultMessage"/>
|
||||
<fault name="fault2" message="tns:InvalidOptionsFaultMessage"/>
|
||||
<fault name="fault3" message="tns:ResourcesCreationFaultMessage"/>
|
||||
</operation>
|
||||
|
||||
<operation name="SendReport">
|
||||
<input message="tns:SendReportInputMessage"/>
|
||||
<output message="tns:VoidMessage"/>
|
||||
<fault name="fault" message="corefaults:GCUBEFaultMessage"/>
|
||||
</operation>
|
||||
|
||||
<operation name="GetReport">
|
||||
<input message="tns:GetReportInputMessage"/>
|
||||
<output message="tns:GetReportResponseMessage"/>
|
||||
<fault name="fault1" message="tns:InvalidScopeFaultMessage"/>
|
||||
<fault name="fault2" message="tns:NoSuchReportFaultMessage"/>
|
||||
</operation>
|
||||
|
||||
</portType>
|
||||
|
||||
</definitions>
|
||||
|
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<definitions name="VREManagementTypes"
|
||||
targetNamespace="http://gcube-system.org/common/vremanagement/types"
|
||||
xmlns:tns="http://gcube-system.org/common/vremanagement/types"
|
||||
xmlns="http://schemas.xmlsoap.org/wsdl/"
|
||||
xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<!--============================================================
|
||||
|
||||
T Y P E S
|
||||
|
||||
============================================================-->
|
||||
<types>
|
||||
<xs:schema
|
||||
targetNamespace="http://gcube-system.org/common/vremanagement/types"
|
||||
xmlns:tns="http://gcube-system.org/common/vremanagement/types">
|
||||
|
||||
<!-- <xs:import namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing" schemaLocation="../../../../ws/addressing/WS-Addressing.xsd" /> -->
|
||||
<xs:import namespace="http://schemas.xmlsoap.org/ws/2004/03/addressing" schemaLocation="../ws/addressing/WS-Addressing.xsd" />
|
||||
<xs:include schemaLocation="VREManagementTypes.xsd" />
|
||||
|
||||
</xs:schema>
|
||||
</types>
|
||||
|
||||
</definitions>
|
|
@ -0,0 +1,80 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema"
|
||||
targetNamespace="http://gcube-system.org/common/vremanagement/types"
|
||||
xmlns:tns="http://gcube-system.org/common/vremanagement/types"
|
||||
xmlns:wsa="http://schemas.xmlsoap.org/ws/2004/03/addressing"
|
||||
elementFormDefault="qualified" attributeFormDefault="unqualified">
|
||||
|
||||
<xs:complexType name="DeployInfoStatus">
|
||||
<xs:sequence minOccurs="1" maxOccurs="1">
|
||||
<xs:element name="ghnID" type="xs:string"/>
|
||||
<xs:element name="packageInfo" type="tns:PackageInfoStatus"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="DeployInfo">
|
||||
<xs:sequence minOccurs="1" maxOccurs="1">
|
||||
<xs:element name="ghnID" type="xs:string"/>
|
||||
<xs:element name="packageInfo" type="tns:PackageInfo"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="Pair">
|
||||
<xs:sequence minOccurs="1" maxOccurs="1">
|
||||
<xs:element name="name" type="xs:string"/>
|
||||
<xs:element name="value" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="PackageInfo">
|
||||
<xs:sequence minOccurs="1" maxOccurs="1">
|
||||
<xs:element name="serviceName" type="xs:string"/>
|
||||
<xs:element name="serviceClass" type="xs:string"/>
|
||||
<xs:element name="serviceVersion" type="xs:string"/>
|
||||
<xs:element name="name" type="xs:string"/>
|
||||
<xs:element name="version" type="xs:string"/>
|
||||
<xs:element name="Options" type="tns:Pair" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="PackageInfoStatus">
|
||||
<xs:sequence>
|
||||
<xs:element name="package" type="tns:PackageInfo" />
|
||||
<xs:element name="status" type="xs:string"/>
|
||||
<xs:element name="message" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
<xs:complexType name="ServiceInfoStatus">
|
||||
<xs:sequence minOccurs="1" maxOccurs="1">
|
||||
<xs:element name="serviceName" type="xs:string"/>
|
||||
<xs:element name="serviceClass" type="xs:string"/>
|
||||
<xs:element name="ghnName" type="xs:string"/>
|
||||
<xs:element name="status" type="xs:string"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
|
||||
<xs:complexType name="deployMessage">
|
||||
<xs:sequence>
|
||||
<xs:element name="serviceName" type="xs:string"/>
|
||||
<xs:element name="serviceClass" type="xs:string"/>
|
||||
<xs:element name="ghnID" type="xs:string" />
|
||||
<xs:element name="Scope" type="xs:string" />
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
|
||||
<xs:complexType name="feedbackMessage">
|
||||
<xs:sequence>
|
||||
<xs:element name="callbackID" type="xs:string" />
|
||||
<xs:element name="log" type="xs:string" />
|
||||
<xs:element name="type" type="xs:string" />
|
||||
<xs:element name="runningInstanceIDsList" type="xs:string" minOccurs="0" maxOccurs="unbounded"/>
|
||||
<xs:element name="packageInfoStatus" type="tns:PackageInfoStatus" minOccurs="0" maxOccurs="unbounded"/>
|
||||
</xs:sequence>
|
||||
</xs:complexType>
|
||||
|
||||
|
||||
|
||||
</xs:schema>
|
Loading…
Reference in New Issue