diff --git a/.classpath b/.classpath index dbe47cd..7b24389 100644 --- a/.classpath +++ b/.classpath @@ -11,5 +11,6 @@ + diff --git a/CHANGELOG b/CHANGELOG deleted file mode 100644 index a02abd1..0000000 --- a/CHANGELOG +++ /dev/null @@ -1,15 +0,0 @@ -v. 1.2.3 (20-11-2009) - * Porting on gCore 0.6.0 - -v. 1.2.0 (13-05-2009) - * Porting on gCore 0.5.0 - * Fixing the loading sequence of the ScopeResource - * Dedicated ScopeResource per VO and Infrastructure - * State under persistent root folder - -v. 1.1.0 (14-11-2008) - * Management of ScopeResource, improved reporting and management of any GCUBEResource - - -v. 1.0.0 (28-09-2008) - * First release diff --git a/README b/README index 2e4e73e..b754b8f 100644 --- a/README +++ b/README @@ -13,7 +13,7 @@ Authors Version and Release Date ------------------------ -v. 1.0.0, 25/09/2008 +v. 1.0.3, 30/08/2010 Description ----------- diff --git a/changelog.xml b/changelog.xml new file mode 100644 index 0000000..e501e3f --- /dev/null +++ b/changelog.xml @@ -0,0 +1,18 @@ + + + Fixing undeployment of the same RI from different scopes + Integration of the Serialization Library of the Broker Service + + + Fixing node2missing variable's initialization in ScopeDeployedService for backwards compatibility + + + Resource Report: the GHN section reports only the packages belonging the service (post-filtering) + Resolving some issues in the communication with the Broker + Resource Report: fixed the problem preventing the report of missing/resolved dependencies + Resource Report: new global Status element stating if the Report is closed or not + + + First release + + \ No newline at end of file diff --git a/etc/deploy-jndi-config.xml b/etc/deploy-jndi-config.xml index 9da2002..e6a335b 100644 --- a/etc/deploy-jndi-config.xml +++ b/etc/deploy-jndi-config.xml @@ -19,28 +19,23 @@ value="org.gcube.vremanagement.resourcemanager.impl.brokerage.ServiceBroker" type="java.lang.String" override="false" /> - + override="false" /> --> + - - + diff --git a/etc/profile.xml b/etc/profile.xml index 5435390..5fe193f 100644 --- a/etc/profile.xml +++ b/etc/profile.xml @@ -26,13 +26,13 @@
- Service package for creating a ResourceManager instance: provide an implementation of all ResourceManager operations + ResourceManager creates and manages Scopes within a gCube infrastructure ResourceManager-service - 1.0.0 + 1.0.3 - + @@ -42,7 +42,7 @@ 1.00.00 ResourceManager-stubs - 1.00.00 + 1.0.3 false @@ -68,7 +68,7 @@ Stubs for ResourceManager: provide facilities to interact with a ResourceManager instance ResourceManager-stubs - 1.0.0 + 1.0.3 @@ -80,7 +80,7 @@ Test-suite for ResourceManager: provide sample usages of interaction with a ResourceManager instance ResourceManager-test-suite - 1.0.0 + 1.0.3 application diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/ResourceManager.java b/src/org/gcube/vremanagement/resourcemanager/impl/ResourceManager.java index 835db1d..6f2a177 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/ResourceManager.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/ResourceManager.java @@ -12,6 +12,7 @@ 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.brokerage.BrokerConnector; import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext; import org.gcube.vremanagement.resourcemanager.impl.contexts.StatefulPortTypeContext; import org.gcube.vremanagement.resourcemanager.impl.deployment.DeployerReport; @@ -34,11 +35,11 @@ import org.gcube.vremanagement.resourcemanager.impl.operators.DisposeScopeOperat 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.ResourceReport; +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.ResourceReport.OPERATION; +import org.gcube.vremanagement.resourcemanager.impl.state.Session.OPERATION; import org.globus.wsrf.NoSuchResourceException; import org.globus.wsrf.ResourceException; @@ -67,19 +68,19 @@ public class ResourceManager extends GCUBEPortType { * 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 report by invoking the {@link ResourceManager#getReport(String)} operation + * @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"); + logger.debug("AddResources operation invoked in scope " + ServiceContext.getContext().getScope().getName()); try { //checks the input scope GCUBEScope targetScope = this.validateOperationScope(resourceList.getTargetScope()); - ResourceReport report = new ResourceReport(UUIDGenFactory.getUUIDGen().nextUUID(),OPERATION.AddResources, targetScope); - this.getResource().addReport(report); + 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 report ID, it can be used to invoke the getReport operation + //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); @@ -100,8 +101,8 @@ public class ResourceManager extends GCUBEPortType { try { GCUBEScope targetScope = this.validateOperationScope(resourceList.getTargetScope()); - ResourceReport report = new ResourceReport(UUIDGenFactory.getUUIDGen().nextUUID(), OPERATION.RemoveResources, targetScope); - this.getResource().addReport(report); + 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){ @@ -132,8 +133,8 @@ public class ResourceManager extends GCUBEPortType { throw new InvalidScopeFaultType(); } try { - ResourceReport report = new ResourceReport(UUIDGenFactory.getUUIDGen().nextUUID(), OPERATION.Dispose,GCUBEScope.getScope(params.getName())); - this.getResource().addReport(report); + 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(); @@ -207,25 +208,25 @@ public class ResourceManager extends GCUBEPortType { } /** - * Receives a deployment report. It is called by the Deployer services on the GHNs contacted within the {@link #addResources(AddResourcesParameters)} + * Receives a deployment session. It is called by the Deployer services on the GHNs contacted within the {@link #addResources(AddResourcesParameters)} * operation * - * @param report the resource report - * @throws GCUBEFault if the report does not have a valid serialization + * @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 report for session " + reportMessage.getCallbackID()); + logger.info("Received session for session " + reportMessage.getCallbackID()); logger.trace("Report content: \n" + reportMessage.getReport()); try { - ResourceReport report = this.getResource().getReport(reportMessage.getCallbackID()); + Session session = this.getResource().getSession(reportMessage.getCallbackID()); DeployerReport dreport = new DeployerReport(reportMessage.getReport()); - report.addGHNReport(dreport); - report.save(); + session.addGHNReport(dreport); + session.save(); PublishedScopeResource resource = this.getResource().getPublishedScopeResource(); - logger.debug("Status report is: " + dreport.getStatus()); + 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 report is closed, declare the node as "non working" node + //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 resources = new HashSet(); @@ -238,12 +239,19 @@ public class ResourceManager extends GCUBEPortType { logger.warn("Instance " + instance.getRIID() + " not found on the IS"); } } - report.addDeployedInstances(dreport.getInstances()); + session.addDeployedInstances(dreport.getInstances()); //add the newly generated RIs to the Scope State this.getResource().getResourceList().addResources(resources); } resource.publish(); - report.save(); + 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); @@ -259,19 +267,36 @@ public class ResourceManager extends GCUBEPortType { /** * Gets a Resource Report * - * @param ID the report identifier - * @return the string serialization of the report - * @throws GNoSuchReportFaultTypeCUBEFault if the report is not found or does not have a valid serialization + * @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().getReport(ID).toXML(); + 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 * diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/Broker.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/Broker.java index 39e6c51..75b7667 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/Broker.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/Broker.java @@ -1,9 +1,11 @@ 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; /** * @@ -23,18 +25,19 @@ public interface Broker { public void initialize(GCUBEScope scope) throws Exception; /** - * Creates a deployment plan + * Creates a deployment plan for the given services + * @param session the current session * @param services the services to deploy - * @param suggestedGHNs the GHNs suggested for the deployment, if specified, only these nodes will be used by the planner + * @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(Set services, String[] suggestedGHNs) throws Exception; + public void makePlan(Session session, Set services, String[] suggestedGHNs) throws Exception; /** - * Sends feedback to the broker about the execution of the plan - * @param services the services belonging the plan + * 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(Set services) throws Exception; + public void sendFeedback(Session session) throws Exception; } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/BrokerConnector.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/BrokerConnector.java index ee0b4f6..36369e5 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/BrokerConnector.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/BrokerConnector.java @@ -7,7 +7,8 @@ import org.gcube.common.core.utils.logging.GCUBELog; import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext; /** - * Locates and connects to the current scope the Broker to use for services' deployment + * 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) * @@ -18,6 +19,12 @@ public class BrokerConnector { 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 { @@ -50,4 +57,4 @@ public class BrokerConnector { Constructor constructor = clazz.getConstructor(new Class[] {}); return (Broker) constructor.newInstance(new Object[]{}); } -} +} \ No newline at end of file diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/InternalBroker.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/InternalBroker.java index f1e7bd7..c4a189d 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/InternalBroker.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/InternalBroker.java @@ -7,10 +7,12 @@ 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; /** * @@ -40,7 +42,7 @@ public class InternalBroker implements Broker { /** * {@inheritDoc} */ - public void makePlan(Set services, String[] suggestedGHNs) throws Exception { + public void makePlan(Session session, Set services, String[] suggestedGHNs) throws Exception { this.suggestedGHNs = suggestedGHNs; for (ScopedDeployedService service : services) { try { @@ -54,11 +56,7 @@ public class InternalBroker implements Broker { } } - /** - * {@inheritDoc} - */ - public void sendFeedback(Set services) throws Exception {/* feedback is not managed by this broker*/} - + /** Selects a target node for the deployment * * @param service the service to deploy @@ -68,12 +66,16 @@ public class InternalBroker implements Broker { 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); - service.setTargetGHN(VirtualNodeManager.getNode(service.getSourceService().getGHN(),this.scope)); + 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); + 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); - service.setTargetGHN(VirtualNodeManager.getNode(this.suggestedGHNs[this.nodewalker++ % this.suggestedGHNs.length],this.scope)); + VirtualNode node = VirtualNodeManager.getNode(this.suggestedGHNs[this.nodewalker++ % this.suggestedGHNs.length],this.scope); + node.setWorkingScope(this.scope); + service.setTargetGHN(node); } else { logger.info("no GHN has been specified as explicit target"); //no GHN has been specified as explicit target @@ -81,5 +83,12 @@ public class InternalBroker implements Broker { } } + + /** + * {@inheritDoc} + */ + public void sendFeedback(Session session) throws Exception { + /* feedback is not managed by this broker*/ + } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/ServiceBroker.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/ServiceBroker.java index 7018f43..505b837 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/ServiceBroker.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/ServiceBroker.java @@ -15,10 +15,12 @@ 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.brokerage.servicebroker.PlanResponse; import org.gcube.vremanagement.resourcemanager.impl.contexts.ServiceContext; import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedService; +import org.gcube.vremanagement.resourcemanager.impl.state.Session; /** * @@ -51,18 +53,15 @@ public final class ServiceBroker implements Broker { logger.info("Broker instances found: #" + this.instances.size()); } - public void makePlan(Set services, String[] suggestedGHNs) throws Exception { + public void makePlan(Session session, Set services, String[] suggestedGHNs) throws Exception { String request = PlanRequest.create(services, suggestedGHNs, scope);; logger.debug("Request for the Broker \n" + request); - ResourceBrokerPortType pt = null; 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 { - pt = new ResourceBrokerServiceAddressingLocator().getResourceBrokerPortTypePort(endpoint); - pt = GCUBERemotePortTypeContext.getProxy(pt, this.scope, TIMEOUT, ServiceContext.getContext()); - plan = pt.getPlan(request); + try { + plan = this.getBrokerPT(endpoint).getPlan(request); logger.debug("Plan received from the broker \n" + plan); break; } catch (Exception e) { @@ -70,13 +69,27 @@ public final class ServiceBroker implements Broker { continue; } } - PlanResponse.parse(plan, services, scope); + PlanParser.parse(plan, services, scope); + session.setDeploymentPlan(plan); } - - public void sendFeedback(Set services) - throws Exception { - + /** + * {@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; + } + } } @@ -95,4 +108,10 @@ public final class ServiceBroker implements Broker { } + private ResourceBrokerPortType getBrokerPT(EndpointReferenceType endpoint) throws Exception { + ResourceBrokerPortType pt = new ResourceBrokerServiceAddressingLocator().getResourceBrokerPortTypePort(endpoint); + pt = GCUBERemotePortTypeContext.getProxy(pt, this.scope, TIMEOUT, ServiceContext.getContext()); + return pt; + } + } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/Feedback.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/Feedback.java new file mode 100644 index 0000000..2c8aa00 --- /dev/null +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/Feedback.java @@ -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 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); + } + + +} diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanParser.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanParser.java new file mode 100644 index 0000000..b370892 --- /dev/null +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanParser.java @@ -0,0 +1,70 @@ +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 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); + service.setTargetGHN(node); + break; + } + } + } + + } +} diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanRequest.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanRequest.java index 11a9689..c8b2d40 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanRequest.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanRequest.java @@ -1,80 +1,51 @@ package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker; 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; +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 { - public static String create(Set 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, a section like this: -// -// -// PkgServiceClass -// PkgServiceName -// PkgServiceVersion -// PkgPackageName -// PkgPackageVersion -// -// -// PkgServiceClass2 -// PkgServiceName2 -// PkgServiceVersion2 -// PkgPackageName2 -// PkgPackageVersion2 -// -// d5a5af20-ac50-11de-a928-ab32081f9f00 -// - for (ScopedDeployedService service : services) { - serializer.startTag(null,"PackageGroup").attribute(null, "service", service.getId()); - for (Dependency dep : service.getResolvedDependencies()) { - 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 + /** + * 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 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()); - if (suggestedGHNs != null) { - serializer.startTag(null,"GHNList"); + 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) - serializer.startTag(null,"GHN").text(ghn).endTag(null, "GHN"); - serializer.endTag(null,"GHNList"); - } - - serializer.endTag(null,"PlanRequest"); - - return request.toString(); + planReq.getGHNList().addGHN(ghn); + } + XStreamTransformer transformer = new XStreamTransformer(); + return transformer.toXML(planReq); } - - public static void main(String[] args) { - try { - System.out.println(create(new HashSet(), new String[] {"ID"}, GCUBEScope.getScope("/gcube"))); - } catch (IOException e) { - e.printStackTrace(); - } - - } - } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KFeedback.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KFeedback.java new file mode 100644 index 0000000..e83ddfc --- /dev/null +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KFeedback.java @@ -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 reports = session.getAllGHNReports(); + Set 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; + } +} diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanResponse.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KPlanParser.java similarity index 84% rename from src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanResponse.java rename to src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KPlanParser.java index 4e10724..4764195 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/PlanResponse.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KPlanParser.java @@ -1,4 +1,4 @@ -package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker; +package org.gcube.vremanagement.resourcemanager.impl.brokerage.servicebroker.kxml; import java.io.BufferedReader; import java.io.IOException; @@ -7,16 +7,31 @@ 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; -public class PlanResponse { +/** + * + * Parser for deployment plans. It uses the KXML library to parse the plan. + * + * @author Manuele Simi (ISTI-CNR) + * + */ +public final class KPlanParser { - protected static final GCUBELog logger = new GCUBELog(PlanResponse.class); - + 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 services, GCUBEScope scope) throws IOException { KXmlParser parser = new KXmlParser(); try { @@ -91,11 +106,12 @@ public class PlanResponse { for (ScopedDeployedService service : services) { if (service.getId().compareToIgnoreCase(serviceID) == 0) { logger.info("Assigning gHN " + ghnID + " to " +service); - service.setTargetGHN(VirtualNodeManager.getNode(ghnID,scope)); + VirtualNode node = VirtualNodeManager.getNode(ghnID,scope); + node.setWorkingScope(scope); + service.setTargetGHN(node); break; } - } - + } } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KPlanRequest.java b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KPlanRequest.java new file mode 100644 index 0000000..5fd3576 --- /dev/null +++ b/src/org/gcube/vremanagement/resourcemanager/impl/brokerage/servicebroker/kxml/KPlanRequest.java @@ -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 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: + // + // + // PkgServiceClass + // PkgServiceName + // PkgServiceVersion + // PkgPackageName + // PkgPackageVersion + // + // + // PkgServiceClass2 + // PkgServiceName2 + // PkgServiceVersion2 + // PkgPackageName2 + // PkgPackageVersion2 + // + // d5a5af20-ac50-11de-a928-ab32081f9f00 + // + 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(), + new String[] { "ID" }, GCUBEScope.getScope("/gcube"))); + } catch (IOException e) { + e.printStackTrace(); + } + + } + +} diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/deployment/SoftwareRepositoryRequest.java b/src/org/gcube/vremanagement/resourcemanager/impl/deployment/SoftwareRepositoryRequest.java index 85c9152..dd0ffe5 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/deployment/SoftwareRepositoryRequest.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/deployment/SoftwareRepositoryRequest.java @@ -116,8 +116,8 @@ public final class SoftwareRepositoryRequest { loop: while (true) { switch (parser.next()) { case KXmlParser.START_TAG: - if (parser.getName().equals("ResolvedDependencies")) this.parseResolvedDependencies(parser, service.getResolvedDependencies()); - if (parser.getName().equals("MissingDependencies")) this.parseMissingDependencies(parser, service.getMissingDependencies()); + 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; @@ -164,8 +164,7 @@ public final class SoftwareRepositoryRequest { * @return the dependency * @throws Exception */ - private Dependency parseDependency(KXmlParser parser) throws Exception { - logger.trace("Parsing a resolved or missing dependency..."); + private Dependency parseDependency(KXmlParser parser) throws Exception { Dependency p = new Dependency(); loop: while (true) { switch (parser.next()) { @@ -184,12 +183,16 @@ public final class SoftwareRepositoryRequest { return p; } - private void parseResolvedDependencies(KXmlParser parser, List listResolvedDeps) throws Exception { + private void parseResolvedDependencies(KXmlParser parser, ScopedDeployedService service) throws Exception { logger.trace("Parsing resolved dependencies..."); + List resolved = new ArrayList(); loop: while (true) { switch (parser.next()) { case KXmlParser.START_TAG: - if (parser.getName().equals("Dependency")) listResolvedDeps.add(this.parseDependency(parser)); + 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; @@ -197,15 +200,20 @@ public final class SoftwareRepositoryRequest { throw new Exception("Parsing failed at ResolvedDependencies"); } } - + logger.trace("Number of deps found: " + resolved.size()); + service.setResolvedDependencies(resolved); } - private void parseMissingDependencies(KXmlParser parser, List listMissingDeps) throws Exception { + private void parseMissingDependencies(KXmlParser parser, ScopedDeployedService service) throws Exception { logger.trace("Parsing missing dependencies..."); + List missing = new ArrayList(); loop: while (true) { switch (parser.next()) { case KXmlParser.START_TAG: - if (parser.getName().equals("MissingDependency")) listMissingDeps.add(this.parseDependency(parser)); + 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; @@ -213,6 +221,8 @@ public final class SoftwareRepositoryRequest { throw new Exception("Parsing failed at MissingDependencies"); } } + logger.trace("Number of deps found: " + missing.size()); + service.setMissingDependencies(missing); } /** diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/deployment/VirtualNode.java b/src/org/gcube/vremanagement/resourcemanager/impl/deployment/VirtualNode.java index aa5683a..f6e0bfe 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/deployment/VirtualNode.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/deployment/VirtualNode.java @@ -49,7 +49,7 @@ public class VirtualNode { private static final String DEPLOYER_PT_NAME = "/wsrf/services/gcube/common/vremanagement/Deployer"; - //if we do not receive a deployment report from the node after one hour, we assume that the node is not working anymore + //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, String ... name) throws NoGHNFoundException { @@ -165,12 +165,13 @@ public class VirtualNode { scope, ServiceContext.getContext()); pt.deploy(param); this.packagesToAdd.clear(); - isWorking = true;//this will prevent further requests to the ghn until the deployment report is received back + 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 */ @@ -192,12 +193,12 @@ public class VirtualNode { params.setEndpointReference(callbackEPR); EndpointReferenceType nodeEPR = new EndpointReferenceType(); nodeEPR.setAddress(new Address("http://" + this.name + DEPLOYER_PT_NAME)); - logger.trace("Undeploying from " + nodeEPR.toString()); + 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 report is received back + isWorking = true;//this will prevent further requests to the ghn until the deployment session is received back this.lastActivity = System.currentTimeMillis(); } @@ -267,14 +268,27 @@ public class VirtualNode { } /** + * Assigns a working scope to the node * @param scope the scope to set */ - public void setScope(GCUBEScope scope) { + 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 getScheduledPackages() { return this.packagesToAdd; } + + /** + * Gets the current scope used on this node + * @return the current scope + */ + public GCUBEScope getWorkingScope() { + return this.scope; + } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/deployment/VirtualNodeManager.java b/src/org/gcube/vremanagement/resourcemanager/impl/deployment/VirtualNodeManager.java index 9b5147d..93df8fd 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/deployment/VirtualNodeManager.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/deployment/VirtualNodeManager.java @@ -1,34 +1,53 @@ 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 nodes; // = new HashMap(); + private static Map nodes; /** * Gets or builds the VirtualNode - * @param callback ID the callback identifier to send to the Deployer * @param ID the node identifier * @param scope the deployment scope * @param name the node name (format has to be host:port) * @return the Virtual Node - * @throws NoGHNFoundException + * @throws NoGHNFoundException if the node does not exist */ public static VirtualNode getNode(String ID, GCUBEScope scope, String ... name) throws NoGHNFoundException { + checkNodes(); if (!nodes.containsKey(ID)) { nodes.put(ID,new VirtualNode(ID, scope, name)); - } + } return nodes.get(ID); } + /** + * Assigns the initial set of nodes to the manager. + * @param nodes the set of nodes + */ public static void setNodes(Map nodes) { VirtualNodeManager.nodes = nodes; } + /** + * Checks the set of node, must be called before any usage of nodes to check if it has been initialized + */ + private static void checkNodes(){ + if (nodes == null) + nodes = new HashMap(); + } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/deployment/resources/Dependency.java b/src/org/gcube/vremanagement/resourcemanager/impl/deployment/resources/Dependency.java index 81d12eb..8dced83 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/deployment/resources/Dependency.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/deployment/resources/Dependency.java @@ -73,8 +73,6 @@ public class Dependency { return true; if (obj == null) return false; - if (getClass() != obj.getClass()) - return false; final Dependency other = (Dependency) obj; if (name == null) { if (other.name != null) @@ -84,8 +82,8 @@ public class Dependency { if (service == null) { if (other.service != null) return false; - } else if (!service.equals(other.service)) - return false; + } else if (!service.equals(other.service)) + return false; if (version == null) { if (other.version != null) return false; diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/operators/AddResourcesOperator.java b/src/org/gcube/vremanagement/resourcemanager/impl/operators/AddResourcesOperator.java index 67657b4..3ea67ba 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/operators/AddResourcesOperator.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/operators/AddResourcesOperator.java @@ -61,8 +61,8 @@ public class AddResourcesOperator extends Operator { throw new Exception("Unable to manage the given resource(s)", e); } } - //save the report - this.configuration.report.save(); + //save the session + this.configuration.session.save(); } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/operators/DeployServiceOperator.java b/src/org/gcube/vremanagement/resourcemanager/impl/operators/DeployServiceOperator.java index 398d9ff..d97aa44 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/operators/DeployServiceOperator.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/operators/DeployServiceOperator.java @@ -10,6 +10,7 @@ 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; @@ -20,6 +21,8 @@ import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedDeployedServ 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 @@ -44,7 +47,7 @@ public class DeployServiceOperator extends Operator { public void exec() throws Exception { - this.configuration.report.save(); + this.configuration.session.save(); Set servicesToDeploy = new HashSet(); Set servicesToUndeploy = new HashSet(); @@ -76,49 +79,90 @@ public class DeployServiceOperator extends Operator { service.findResource();//resolve the service deps servicesToDeploy.add(service); } else { - service.setCallbackID(this.configuration.report.getId()); + service.setCallbackID(this.configuration.session.getId()); servicesToUndeploy.add(service); } } catch (Exception e) { logger.warn("Failed to find the service",e); } - this.configuration.report.addResource(service); - this.configuration.report.addService(service); //for the specific service section + this.configuration.session.addResource(service); + this.configuration.session.addService(service); //for the specific service section } - //create the Deployment Plan with the Resource Broker - boolean brokerSuccess = true; - try { - if (servicesToDeploy.size() > 0) { - BrokerConnector.getBroker(this.configuration.scope).makePlan(servicesToDeploy, services.getGHN()); - this.configuration.report.reportBrokerWork(true, "The Deployment Plan was successfully created"); - } - } catch (Exception e) { - brokerSuccess = false; - this.configuration.report.reportBrokerWork(false, e.getMessage()); - } - if (brokerSuccess) { + //create the Deployment Plan with the Resource Broker + if ((this.action == ACTION.ADD) && this.allocate(servicesToDeploy)) { Set resourcesToAdd = new HashSet(); for (ScopedDeployedService service : servicesToDeploy) { if (service.getStatus() != STATUS.LOST) { - service.setCallbackID(this.configuration.report.getId()); + 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.report.addResource(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); - //add/remove the services to/from the ScopeState - if(servicesToDeploy.size() > 0) - configuration.scopeState.addResources(resourcesToAdd); - if(servicesToUndeploy.size() > 0) - configuration.scopeState.removeResources(servicesToUndeploy); - } - this.configuration.report.save(); + 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 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; + } + } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/operators/DisposeScopeOperator.java b/src/org/gcube/vremanagement/resourcemanager/impl/operators/DisposeScopeOperator.java index 8db9065..1440734 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/operators/DisposeScopeOperator.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/operators/DisposeScopeOperator.java @@ -37,13 +37,13 @@ public class DisposeScopeOperator extends Operator { && (resource.getStatus() != STATUS.LOST) && (resource.getStatus() != STATUS.REMOVED)){ resources.add(resource); - this.configuration.report.addResource(resource); + this.configuration.session.addResource(resource); } } configuration.scopeState.removeResources(resources); //TODO: should we also undeploy the RM itself? - this.configuration.report.save(); + this.configuration.session.save(); } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/operators/OperatorConfig.java b/src/org/gcube/vremanagement/resourcemanager/impl/operators/OperatorConfig.java index 78323ca..341b791 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/operators/OperatorConfig.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/operators/OperatorConfig.java @@ -3,7 +3,7 @@ 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.ResourceReport; +import org.gcube.vremanagement.resourcemanager.impl.state.Session; /** * Basic configuration for every {@link Operator} @@ -13,14 +13,14 @@ import org.gcube.vremanagement.resourcemanager.impl.state.ResourceReport; */ public class OperatorConfig { - public final ResourceReport report; + public final Session session; public final GCUBEScope scope; public final ScopeState scopeState; - public OperatorConfig(ResourceReport report, ScopeState scopeState, GCUBEScope ... scope) { - this.report = report; + 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(); } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/operators/ScopedResourceManagerOperator.java b/src/org/gcube/vremanagement/resourcemanager/impl/operators/ScopedResourceManagerOperator.java index 50061cc..4255b4f 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/operators/ScopedResourceManagerOperator.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/operators/ScopedResourceManagerOperator.java @@ -35,15 +35,15 @@ public class ScopedResourceManagerOperator extends Operator { 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.getName()); + 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.getName()); + logger.info("Removing resource " + sresource.getId() + " (" + sresource.getType() + ") from scope " + this.configuration.scope.toString()); toremove.add(sresource); } - //add the resource item to the report - this.configuration.report.addResource(sresource); + //add the resource item to the session + this.configuration.session.addResource(sresource); } catch (Exception e) { logger.error("Unable to manage the resource",e); } @@ -53,7 +53,7 @@ public class ScopedResourceManagerOperator extends Operator { if(toremove.size() > 0) configuration.scopeState.removeResources(toremove); - this.configuration.report.save(); + this.configuration.session.save(); } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedDeployedService.java b/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedDeployedService.java index 43e7e82..2390a13 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedDeployedService.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedDeployedService.java @@ -1,6 +1,7 @@ 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; @@ -45,12 +46,12 @@ public final class ScopedDeployedService extends ScopedResource { /** missing dependency */ private List missing = new ArrayList(); - /** the packages deployed for this service*/ - + /** the packages deployed for this service*/ private Map > node2packages = new HashMap>(); - //private Set packages = new HashSet(); - + /** the packages deployed for this service*/ + private Map > node2missing = new HashMap>(); + private Service service; private String lastActivityOnGHN; @@ -58,6 +59,9 @@ public final class ScopedDeployedService extends ScopedResource { //the target ghn(s) private List virtualNodes = new ArrayList(); + /** maps node with the scope used when deploying there */ + private Map node2scope = new HashMap(); + /** maps RI id with the ghn id (where the instance is deployed on*/ private Map ri2ghn = new HashMap(); @@ -74,20 +78,64 @@ public final class ScopedDeployedService extends ScopedResource { } /** + * 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 getResolvedDependencies() { - return resolved; + public List getResolvedDependencies(String ghnid) { + return Collections.unmodifiableList(node2packages.get(ghnid)); } - - /** - * @return the missing dependencies + /** + * Gets the list of resolved dependencies to be used in the next deployment + * + * @return the resolved dependencies */ - public List getMissingDependencies() { - return missing; + public List 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 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 getMissingDependencies(String ghnid) { + return Collections.unmodifiableList(node2missing.get(ghnid)); + } + + /** + * Gets the list of missing dependencies for the last (failed) deployment + * + * @return the missing dependencies + */ + public List getLastMissingDependencies() { + return this.missing; + } + + /** + * Sets the list of missing dependencies for the next deployment + * + * @param dependencies the missign dependencies + */ + public void setMissingDependencies(List 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 @@ -96,13 +144,13 @@ public final class ScopedDeployedService extends ScopedResource { this.setErrorMessage(""); //empty any previous message try { request.send(); - if (this.getResolvedDependencies().size() == 0) { + if (this.resolved.size() == 0) { this.success = false; this.setErrorMessage("Invalid list of dependecies retrieved from the Software Repository"); } - if (this.getMissingDependencies().size() > 0) {//ops, some deps are missing! + 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.getMissingDependencies()); + this.setErrorMessage("The service cannot be deployed due to one or more missing dependencies: " + this.missing); } this.success = true; } catch (Exception e) { @@ -116,6 +164,7 @@ public final class ScopedDeployedService extends ScopedResource { @Override protected void addToScope() throws ResourceNotFound, Exception { + logger.trace("This service belongs to " + this.scope); if (!this.isSuccess()) { this.noHopeForMe(this.getErrorMessage(),new Exception()); } @@ -129,12 +178,20 @@ public final class ScopedDeployedService extends ScopedResource { try { for (VirtualNode node : this.virtualNodes) { node.deploy(this.getScope()); - //store packages for future undeployment - List packages = new ArrayList(); + //store packages for future undeployment and reporting purposes + List resolvedPackages = new ArrayList(); for (Dependency dep : this.resolved) - packages.add(dep); - node2packages.put(node.getID(), packages); - + resolvedPackages.add(dep); + node2packages.put(node.getID(), resolvedPackages); + //store missing packages for reporting purposes + List missingPackages = new ArrayList(); + for (Dependency dep : this.missing) + missingPackages.add(dep); + if (node2missing == null) { + logger.trace("node2missing is null"); + node2missing = new HashMap>(); // this is here for backwards compatibility + } + node2missing.put(node.getID(), missingPackages); } } catch (Exception e) { this.noHopeForMe("Unable to contact the target gHN ("+ this.lastActivityOnGHN +") where to deploy the service",e); @@ -147,6 +204,7 @@ public final class ScopedDeployedService extends ScopedResource { @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()); @@ -161,7 +219,10 @@ public final class ScopedDeployedService extends ScopedResource { try { for (VirtualNode node : this.virtualNodes) { try { - node.undeploy(this.getScope()); + 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); } @@ -178,8 +239,8 @@ public final class ScopedDeployedService extends ScopedResource { * @throws Exception if the operation fails */ public void scheduleUndeploy() { - for (VirtualNode node : this.virtualNodes) - scheduleUndeploy(node); + for (VirtualNode node : this.virtualNodes) + scheduleUndeploy(node); } /** @@ -190,6 +251,10 @@ public final class ScopedDeployedService extends ScopedResource { */ 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 deps = node2packages.get(node.getID()); Set packages = new HashSet(); @@ -214,10 +279,15 @@ public final class ScopedDeployedService extends ScopedResource { * @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) { - node.undeploy(this.getScope()); + 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; } @@ -235,7 +305,7 @@ public final class ScopedDeployedService extends ScopedResource { Set packages = new HashSet(); //prepare the input list of packagesToAdd for that GHN - List deps = this.getResolvedDependencies(); + List deps = this.resolved; for (int i = 0; i < deps.size(); i++) { PackageInfo p = new PackageInfo(); p.setServiceName(deps.get(i).getService().getName()); @@ -247,6 +317,8 @@ public final class ScopedDeployedService extends ScopedResource { 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(); } @@ -289,4 +361,20 @@ public final class ScopedDeployedService extends ScopedResource { public List 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(); + } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedResource.java b/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedResource.java index fee813e..af1a5e9 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedResource.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedResource.java @@ -98,7 +98,7 @@ public abstract class ScopedResource { break; } catch (Exception e) { logger.warn("Can't find resource "+ this + " on the IS"); - if (++i <= max_attempts) { + if (i++ <= max_attempts) { logger.warn("try again in 5 secs"); try {Thread.sleep(5000);} catch (InterruptedException e1) {} continue; diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedRunningInstance.java b/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedRunningInstance.java index e6bb45a..160d5f2 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedRunningInstance.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/resources/ScopedRunningInstance.java @@ -1,5 +1,6 @@ package org.gcube.vremanagement.resourcemanager.impl.resources; +import java.io.StringReader; import java.util.ArrayList; import java.util.List; @@ -9,8 +10,10 @@ 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.GCUBERIQuery; +import org.gcube.common.core.informationsystem.client.queries.GCUBEGenericQuery; import org.gcube.common.core.resources.GCUBERunningInstance; import org.gcube.common.core.scope.GCUBEScope; import org.gcube.common.vremanagement.ghnmanager.stubs.GHNManagerPortType; @@ -38,7 +41,7 @@ public final class ScopedRunningInstance extends ScopedResource { private String hostedOnID = ""; /** Scopes the instance belongs to */ - private List scopes; + private List scopes; protected ScopedRunningInstance(String id, GCUBEScope scope, String ... hostedOn) { super(id, TYPE, scope); @@ -51,18 +54,23 @@ public final class ScopedRunningInstance extends ScopedResource { //looks for the RI to manage try { ISClient client = GHNContext.getImplementation(ISClient.class); - GCUBERunningInstance profile = null; - GCUBERIQuery query = client.getQuery(GCUBERIQuery.class); - query.addAtomicConditions(new AtomicCondition("/ID/text()", id)); - List ris = client.execute(query, ServiceContext.getContext().getScope()); - if (ris == null || ris.size() == 0) { - ris = client.execute(query, ServiceContext.getContext().getScope().getEnclosingScope()); - if (ris == null || ris.size() == 0) { + //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 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); } } - profile = ris.get(0); - + + 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(); @@ -157,7 +165,7 @@ public final class ScopedRunningInstance extends ScopedResource { 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 in this scope: it's going to be undeployed"); + getLogger().info(this + " joins only this scope: it's going to be undeployed"); return true; } return false; @@ -191,6 +199,9 @@ public final class ScopedRunningInstance extends ScopedResource { return 40; } + + + /** * * Groups some service data diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/state/InstanceState.java b/src/org/gcube/vremanagement/resourcemanager/impl/state/InstanceState.java index 0e8a1da..a954c9b 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/state/InstanceState.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/state/InstanceState.java @@ -32,8 +32,8 @@ public final class InstanceState extends GCUBEWSResource { protected ScopeState scopeState; - /** report id -> report map*/ - static Map id2report = Collections.synchronizedMap(new HashMap());; + /** session id -> session map*/ + static Map id2session = Collections.synchronizedMap(new HashMap());; @SuppressWarnings("unchecked") @Override @@ -87,38 +87,38 @@ public final class InstanceState extends GCUBEWSResource { /** - * Gets the {@link ResourceReport} + * Gets the {@link Session} * - * @param id the report ID - * @return the report + * @param id the session ID + * @return the session * @throws IOException */ - public ResourceReport getReport(String id) throws IOException { - if (! id2report.containsKey(id)) - id2report.put(id, ResourceReport.load(id)); - return id2report.get(id); + 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 ResourceReport} + * Gets the string representation of a {@link Session} * - * @param id the report ID - * @return the string representation of the report + * @param id the session ID + * @return the string representation of the session * @throws IOException */ - public String getReportAsString(String id) throws IOException { - return ResourceReport.loadAsString(id); + public String getSerializedSession(String id) throws IOException { + return Session.loadAsString(id); } /** - * Adds a new {@link ResourceReport} to the service's state + * Adds a new {@link Session} to the service's state * - * @param report the report to add + * @param session the session to add */ - public void addReport(ResourceReport report) { - this.getResourceList().setLastReport(report); - id2report.put(report.getId(), report); + public void addSession(Session session) { + this.getResourceList().setLastSession(session); + id2session.put(session.getId(), session); } /** diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/state/ScopeState.java b/src/org/gcube/vremanagement/resourcemanager/impl/state/ScopeState.java index 38ec02f..2bd778f 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/state/ScopeState.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/state/ScopeState.java @@ -32,7 +32,7 @@ public class ScopeState extends Observable { private RawScopeState rawState; - private ResourceReport report; + private Session report; protected ScopeState() {} @@ -298,18 +298,18 @@ public class ScopeState extends Observable { } /** - * Gets the last active {@link ResourceReport} - * @return the report + * Gets the last active {@link Session} + * @return the session */ - public ResourceReport getLastReport() { + public Session getLastReport() { return this.report; } /** - * Sets the last active {@link ResourceReport} - * @param report the report + * Sets the last active {@link Session} + * @param session the session */ - public void setLastReport(ResourceReport report) { + public void setLastSession(Session report) { this.report = report; } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/state/ResourceReport.java b/src/org/gcube/vremanagement/resourcemanager/impl/state/Session.java similarity index 77% rename from src/org/gcube/vremanagement/resourcemanager/impl/state/ResourceReport.java rename to src/org/gcube/vremanagement/resourcemanager/impl/state/Session.java index b579bdd..b4949f3 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/state/ResourceReport.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/state/Session.java @@ -28,12 +28,14 @@ import org.gcube.vremanagement.resourcemanager.impl.resources.ScopedResource.STA import org.kxml2.io.KXmlSerializer; /** - * Integrated deployment report. It collects the report sent by the Deployer Service and build a single integrated report + * 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 ResourceReport implements Serializable { +public class Session implements Serializable { protected final GCUBELog logger = new GCUBELog(this, ServiceContext.getContext()); @@ -63,7 +65,7 @@ public class ResourceReport implements Serializable { /** Status of a dependency resolver request */ public enum DEPSTATUS {SUCCESS, FAILED}; - public enum OPERATION {AddResources, UpdateResource, RemoveResources, Dispose, Create}; + public enum OPERATION {Create, AddResources, UpdateResources, RemoveResources, Dispose}; private Set services = Collections.synchronizedSet(new HashSet()); @@ -71,15 +73,17 @@ public class ResourceReport implements Serializable { /** the instances deployed by the services included in this report*/ private Set instances = new HashSet(); + + private String deploymentPlan; - /** internally used by {@link ResourceReport#loadAsString(String)}*/ - private ResourceReport () {} + /** internally used by {@link Session#loadAsString(String)}*/ + private Session () {} /** * Builds a new empty report * @param id the session ID assigned to the operation */ - public ResourceReport(String id, OPERATION operation, GCUBEScope ... scope) { + public Session(String id, OPERATION operation, GCUBEScope ... scope) { this.id = id; this.operation = operation; if ((scope == null)|| (scope[0] == null)) @@ -117,8 +121,9 @@ public class ResourceReport implements Serializable { //serializer.setProperty(XmlSerializer, "\t"); try { serializer.startDocument("UTF-8", true); - serializer.startTag(NS,"ResourceReport"); + serializer.startTag(NS,"Session"); 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"); @@ -160,7 +165,7 @@ public class ResourceReport implements Serializable { 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().size() > 0) || (service.getErrorMessage().length() > 0) ) { + 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"); @@ -172,7 +177,7 @@ public class ResourceReport implements Serializable { serializer.startTag(NS,"DependenciesResolution"); //resolved dependencies serializer.startTag(NS,"ResolvedDependencies"); - for (Dependency dep : service.getResolvedDependencies()) { + 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"); @@ -184,7 +189,7 @@ public class ResourceReport implements Serializable { serializer.endTag(NS,"ResolvedDependencies"); //missing dependencies serializer.startTag(NS,"MissingDependencies"); - for (Dependency dep : service.getMissingDependencies()) { + 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"); @@ -209,7 +214,7 @@ public class ResourceReport implements Serializable { 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)); + this.addGHNReport(serializer, node2report.get(reportID), service); serializer.endTag(NS, "LastReportReceived"); serializer.endTag(NS,"GHN"); DeployedRunningInstance instance = this.getInstanceForService(service); @@ -226,12 +231,12 @@ public class ResourceReport implements Serializable { } 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 instance of this service on the target gHN").endTag(NS,"Message"); + 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()) + if (service.isSuccess() && (this.brokerReportAvailable)) serializer.text("The report is still not available for this service"); else serializer.text("No report"); @@ -242,17 +247,15 @@ public class ResourceReport implements Serializable { else serializer.endTag(NS,"UndeploymentActivity"); - - serializer.endTag(NS,"Service"); } serializer.endTag(NS,"Services"); - serializer.endTag(NS,"ResourceReport"); + serializer.endTag(NS,"Session"); 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"); + throw new IOException("The Resource Report does not have a valid serialisation "+ e.getMessage()); } finally { report.close(); @@ -314,8 +317,8 @@ public class ResourceReport implements Serializable { * @return the report * @throws IOException if the report does not have a valid serialization */ - protected static ResourceReport load(String id) throws IOException { - ResourceReport report = new ResourceReport(); + protected static Session load(String id) throws IOException { + Session report = new Session(); // load the report from its serialization return report; @@ -352,19 +355,20 @@ public class ResourceReport implements Serializable { } - private void addGHNReport(KXmlSerializer serializer, DeployerReport report) throws Exception { - + private void addGHNReport(KXmlSerializer serializer, DeployerReport report, ScopedDeployedService service) throws Exception { serializer.startTag(NS, "Packages"); for (DeployedDependency dep: report.getDependencies()) { - 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"); + 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"); @@ -389,5 +393,71 @@ public class ResourceReport implements Serializable { 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 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 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; + } } diff --git a/src/org/gcube/vremanagement/resourcemanager/impl/state/observers/Executor.java b/src/org/gcube/vremanagement/resourcemanager/impl/state/observers/Executor.java index 8069876..1a4a6c4 100644 --- a/src/org/gcube/vremanagement/resourcemanager/impl/state/observers/Executor.java +++ b/src/org/gcube/vremanagement/resourcemanager/impl/state/observers/Executor.java @@ -52,8 +52,8 @@ public class Executor extends ScopeObserver { ScopedDeployedService service = ScopedResourceFactory.getRelatedService((ScopedRunningInstance)resource); if (service.getNodes().size() > 1) { logger.debug("Removing " + service + " from node " + resource.getHostedOn()); - //there exists other instances of the service in the scope, we are going to remove only this one - service.scheduleUndeploy(VirtualNodeManager.getNode(hostedOnID, scopeState.getScope())); + //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); diff --git a/src/org/gcube/vremanagement/resourcemanager/stubs/testsuite/DisposeScopeTest.java b/src/org/gcube/vremanagement/resourcemanager/stubs/testsuite/DisposeScopeTest.java index 9551013..22a3f67 100644 --- a/src/org/gcube/vremanagement/resourcemanager/stubs/testsuite/DisposeScopeTest.java +++ b/src/org/gcube/vremanagement/resourcemanager/stubs/testsuite/DisposeScopeTest.java @@ -36,7 +36,7 @@ public class DisposeScopeTest { String reportID = pt.disposeScope(new DisposeScopeParameters(args[2])); logger.info("Returned report ID: " + reportID); } catch (Exception e) { - logger.fatal("Failed to create VRE",e); + logger.fatal("Failed to dispose the VRE",e); } } diff --git a/test-suite/samples/add.metadata.properties b/test-suite/samples/add.metadata.properties index 2a25854..7ff71cd 100644 --- a/test-suite/samples/add.metadata.properties +++ b/test-suite/samples/add.metadata.properties @@ -10,9 +10,11 @@ callerScope=/gcube/devsec/CNR-VRE service.1.name=MetadataManager service.1.class=MetadataManagement service.1.version=1.00.00 +service.1.GHN=ccc70030-6225-11df-b8c4-c9bf4572cf57 service.2.name=XMLIndexer service.2.class=MetadataManagement service.2.version=1.00.00 +service.2.GHN=ccc70030-6225-11df-b8c4-c9bf4572cf57 #GHNID(s) on which the services will be deployed -GHNSet=233ecf30-5f77-11df-a7f3-937828a57691 +#GHNSet= diff --git a/test-suite/samples/create.VRE.properties b/test-suite/samples/create.VRE.properties index 9a497c6..81ea94f 100644 --- a/test-suite/samples/create.VRE.properties +++ b/test-suite/samples/create.VRE.properties @@ -35,4 +35,4 @@ service.2.class=MetadataManagement service.2.version=1.00.00 #GHNID(s) on which the services will be deployed -GHNSet=c0b5e940-5f6f-11df-85bd-da352f223a9e +GHNSet=b82c3290-62d3-11df-bf23-e96f2ebe5fa6 diff --git a/test-suite/samples/scopeoptions.properties b/test-suite/samples/scopeoptions.properties index 180b90c..a62edb2 100644 --- a/test-suite/samples/scopeoptions.properties +++ b/test-suite/samples/scopeoptions.properties @@ -1,11 +1,12 @@ -callerScope=/gcube/devsec/FAO-VRE +callerScope=/d4science.research-infrastructures.eu/FARM/ICIS # scope options -creator=CN=Manuele Simi, L=NMIS-ISTI, OU=Personal Certificate, O=INFN, C=IT -designer=CN=Manuele Simi, L=NMIS-ISTI, OU=Personal Certificate, O=INFN, C=IT +creator=anton.ellenbroek +designer=andrea.manzi securityenabled=false -displayName=FAO-VRE -description=Sample VRE for FAO -#startTime=2008-11-27T16:58:12+01:00 +displayName=ICIS +description=Integrated Capture Information System (ICIS)VRE
Purpose: Facilitate the collection, curation and dissimination of Fisheries statistics
Target audience: Fishery statisticians, marine biologists
Implementation:
ICIS offers fisheries statisticians a set of tools to manage their data.Statisticians produce statistics from often very different data sources, and need a controlled process for the ingestion, validation, transformation, comparison and exploitation of statistical data for the fisheries captures domain. There is a need to:
  • Collect and analyze capture data;
  • Check and control data and data-quality;
  • Produce uniform data-sets for consumption by outside clients, such as the FishStatJ application;
  • Provide an authoritative data-repository for fisheries data.

Also, there is a growing interest to share data and use statistical data in other use-scenarios, such as spatial analysis or reporting. The D4Science grid e-Infrastructure offers not only collaborative and computing advantages, but also promises to ease the difficult transformations from one reporting framework to another. +startTime=2010-06-07T18:42:49+02:00 +endTime=2012-06-07T18:42:49+02:00 diff --git a/test-suite/setscopeoptions.sh b/test-suite/setscopeoptions.sh index 778bc19..5053a98 100755 --- a/test-suite/setscopeoptions.sh +++ b/test-suite/setscopeoptions.sh @@ -1 +1 @@ -java -cp .:./lib/org.gcube.resourcemanagement.manager.testsuite.jar:$CLASSPATH org/gcube/vremanagement/vremanager/stubs/testsuite/SetScopeOptionsTest $1 $2 $3 +java -cp .:./lib/org.gcube.resourcemanagement.manager.testsuite.jar:$CLASSPATH org/gcube/vremanagement/resourcemanager/stubs/testsuite/SetScopeOptionsTest $1 $2 $3