diff --git a/.classpath b/.classpath new file mode 100644 index 0000000..953de0b --- /dev/null +++ b/.classpath @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/.project b/.project new file mode 100644 index 0000000..4b4674f --- /dev/null +++ b/.project @@ -0,0 +1,23 @@ + + + resource-registry-handlers + + + + + + org.eclipse.jdt.core.javabuilder + + + + + org.eclipse.m2e.core.maven2Builder + + + + + + org.eclipse.jdt.core.javanature + org.eclipse.m2e.core.maven2Nature + + diff --git a/.settings/org.eclipse.jdt.core.prefs b/.settings/org.eclipse.jdt.core.prefs new file mode 100644 index 0000000..ec4300d --- /dev/null +++ b/.settings/org.eclipse.jdt.core.prefs @@ -0,0 +1,5 @@ +eclipse.preferences.version=1 +org.eclipse.jdt.core.compiler.codegen.targetPlatform=1.7 +org.eclipse.jdt.core.compiler.compliance=1.7 +org.eclipse.jdt.core.compiler.problem.forbiddenReference=warning +org.eclipse.jdt.core.compiler.source=1.7 diff --git a/.settings/org.eclipse.m2e.core.prefs b/.settings/org.eclipse.m2e.core.prefs new file mode 100644 index 0000000..f897a7f --- /dev/null +++ b/.settings/org.eclipse.m2e.core.prefs @@ -0,0 +1,4 @@ +activeProfiles= +eclipse.preferences.version=1 +resolveWorkspaceProjects=true +version=1 diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..1380fb4 --- /dev/null +++ b/pom.xml @@ -0,0 +1,81 @@ + + 4.0.0 + org.gcube.smartgears.handlers + resource-registry-handlers + 1.0.0-SNAPSHOT + Resource Registry Handler + + + + + org.gcube.distribution + gcube-bom + LATEST + pom + import + + + org.gcube.distribution + maven-smartgears-bom + LATEST + pom + import + + + + + + + org.gcube.information-system + resource-registry-publisher + + + + org.gcube.information-system + resource-registry-client + + + + org.gcube.core + common-events + + + + org.gcube.core + common-smartgears + + + + org.gcube.information-system + information-system-model + + + + org.gcube.information-system + gcube-resources + + + + javax.servlet + javax.servlet-api + 3.0.1 + provided + + + + + + ${artifactId} + + + maven-compiler-plugin + 2.3.2 + + 1.7 + 1.7 + + + + + \ No newline at end of file diff --git a/src/main/java/org/gcube/smartgears/handler/resourceregistry/Constants.java b/src/main/java/org/gcube/smartgears/handler/resourceregistry/Constants.java new file mode 100644 index 0000000..83a6d37 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handler/resourceregistry/Constants.java @@ -0,0 +1,34 @@ +package org.gcube.smartgears.handler.resourceregistry; + +import org.gcube.informationsystem.model.entity.resource.EService; +import org.gcube.informationsystem.model.entity.resource.HostingNode; + +/** + * Library-wide constants. + * + * + * @author Fabio Simeoni + * + */ +public class Constants { + + + public static final String HOSTING_NODE_PROPERTY = HostingNode.NAME; + + + /** + * The configuration name of {@link EServiceManager} and {@link HostingNodeManager}. + */ + public static final String RESOURCE_MANAGEMENT = "resource-management"; + + + + /** + * The name of the context property that contains the EService Resource. + */ + public static final String ESERVICE_PROPERTY = EService.NAME; + + public static final long default_container_publication_frequency_in_seconds = 60; + + public static final int application_republish_frequency_in_minutes = 20; +} diff --git a/src/main/java/org/gcube/smartgears/handler/resourceregistry/EServiceManager.java b/src/main/java/org/gcube/smartgears/handler/resourceregistry/EServiceManager.java new file mode 100644 index 0000000..2b61f99 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handler/resourceregistry/EServiceManager.java @@ -0,0 +1,593 @@ +package org.gcube.smartgears.handler.resourceregistry; + +import static org.gcube.common.events.Observes.Kind.resilient; +import static org.gcube.smartgears.handler.resourceregistry.Constants.ESERVICE_PROPERTY; +import static org.gcube.smartgears.handler.resourceregistry.Constants.RESOURCE_MANAGEMENT; +import static org.gcube.smartgears.handlers.ProfileEvents.addToContext; +import static org.gcube.smartgears.handlers.ProfileEvents.removeFromContext; +import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.activation; +import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.failure; +import static org.gcube.smartgears.lifecycle.application.ApplicationLifecycle.stop; +import static org.gcube.smartgears.utils.Utils.rethrowUnchecked; + +import java.net.URI; +import java.util.Arrays; +import java.util.List; +import java.util.Set; +import java.util.UUID; +import java.util.concurrent.ScheduledFuture; +import java.util.concurrent.TimeUnit; + +import javax.servlet.ServletRegistration; +import javax.xml.bind.annotation.XmlRootElement; + +import org.gcube.common.authorization.client.proxy.AuthorizationProxy; +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.events.Observes; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.informationsystem.impl.embedded.HeaderImpl; +import org.gcube.informationsystem.impl.embedded.PropagationConstraintImpl; +import org.gcube.informationsystem.impl.embedded.ValueSchemaImpl; +import org.gcube.informationsystem.impl.entity.facet.AccessPointFacetImpl; +import org.gcube.informationsystem.impl.entity.facet.ServiceStateFacetImpl; +import org.gcube.informationsystem.impl.entity.facet.SoftwareFacetImpl; +import org.gcube.informationsystem.impl.entity.resource.EServiceImpl; +import org.gcube.informationsystem.impl.relation.ConsistsOfImpl; +import org.gcube.informationsystem.impl.relation.IsIdentifiedByImpl; +import org.gcube.informationsystem.impl.relation.isrelatedto.HostsImpl; +import org.gcube.informationsystem.model.embedded.Header; +import org.gcube.informationsystem.model.embedded.PropagationConstraint; +import org.gcube.informationsystem.model.embedded.PropagationConstraint.AddConstraint; +import org.gcube.informationsystem.model.embedded.PropagationConstraint.RemoveConstraint; +import org.gcube.informationsystem.model.embedded.ValueSchema; +import org.gcube.informationsystem.model.entity.Facet; +import org.gcube.informationsystem.model.entity.Resource; +import org.gcube.informationsystem.model.entity.facet.AccessPointFacet; +import org.gcube.informationsystem.model.entity.facet.ServiceStateFacet; +import org.gcube.informationsystem.model.entity.facet.SoftwareFacet; +import org.gcube.informationsystem.model.entity.resource.EService; +import org.gcube.informationsystem.model.entity.resource.HostingNode; +import org.gcube.informationsystem.model.relation.ConsistsOf; +import org.gcube.informationsystem.model.relation.IsIdentifiedBy; +import org.gcube.informationsystem.model.relation.IsRelatedTo; +import org.gcube.informationsystem.model.relation.isrelatedto.Hosts; +import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceAlreadyPresentException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException; +import org.gcube.informationsystem.resourceregistry.client.proxy.Direction; +import org.gcube.informationsystem.resourceregistry.client.proxy.ResourceRegistryClient; +import org.gcube.informationsystem.resourceregistry.client.proxy.ResourceRegistryClientFactory; +import org.gcube.informationsystem.resourceregistry.publisher.proxy.ResourceRegistryPublisher; +import org.gcube.informationsystem.resourceregistry.publisher.proxy.ResourceRegistryPublisherFactory; +import org.gcube.smartgears.configuration.application.ApplicationConfiguration; +import org.gcube.smartgears.configuration.container.ContainerConfiguration; +import org.gcube.smartgears.context.Property; +import org.gcube.smartgears.context.application.ApplicationContext; +import org.gcube.smartgears.handlers.application.ApplicationLifecycleEvent; +import org.gcube.smartgears.handlers.application.ApplicationLifecycleHandler; +import org.gcube.smartgears.lifecycle.application.ApplicationLifecycle; +import org.gcube.smartgears.lifecycle.application.ApplicationState; +import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; +import org.gcube.smartgears.provider.ProviderFactory; +import org.gcube.smartgears.utils.Utils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Manages the {@link EService} {@link Resource} of the application. + *

+ * The manager: + *

+ *

+ * + * @author Luca Frosini + */ +@XmlRootElement(name = RESOURCE_MANAGEMENT) +public class EServiceManager extends ApplicationLifecycleHandler { + + private static final Logger logger = LoggerFactory + .getLogger(EServiceManager.class); + + private ApplicationContext applicationContext; + private AuthorizationProxy authorizationProxy; + private ScheduledFuture periodicUpdates; + + private static List servletExcludes = Arrays.asList("default","jsp"); + + public EServiceManager() { + super(); + this.authorizationProxy = ProviderFactory.provider() + .authorizationProxy(); + } + + private void setContextFromToken(String token) { + if (token == null || token.compareTo("") == 0) { + SecurityTokenProvider.instance.reset(); + ScopeProvider.instance.reset(); + } else { + SecurityTokenProvider.instance.set(token); + String scope = getCurrentContextName(token); + ScopeProvider.instance.set(scope); + } + + } + + @Override + public void onStart(ApplicationLifecycleEvent.Start e) { + this.applicationContext = e.context(); + EService eService = instantiateEService(); + eService = publishEservice(eService); + registerObservers(); + schedulePeriodicUpdates(); + } + + private void share(EService eService) { + logger.trace("sharing EService for {}", applicationContext.name()); + applicationContext.properties().add( + new Property(ESERVICE_PROPERTY, eService)); + } + + // helpers + private void registerObservers() { + + applicationContext.events().subscribe(new Object() { + + @Observes({ activation, stop, failure }) + void onChanged(ApplicationLifecycle lc) { + String state = lc.state().remoteForm().toLowerCase(); + logger.debug("Moving app {} to {}", applicationContext.name(), + state); + EService eService = applicationContext.properties().lookup(Constants.ESERVICE_PROPERTY).value(EService.class); + createOrUpdateServiceStateFacet(eService, state); + } + + @Observes(value = addToContext) + void addTo(String token) { + EService eService = applicationContext.properties().lookup(Constants.ESERVICE_PROPERTY).value(EService.class); + addToContext(eService, token); + } + + @Observes(value = removeFromContext) + void removeFrom(String token) { + EService eService = applicationContext.properties().lookup(Constants.ESERVICE_PROPERTY).value(EService.class); + removeFromContext(eService, token); + } + }); + } + + private void schedulePeriodicUpdates() { + + // register to cancel updates + applicationContext.events().subscribe( + + new Object() { + + // we register it in response to lifecycle events so that we can + // stop and resume along with application + @Observes(value = { activation }, kind = resilient) + synchronized void restartPeriodicUpdates( + final ApplicationLifecycle lc) { + + // already running + if (periodicUpdates != null) { + return; + } + + if (lc.state() == ApplicationState.active) { + logger.info( + "scheduling periodic updates of application {} EService", + applicationContext.name()); + } else { + logger.info( + "resuming periodic updates of application {} EService", + applicationContext.name()); + } + + final Runnable updateTask = new Runnable() { + public void run() { + EService eService = applicationContext.properties().lookup(Constants.ESERVICE_PROPERTY).value(EService.class); + try { + String state = lc.state().remoteForm() + .toLowerCase(); + createOrUpdateServiceStateFacet(eService, state); + } catch (Exception e) { + logger.error( + "cannot complete periodic update of EService", + e); + } + } + }; + + periodicUpdates = Utils.scheduledServicePool + .scheduleAtFixedRate( + updateTask, + Constants.application_republish_frequency_in_minutes, + Constants.application_republish_frequency_in_minutes, + TimeUnit.MINUTES); + + } + + @Observes(value = { stop, failure }, kind = resilient) + synchronized void cancelPeriodicUpdates(ContainerLifecycle ignore) { + + if (periodicUpdates != null) { + logger.trace( + "stopping periodic updates of application {} EService", + applicationContext.name()); + + try { + periodicUpdates.cancel(true); + periodicUpdates = null; + } catch (Exception e) { + logger.warn( + "could not stop periodic updates of application {} EService", + applicationContext.name(), e); + } + } + } + + }); + + } + + + @SuppressWarnings("unchecked") + private void createHostsRelation(EService eService, + ResourceRegistryPublisher resourceRegistryPublisher) { + HostingNode hostingNode = applicationContext.container().properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class); + + if (hostingNode != null) { + + ResourceRegistryClient resourceRegistryClient = ResourceRegistryClientFactory.create(); + + Hosts hosts = null; + + try { + List resources = resourceRegistryClient.getInstancesFromEntity(Hosts.NAME, false, hostingNode.getHeader().getUUID(), Direction.out); + for(Resource resource : resources){ + if(resource instanceof HostingNode && resource.getHeader().getUUID().compareTo(hostingNode.getHeader().getUUID())==0){ + List> isRelatedToList = resource.getIsRelatedTo(); + for (IsRelatedTo isRelatedTo : isRelatedToList) { + if (isRelatedTo instanceof Hosts) { + if (isRelatedTo.getTarget().getHeader().getUUID() + .compareTo(eService.getHeader().getUUID()) == 0) { + hosts = (Hosts) isRelatedTo; + break; + } + } + } + } + } + + }catch (Exception e) { + logger.error("Error while trying to retrieve Hosts relation", e); + } + + if (hosts == null) { + + PropagationConstraint propagationConstraint = new PropagationConstraintImpl(); + propagationConstraint + .setRemoveConstraint(RemoveConstraint.cascade); + propagationConstraint + .setAddConstraint(AddConstraint.propagate); + + hosts = new HostsImpl<>(hostingNode, eService, + propagationConstraint); + + try { + hosts = resourceRegistryPublisher.createIsRelatedTo( + Hosts.class, hosts); + } catch (ResourceNotFoundException e) { + logger.error("THIS IS REALLY STRANGE. YOU SHOULD NE BE HERE. Error while creating {}.", hosts, e); + } catch (ResourceRegistryException e) { + logger.error("Error while creating {}", hosts, e); + } + } + } + } + + private EService createEServiceAndHosts( + ResourceRegistryPublisher resourceRegistryPublisher, + EService eService) throws ResourceRegistryException { + try { + eService = resourceRegistryPublisher.createResource(EService.class, + eService); + } catch (ResourceAlreadyPresentException e) { + ResourceRegistryClient registryClient = ResourceRegistryClientFactory + .create(); + eService = registryClient.getInstance(EService.class, eService + .getHeader().getUUID()); + } + + try { + createHostsRelation(eService, resourceRegistryPublisher); + } catch (Exception ex) { + logger.error( + "Unable to Create {} relation from {} to {} ({} : {})", + Hosts.NAME, HostingNode.NAME, EService.NAME, + applicationContext.name(), eService.getHeader().getUUID(), + ex); + } + + return eService; + } + + private EService publishEservice(EService eService) { + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + String previousToken = SecurityTokenProvider.instance.get(); + try { + Thread.currentThread().setContextClassLoader( + EServiceManager.class.getClassLoader()); + + boolean create = true; + + Set startTokens = applicationContext.configuration() + .startTokens(); + for (String token : startTokens) { + setContextFromToken(token); + + try { + ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory + .create(); + if (create) { + + eService = createEServiceAndHosts( + resourceRegistryPublisher, eService); + + create = false; + + } else { + boolean added = resourceRegistryPublisher + .addResourceToContext(eService); + + if (added) { + logger.info( + "{} successfully added to current context ({})", + eService, getCurrentContextName(token)); + share(eService); + } else { + logger.error( + "Unable to add {} to current context ({})", + eService, getCurrentContextName(token)); + } + } + + share(eService); + + } catch (ResourceRegistryException e) { + logger.error("Unable to add {} to current context ({})", + eService, getCurrentContextName(token), e); + } + + } + + } catch (Exception e) { + rethrowUnchecked(e); + } finally { + setContextFromToken(previousToken); + Thread.currentThread().setContextClassLoader(contextCL); + } + + return eService; + + } + + private String getCurrentContextName(String token) { + try { + return this.authorizationProxy.get(token).getContext(); + } catch (Exception e) { + logger.error("Error retrieving token {}, it should never happen", + token); + return null; + } + } + + private void removeFromContext(EService eService, String token) { + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + String previousToken = SecurityTokenProvider.instance.get(); + try { + Thread.currentThread().setContextClassLoader( + EServiceManager.class.getClassLoader()); + setContextFromToken(token); + + boolean removed = false; + + ResourceRegistryPublisher resourceRegistryPublisher = + ResourceRegistryPublisherFactory.create(); + removed = resourceRegistryPublisher + .removeResourceFromContext(eService); + + if (removed) { + logger.info( + "{} successfully removed from current context ({})", + eService, getCurrentContextName(token)); + share(eService); + } else { + logger.error("Unable to remove {} from current context ({})", + eService, getCurrentContextName(token)); + } + + share(eService); + + } catch (Exception e) { + logger.error("Unable to remove {} from current context ({})", + eService, getCurrentContextName(token), e); + rethrowUnchecked(e); + } finally { + setContextFromToken(previousToken); + Thread.currentThread().setContextClassLoader(contextCL); + } + } + + private void addToContext(EService eService, String token) { + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + String previousToken = SecurityTokenProvider.instance.get(); + try { + Thread.currentThread().setContextClassLoader( + EServiceManager.class.getClassLoader()); + setContextFromToken(token); + + ResourceRegistryPublisher resourceRegistryPublisher = + ResourceRegistryPublisherFactory.create(); + boolean added = resourceRegistryPublisher + .addResourceToContext(eService); + + if (added) { + logger.info("{} successfully added to current context ({})", + eService, getCurrentContextName(token)); + share(eService); + } else { + logger.error("Unable to add {} to current context ({})", + eService, getCurrentContextName(token)); + } + + share(eService); + + } catch (Exception e) { + logger.error("Unable to add {} to current context ({})", eService, + getCurrentContextName(token), e); + rethrowUnchecked(e); + } finally { + setContextFromToken(previousToken); + Thread.currentThread().setContextClassLoader(contextCL); + } + } + + private void createOrUpdateServiceStateFacet(EService eService, String state) { + + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + String previousToken = SecurityTokenProvider.instance.get(); + try { + + if (previousToken == null) { + setContextFromToken((String) applicationContext.configuration() + .startTokens().toArray()[0]); + } + Thread.currentThread().setContextClassLoader( + EServiceManager.class.getClassLoader()); + + ServiceStateFacet serviceStateFacet = null; + + List> consistsOfList = eService + .getConsistsOf(); + for (ConsistsOf c : consistsOfList) { + if (c.getTarget() instanceof ServiceStateFacet) { + serviceStateFacet = (ServiceStateFacet) c.getTarget(); + break; + } + } + + ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory + .create(); + try { + serviceStateFacet.setValue(state); + serviceStateFacet = resourceRegistryPublisher.updateFacet( + ServiceStateFacet.class, serviceStateFacet); + + } catch (Exception e) { + try { + ConsistsOf consistsOf = new ConsistsOfImpl( + eService, serviceStateFacet, null); + @SuppressWarnings("unchecked") + ConsistsOf createdConsistsOf = resourceRegistryPublisher.createConsistsOf(ConsistsOf.class, consistsOf); + + eService.addFacet(createdConsistsOf); + } catch (Exception ex) { + eService = createEServiceAndHosts( + resourceRegistryPublisher, eService); + } + } + + share(eService); + + } catch (Exception e) { + rethrowUnchecked(e); + } finally { + setContextFromToken(previousToken); + Thread.currentThread().setContextClassLoader(contextCL); + } + + } + + private EService instantiateEService() { + logger.info("Creating EService for {}", applicationContext.name()); + + ApplicationConfiguration applicationConfiguration = applicationContext + .configuration(); + + UUID uuid = UUID.fromString(this.applicationContext.id()); + EService eService = new EServiceImpl(); + Header header = new HeaderImpl(uuid); + eService.setHeader(header); + + SoftwareFacet softwareFacet = new SoftwareFacetImpl(); + softwareFacet.setDescription(applicationConfiguration.description()); + softwareFacet.setGroup(applicationConfiguration.serviceClass()); + softwareFacet.setName(applicationConfiguration.name()); + softwareFacet.setVersion(applicationConfiguration.version()); + + IsIdentifiedBy isIdentifiedBy = new IsIdentifiedByImpl( + eService, softwareFacet, null); + eService.addFacet(isIdentifiedBy); + + ApplicationConfiguration configuration = applicationContext.configuration(); + ContainerConfiguration container = applicationContext.container().configuration(); + + String baseAddress; + if (configuration.proxied()){ + String protocol = container.proxyAddress().secure()? "https://": "http://"; + int port = container.proxyAddress().port(); + baseAddress=String.format("%s%s:%d%s", protocol , container.proxyAddress().hostname(), port,applicationContext.application().getContextPath()); + } else { + String protocol = configuration.secure()? "https://": "http://"; + int port = configuration.secure()?container.securePort(): container.port(); + baseAddress=String.format("%s%s:%d%s", protocol , container.hostname(), port,applicationContext.application().getContextPath()); + } + + + for (ServletRegistration servlet : applicationContext.application() + .getServletRegistrations().values()) { + if (!servletExcludes.contains(servlet.getName())) { + for (String mapping : servlet.getMappings()) { + + + /*String address = ProfileBuilder.getAddressFromBaseAddress( + baseAddress, mapping); + */ + String address = baseAddress+(mapping.endsWith("*")?mapping.substring(0,mapping.length()-2):mapping); + + AccessPointFacet accessPointFacet = new AccessPointFacetImpl(); + accessPointFacet.setEntryName(servlet.getName()); + accessPointFacet.setEndpoint(URI.create(address)); + ValueSchema valueSchema = new ValueSchemaImpl(); + valueSchema.setValue("gcube-token"); + + accessPointFacet.setAuthorization(valueSchema); + + eService.addFacet(accessPointFacet); + } + } + } + + ServiceStateFacet serviceStateFacet = new ServiceStateFacetImpl(); + String state = applicationContext.lifecycle().state().remoteForm() + .toLowerCase(); + serviceStateFacet.setValue(state.toLowerCase()); + eService.addFacet(serviceStateFacet); + + return eService; + } + + @Override + public String toString() { + return RESOURCE_MANAGEMENT; + } + +} diff --git a/src/main/java/org/gcube/smartgears/handler/resourceregistry/HostingNodeManager.java b/src/main/java/org/gcube/smartgears/handler/resourceregistry/HostingNodeManager.java new file mode 100644 index 0000000..d552de8 --- /dev/null +++ b/src/main/java/org/gcube/smartgears/handler/resourceregistry/HostingNodeManager.java @@ -0,0 +1,807 @@ +package org.gcube.smartgears.handler.resourceregistry; + +import static java.util.concurrent.TimeUnit.SECONDS; +import static org.gcube.common.events.Observes.Kind.resilient; +import static org.gcube.smartgears.handlers.ProfileEvents.addToContext; +import static org.gcube.smartgears.handlers.ProfileEvents.removeFromContext; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.activation; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.failure; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.part_activation; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.shutdown; +import static org.gcube.smartgears.lifecycle.container.ContainerLifecycle.stop; +import static org.gcube.smartgears.lifecycle.container.ContainerState.active; +import static org.gcube.smartgears.utils.Utils.rethrowUnchecked; + +import java.io.BufferedReader; +import java.io.File; +import java.io.FileReader; +import java.io.IOException; +import java.lang.management.ManagementFactory; +import java.lang.management.OperatingSystemMXBean; +import java.net.InetAddress; +import java.net.UnknownHostException; +import java.nio.file.FileStore; +import java.nio.file.Files; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.UUID; +import java.util.concurrent.Executors; +import java.util.concurrent.ScheduledExecutorService; +import java.util.concurrent.ScheduledFuture; +import java.util.regex.Matcher; +import java.util.regex.Pattern; + +import javax.xml.bind.annotation.XmlRootElement; + +import org.gcube.common.authorization.client.proxy.AuthorizationProxy; +import org.gcube.common.authorization.library.provider.SecurityTokenProvider; +import org.gcube.common.events.Observes; +import org.gcube.common.scope.api.ScopeProvider; +import org.gcube.informationsystem.impl.embedded.HeaderImpl; +import org.gcube.informationsystem.impl.entity.facet.CPUFacetImpl; +import org.gcube.informationsystem.impl.entity.facet.ContainerStateFacetImpl; +import org.gcube.informationsystem.impl.entity.facet.MemoryFacetImpl; +import org.gcube.informationsystem.impl.entity.facet.NetworkingFacetImpl; +import org.gcube.informationsystem.impl.entity.facet.SimplePropertyFacetImpl; +import org.gcube.informationsystem.impl.entity.facet.SoftwareFacetImpl; +import org.gcube.informationsystem.impl.entity.resource.HostingNodeImpl; +import org.gcube.informationsystem.impl.relation.IsIdentifiedByImpl; +import org.gcube.informationsystem.impl.relation.consistsof.HasPersistentMemoryImpl; +import org.gcube.informationsystem.impl.relation.consistsof.HasVolatileMemoryImpl; +import org.gcube.informationsystem.model.embedded.Header; +import org.gcube.informationsystem.model.entity.Facet; +import org.gcube.informationsystem.model.entity.Resource; +import org.gcube.informationsystem.model.entity.facet.CPUFacet; +import org.gcube.informationsystem.model.entity.facet.ContainerStateFacet; +import org.gcube.informationsystem.model.entity.facet.MemoryFacet; +import org.gcube.informationsystem.model.entity.facet.MemoryFacet.MemoryUnit; +import org.gcube.informationsystem.model.entity.facet.NetworkingFacet; +import org.gcube.informationsystem.model.entity.facet.SimplePropertyFacet; +import org.gcube.informationsystem.model.entity.facet.SoftwareFacet; +import org.gcube.informationsystem.model.entity.resource.HostingNode; +import org.gcube.informationsystem.model.relation.ConsistsOf; +import org.gcube.informationsystem.model.relation.IsIdentifiedBy; +import org.gcube.informationsystem.model.relation.consistsof.HasPersistentMemory; +import org.gcube.informationsystem.model.relation.consistsof.HasVolatileMemory; +import org.gcube.informationsystem.resourceregistry.api.exceptions.ResourceRegistryException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceAlreadyPresentException; +import org.gcube.informationsystem.resourceregistry.api.exceptions.entity.resource.ResourceNotFoundException; +import org.gcube.informationsystem.resourceregistry.client.proxy.ResourceRegistryClient; +import org.gcube.informationsystem.resourceregistry.client.proxy.ResourceRegistryClientFactory; +import org.gcube.informationsystem.resourceregistry.publisher.proxy.ResourceRegistryPublisher; +import org.gcube.informationsystem.resourceregistry.publisher.proxy.ResourceRegistryPublisherFactory; +import org.gcube.smartgears.configuration.container.ContainerConfiguration; +import org.gcube.smartgears.configuration.library.SmartGearsConfiguration; +import org.gcube.smartgears.context.Property; +import org.gcube.smartgears.context.container.ContainerContext; +import org.gcube.smartgears.handlers.container.ContainerHandler; +import org.gcube.smartgears.handlers.container.ContainerLifecycleEvent.Start; +import org.gcube.smartgears.lifecycle.container.ContainerLifecycle; +import org.gcube.smartgears.provider.ProviderFactory; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +/** + * Manages the {@link HostingNode} {@link Resource} of the application. + *

+ * The manager: + *

    + *
  • + * creates the {@link HostingNode} {@link Resource} and the facets it + * {@link ConsistsOf} when the container starts for the first time;
  • + *
  • + * update the {@link ContainerStateFacet} when the application becomes active, + * and at any lifecycle change thereafter;
  • + *
  • + * schedule a periodic update of {@link Facet}s containing variables + * information.
  • + *
+ *

+ * + * @author Luca Frosini + */ +@XmlRootElement(name = Constants.RESOURCE_MANAGEMENT) +public class HostingNodeManager extends ContainerHandler { + + private static Logger logger = LoggerFactory + .getLogger(HostingNodeManager.class); + + public static final String MEMORY_TYPE = "memoryType"; + public static final String MEMORY_TYPE_RAM = "RAM"; + public static final String MEMORY_TYPE_JVM = "JVM"; + public static final String JVM_MAX_MEMORY = "jvmMaxMemory"; + + public static final String MESSAGE = "message"; + + private ContainerContext context; + private AuthorizationProxy authorizationProxy; + + private ScheduledFuture periodicUpdates; + + public HostingNodeManager() { + super(); + this.authorizationProxy = ProviderFactory.provider() + .authorizationProxy(); + } + + private void setContextFromToken(String token) { + if (token == null || token.compareTo("") == 0) { + SecurityTokenProvider.instance.reset(); + ScopeProvider.instance.reset(); + } else { + SecurityTokenProvider.instance.set(token); + String scope = getCurrentContextName(token); + ScopeProvider.instance.set(scope); + } + + } + + @Override + public void onStart(Start e) { + context = e.context(); + HostingNode hostingNode = instantiateHostingNode(); + hostingNode = publishHostingNode(hostingNode); + registerObservers(); + schedulePeriodicUpdates(); + } + + private void share(HostingNode hostingNode) { + logger.trace("sharing {} {}", HostingNode.NAME, Resource.NAME); + context.properties().add( + new Property(Constants.HOSTING_NODE_PROPERTY, hostingNode)); + } + + private void registerObservers() { + + context.events().subscribe(new Object() { + + @Observes({ activation, part_activation, shutdown, stop, failure }) + void onChanged(ContainerLifecycle lc) { + HostingNode hostingNode = context.properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class); + updateHostingNode(hostingNode); + } + + @Observes(value = addToContext) + void addTo(String token) { + HostingNode hostingNode = context.properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class); + addToContext(hostingNode, token); + } + + @Observes(value = removeFromContext) + void removeFrom(String token) { + HostingNode hostingNode = context.properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class); + removeFromContext(hostingNode, token); + } + + }); + } + + private void schedulePeriodicUpdates() { + + // register to cancel updates + context.events().subscribe( + + new Object() { + + final ScheduledExecutorService service = Executors + .newScheduledThreadPool(1); + + // we register it in response to lifecycle events so that we can + // stop and resume along with application + @Observes(value = { activation, part_activation }, kind = resilient) + synchronized void restartPeriodicUpdates(ContainerLifecycle lc) { + + // already running + if (periodicUpdates != null) { + return; + } + + if (lc.state() == active) { + logger.info("scheduling periodic updates of {}", + HostingNode.NAME); + } else { + logger.info("resuming periodic updates of {}", + HostingNode.NAME); + } + + final Runnable updateTask = new Runnable() { + public void run() { + HostingNode hostingNode = context.properties().lookup(Constants.HOSTING_NODE_PROPERTY).value(HostingNode.class); + try { + updateHostingNode(hostingNode); + } catch (Exception e) { + logger.error( + "cannot complete periodic update of {}", + HostingNode.NAME, e); + } + } + }; + + periodicUpdates = service + .scheduleAtFixedRate(updateTask, 3, context + .configuration().publicationFrequency(), + SECONDS); + + } + + @Observes(value = { stop, failure, shutdown }, kind = resilient) + synchronized void cancelPeriodicUpdates(ContainerLifecycle ignore) { + + if (periodicUpdates != null) { + logger.trace("stopping periodic updates of {}", + HostingNode.NAME); + try { + periodicUpdates.cancel(true); + service.shutdownNow(); + periodicUpdates = null; + } catch (Exception e) { + logger.warn("could not stop periodic updates of {}", + HostingNode.NAME, e); + } + } + } + + }); + + } + + private HostingNode publishHostingNode(HostingNode hostingNode) { + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + String previousToken = SecurityTokenProvider.instance.get(); + try { + Thread.currentThread().setContextClassLoader( + HostingNodeManager.class.getClassLoader()); + + boolean create = true; + + List startTokens = context.configuration().startTokens(); + for (String token : startTokens) { + setContextFromToken(token); + + try { + ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory + .create(); + + if (create) { + + try { + hostingNode = resourceRegistryPublisher + .createResource(HostingNode.class, + hostingNode); + + // TODO Add a Reference to Site + /* + * node.profile().newSite().country(cfg.site().country + * ()).location(cfg.site ().location()) + * .latitude(cfg + * .site().latitude()).longitude(cfg.site + * ().longitude + * ()).domain(domainIn(cfg.hostname())); + */ + + } catch (ResourceAlreadyPresentException e) { + ResourceRegistryClient registryClient = ResourceRegistryClientFactory + .create(); + hostingNode = registryClient.getInstance( + HostingNode.class, hostingNode.getHeader() + .getUUID()); + } + + create = false; + + } else { + boolean added = resourceRegistryPublisher + .addResourceToContext(hostingNode); + if (added) { + logger.info( + "{} successfully added to current context ({})", + hostingNode, getCurrentContextName(token)); + share(hostingNode); + } else { + logger.error( + "Unable to add {} to current context ({})", + hostingNode, getCurrentContextName(token)); + } + } + share(hostingNode); + + } catch (Exception e) { + logger.error("Unable to add {} to current context ({})", + hostingNode, getCurrentContextName(token), e); + } + + } + + } catch (Exception e) { + rethrowUnchecked(e); + } finally { + setContextFromToken(previousToken); + Thread.currentThread().setContextClassLoader(contextCL); + } + return hostingNode; + } + + private String getCurrentContextName(String token) { + try { + return this.authorizationProxy.get(token).getContext(); + } catch (Exception e) { + logger.error("Error retrieving context form token {}, it should never happen", + token, e); + return null; + } + } + + private void removeFromContext(HostingNode hostingNode, String token) { + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + String previousToken = SecurityTokenProvider.instance.get(); + try { + Thread.currentThread().setContextClassLoader( + HostingNodeManager.class.getClassLoader()); + setContextFromToken(token); + + boolean removed = false; + + ResourceRegistryPublisher resourceRegistryPublisher = + ResourceRegistryPublisherFactory.create(); + removed = resourceRegistryPublisher. + removeResourceFromContext(hostingNode); + + if (removed) { + logger.info( + "{} successfully removed from current context ({})", + hostingNode, getCurrentContextName(token)); + share(hostingNode); + } else { + logger.error("Unable to remove {} from current context ({})", + hostingNode, getCurrentContextName(token)); + } + + share(hostingNode); + + } catch (Exception e) { + logger.error("Unable to remove {} from current context ({})", + hostingNode, getCurrentContextName(token), e); + rethrowUnchecked(e); + } finally { + setContextFromToken(previousToken); + Thread.currentThread().setContextClassLoader(contextCL); + } + } + + private void addToContext(HostingNode hostingNode, String token) { + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + String previousToken = SecurityTokenProvider.instance.get(); + try { + Thread.currentThread().setContextClassLoader( + HostingNodeManager.class.getClassLoader()); + setContextFromToken(token); + + ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory + .create(); + boolean added = resourceRegistryPublisher + .addResourceToContext(hostingNode); + + if (added) { + logger.info("{} successfully added to current context ({})", + hostingNode, getCurrentContextName(token)); + share(hostingNode); + } else { + logger.error("Unable to add {} to current context ({})", + hostingNode, getCurrentContextName(token)); + } + + share(hostingNode); + + } catch (Exception e) { + logger.error("Unable to add {} to current context ({})", + hostingNode, getCurrentContextName(token), e); + rethrowUnchecked(e); + } finally { + setContextFromToken(previousToken); + Thread.currentThread().setContextClassLoader(contextCL); + } + } + + private HostingNode updateHostingNode(HostingNode hostingNode) { + ClassLoader contextCL = Thread.currentThread().getContextClassLoader(); + String previousToken = SecurityTokenProvider.instance.get(); + try { + + if (previousToken == null) { + setContextFromToken((String) context.configuration() + .startTokens().toArray()[0]); + } + Thread.currentThread().setContextClassLoader( + HostingNodeManager.class.getClassLoader()); + + ResourceRegistryPublisher resourceRegistryPublisher = ResourceRegistryPublisherFactory + .create(); + + hostingNode = updateFacets(hostingNode, resourceRegistryPublisher); + + share(hostingNode); + + } catch (Exception e) { + rethrowUnchecked(e); + } finally { + setContextFromToken(previousToken); + Thread.currentThread().setContextClassLoader(contextCL); + } + return hostingNode; + + } + + private HostingNode updateFacets(HostingNode hostingNode, + ResourceRegistryPublisher resourceRegistryPublisher) throws ResourceRegistryException { + logger.debug("Updating HostingNode"); + + ContainerStateFacet containerStateFacet = null; + MemoryFacet ramFacet = null; + MemoryFacet jvmMemoryFacet = null; + MemoryFacet disk = null; + + List> consistsOfToRemove = new ArrayList<>(); + + List> consistsOfList = hostingNode + .getConsistsOf(); + for (ConsistsOf c : consistsOfList) { + if (c.getTarget() instanceof ContainerStateFacet) { + containerStateFacet = (ContainerStateFacet) c.getTarget(); + containerStateFacet = getContainerStateFacet(containerStateFacet); + continue; + } + + if (c instanceof HasVolatileMemory) { + String memoryType = (String) c + .getAdditionalProperty(MEMORY_TYPE); + if (memoryType.compareTo(MEMORY_TYPE_RAM) == 0) { + ramFacet = (MemoryFacet) c.getTarget(); + ramFacet = getRamInfo(ramFacet); + continue; + } + + if (memoryType.compareTo(MEMORY_TYPE_JVM) == 0) { + jvmMemoryFacet = (MemoryFacet) c.getTarget(); + jvmMemoryFacet = getJVMMemoryInfo(jvmMemoryFacet); + continue; + } + + } + + if (c instanceof HasPersistentMemory) { + disk = (MemoryFacet) c.getTarget(); + disk = getDiskSpace(disk); + continue; + } + + consistsOfToRemove.add(c); + + } + + // Resource Update has affect an all specified facet. + // Removing the one that have not to be changed + consistsOfList.removeAll(consistsOfToRemove); + + try { + hostingNode = resourceRegistryPublisher.updateResource( + HostingNode.class, hostingNode); + } catch (ResourceNotFoundException e) { + /* Update failed trying to recreate it */ + // ReAdding the removed relations to recreate all + consistsOfList.addAll(consistsOfToRemove); + hostingNode = resourceRegistryPublisher.createResource( + HostingNode.class, hostingNode); + } + + return hostingNode; + } + + private HostingNode instantiateHostingNode() { + logger.info("Creating {} {}", HostingNode.NAME, Resource.NAME); + + ContainerConfiguration containerConfiguration = context.configuration(); + + UUID uuid = UUID.fromString(this.context.id()); + HostingNode hostingNode = new HostingNodeImpl(); + Header header = new HeaderImpl(uuid); + hostingNode.setHeader(header); + + NetworkingFacet networkingFacet = new NetworkingFacetImpl(); + try { + networkingFacet.setIPAddress(InetAddress.getLocalHost() + .getHostAddress()); + } catch (UnknownHostException e) { + logger.warn("unable to detect the IP address of the host"); + } + String hostname = containerConfiguration.hostname(); + networkingFacet.setHostName(hostname); + networkingFacet.setDomainName(getDomain(hostname)); + + networkingFacet.setAdditionalProperty("Port", + containerConfiguration.port()); + IsIdentifiedBy isIdentifiedBy = new IsIdentifiedByImpl<>( + hostingNode, networkingFacet, null); + hostingNode.addFacet(isIdentifiedBy); + + List cpuFacets = getCPUFacets(); + for (CPUFacet cpuFacet : cpuFacets) { + hostingNode.addFacet(cpuFacet); + } + + SoftwareFacet softwareFacet = new SoftwareFacetImpl(); + OperatingSystemMXBean mxbean = ManagementFactory + .getOperatingSystemMXBean(); + softwareFacet.setGroup(mxbean.getName()); // softwareFacet.setGroup(System.getProperty("os.name")); + softwareFacet.setName(mxbean.getArch()); // softwareFacet.setName(System.getProperty("os.arch")); + softwareFacet.setVersion(mxbean.getVersion()); // softwareFacet.setName(System.getProperty("os.version")); + hostingNode.addFacet(softwareFacet); + + SimplePropertyFacet simplePropertyFacet = addEnvironmentVariables(); + hostingNode.addFacet(simplePropertyFacet); + + ContainerStateFacet containerStateFacet = getContainerStateFacet(null); + hostingNode.addFacet(containerStateFacet); + + MemoryFacet ramFacet = getRamInfo(null); + HasVolatileMemory hasVolatileRAMMemory = new HasVolatileMemoryImpl( + hostingNode, ramFacet, null); + hasVolatileRAMMemory + .setAdditionalProperty(MEMORY_TYPE, MEMORY_TYPE_RAM); + hostingNode.addFacet(hasVolatileRAMMemory); + + MemoryFacet jvmMemoryFacet = getJVMMemoryInfo(null); + HasVolatileMemory hasVolatileJVMMemory = new HasVolatileMemoryImpl( + hostingNode, jvmMemoryFacet, null); + hasVolatileJVMMemory + .setAdditionalProperty(MEMORY_TYPE, MEMORY_TYPE_JVM); + hostingNode.addFacet(hasVolatileJVMMemory); + + MemoryFacet diskFacet = getDiskSpace(null); + HasPersistentMemory hasPersistentMemory = new HasPersistentMemoryImpl( + hostingNode, diskFacet, null); + hostingNode.addFacet(hasPersistentMemory); + + return hostingNode; + } + + private ContainerStateFacet getContainerStateFacet( + ContainerStateFacet containerStateFacet) { + if (containerStateFacet == null) { + containerStateFacet = new ContainerStateFacetImpl(); + } + containerStateFacet.setValue(context.lifecycle().state().remoteForm()); + return containerStateFacet; + } + + private MemoryFacet getDiskSpace(MemoryFacet memoryFacet) { + if (memoryFacet == null) { + memoryFacet = new MemoryFacetImpl(); + } + + long free = 0; + long total = 0; + try { + FileStore fileStore = Files.getFileStore(Paths.get(context + .configuration().persistence().location())); + free = fileStore.getUsableSpace() / 1048576; // 1048576 = 1024*1024 + // user to convert + // bytes in MByte + total = fileStore.getTotalSpace() / 1048576; // 1048576 = 1024*1024 + // user to convert + // bytes in MByte + } catch (IOException ioe) { + logger.warn("Unable to detect disk space information", ioe); + memoryFacet.setAdditionalProperty(MESSAGE, + "Unable to detect disk space information."); + } + + memoryFacet.setUnit(MemoryUnit.MB); + memoryFacet.setSize(total); + memoryFacet.setUsed(total - free); + + return memoryFacet; + } + + @SuppressWarnings("restriction") + private MemoryFacet getRamInfo(MemoryFacet memoryFacet) { + if (memoryFacet == null) { + memoryFacet = new MemoryFacetImpl(); + } + + OperatingSystemMXBean mxbean = ManagementFactory + .getOperatingSystemMXBean(); + com.sun.management.OperatingSystemMXBean sunmxbean = (com.sun.management.OperatingSystemMXBean) mxbean; + long freeMemory = sunmxbean.getFreePhysicalMemorySize() / 1048576; // in + // MB + long totalMemory = sunmxbean.getTotalPhysicalMemorySize() / 1048576; // in + // MB + + memoryFacet.setUnit(MemoryUnit.MB); + memoryFacet.setSize(totalMemory); + memoryFacet.setUsed(totalMemory - freeMemory); + + return memoryFacet; + } + + private MemoryFacet getJVMMemoryInfo(MemoryFacet memoryFacet) { + if (memoryFacet == null) { + memoryFacet = new MemoryFacetImpl(); + } + + /* 1048576 = 1024*1024 used to convert bytes in MByte */ + long jvmFreeMemory = Runtime.getRuntime().freeMemory() / 1048576; + long jvmTotalMemory = Runtime.getRuntime().totalMemory() / 1048576; + long jvmMaxMemory = Runtime.getRuntime().maxMemory() / 1048576; + + memoryFacet.setUnit(MemoryUnit.MB); + memoryFacet.setSize(jvmTotalMemory); + memoryFacet.setUsed(jvmTotalMemory - jvmFreeMemory); + memoryFacet.setAdditionalProperty(JVM_MAX_MEMORY, jvmMaxMemory); + + return memoryFacet; + } + + private static String sanitizeKey(String key) { + return key.trim().replace(" ", "_"); + } + + private SimplePropertyFacet addEnvironmentVariables() { + + ContainerConfiguration cfg = context.configuration(); + + Map map = new HashMap(); + map.putAll(cfg.properties()); + map.putAll(System.getenv()); + + SimplePropertyFacet simplePropertyFacet = new SimplePropertyFacetImpl(); + simplePropertyFacet.setName("ENVIRONMENT_VARIABLES"); + simplePropertyFacet.setValue(""); + + for (Map.Entry entry : map.entrySet()) { + String varname = entry.getKey(); + if ((varname.compareToIgnoreCase("CLASSPATH") == 0) + || (varname.compareToIgnoreCase("PATH") == 0) + || (varname.contains("SSH")) || (varname.contains("MAIL")) + || (varname.compareToIgnoreCase("LS_COLORS") == 0)) { + continue; + } + + simplePropertyFacet.setAdditionalProperty( + sanitizeKey(entry.getKey()), entry.getValue()); + + } + + simplePropertyFacet.setAdditionalProperty("Java", + System.getProperty("java.version")); + SmartGearsConfiguration config = ProviderFactory.provider() + .smartgearsConfiguration(); + + simplePropertyFacet.setAdditionalProperty("SmartGears", + config.version()); + simplePropertyFacet.setAdditionalProperty( + "ghn-update-interval-in-secs", + String.valueOf(cfg.publicationFrequency())); + + return simplePropertyFacet; + } + + private static String getDomain(String hostname) { + try { + Pattern pattern = Pattern + .compile("([0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3})"); + Matcher regexMatcher = pattern.matcher(hostname); + if (regexMatcher.matches()) { // it's an IP address, nothing to trim + return hostname; + } + return hostname.substring(hostname.indexOf(".") + 1); + } catch (Exception e) { + logger.warn("Error while getting domain from hostname"); + return hostname; + } + } + + public static final String CPU_PROCESSOR = "processor"; + public static final String CPU_VENDOR_ID = "vendor_id"; + public static final String CPU_MODEL_NAME = "model name"; + public static final String CPU_CPU_MHZ = "cpu MHz"; + public static final String CPU_MODEL_T = "model\t"; + public static final String CPU_MODEL_B = "model\b"; + public static final String CPU_MODEL_NUMBER = "modelNumber"; + + public static List getCPUFacets() { + + List cpuFacets = new ArrayList<>(); + + File file = new File("/proc/cpuinfo"); + + if (!file.exists()) { + logger.warn("cannot acquire CPU info (no /proc/cpuinfo)"); + return cpuFacets; + } + + BufferedReader input = null; + + try { + input = new BufferedReader(new FileReader(file)); + + String line = null; + + CPUFacet cpuFacet = null; + + while ((line = input.readLine()) != null) { + + if ((line.startsWith(CPU_PROCESSOR))) { // add the current + // processor to the map + cpuFacet = new CPUFacetImpl(); + cpuFacets.add(cpuFacet); + } + + try { + if (line.contains(CPU_VENDOR_ID)) { + cpuFacet.setVendor(line.split(":")[1].trim()); + continue; + } + } catch (Exception e) { + continue; + } + + try { + if (line.contains(CPU_MODEL_NAME)) { + cpuFacet.setModel(line.split(":")[1].trim()); + continue; + } + } catch (Exception e) { + continue; + } + + try { + if (line.contains(CPU_CPU_MHZ)) { + cpuFacet.setClockSpeed(line.split(":")[1].trim()); + continue; + } + } catch (Exception e) { + continue; + } + + try { + if ((line.contains(CPU_MODEL_T)) + || (line.contains(CPU_MODEL_B))) { + cpuFacet.setAdditionalProperty(CPU_MODEL_NUMBER, + line.split(":")[1].trim()); + continue; + } + } catch (Exception e) { + continue; + } + + try { + String[] nameValue = line.split(":"); + cpuFacet.setAdditionalProperty(sanitizeKey(nameValue[0]), + line.split(":")[1].trim()); + } catch (Exception e) { + + } + + } + } catch (Exception e) { + logger.warn("unable to acquire CPU info", e); + } finally { + if (input != null) { + try { + input.close(); + } catch (IOException e) { + logger.warn("unable to close stream", e); + } + } + } + return cpuFacets; + } + + @Override + public String toString() { + return Constants.RESOURCE_MANAGEMENT; + } +} diff --git a/src/main/resources/META-INF/gcube-application-handlers.xml b/src/main/resources/META-INF/gcube-application-handlers.xml new file mode 100644 index 0000000..19718e4 --- /dev/null +++ b/src/main/resources/META-INF/gcube-application-handlers.xml @@ -0,0 +1,6 @@ + + + + + + diff --git a/src/main/resources/META-INF/gcube-container-handlers.xml b/src/main/resources/META-INF/gcube-container-handlers.xml new file mode 100644 index 0000000..ff86c79 --- /dev/null +++ b/src/main/resources/META-INF/gcube-container-handlers.xml @@ -0,0 +1,4 @@ + + + + diff --git a/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler new file mode 100644 index 0000000..5fa2b01 --- /dev/null +++ b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.application.ApplicationHandler @@ -0,0 +1 @@ +org.gcube.smartgears.handler.resourceregistry.EServiceManager \ No newline at end of file diff --git a/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler new file mode 100644 index 0000000..469f25f --- /dev/null +++ b/src/main/resources/META-INF/services/org.gcube.smartgears.handlers.container.ContainerHandler @@ -0,0 +1 @@ +org.gcube.smartgears.handler.resourceregistry.HostingNodeManager \ No newline at end of file