diff --git a/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java b/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java index c8219a64563e1b52582ac9fb7bfa69345223e70a..0664b5ad40a42ad5b197c18769d2274fa1c801f0 100644 --- a/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java +++ b/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java @@ -13,6 +13,7 @@ import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobRef; import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification; import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCreate; import org.etsi.osl.tmf.ri639.model.*; +import org.etsi.osl.tmf.scm633.model.ServiceSpecification; import org.etsi.osl.tmf.sim638.model.Service; import org.etsi.osl.tmf.sim638.model.ServiceUpdate; import org.slf4j.Logger; @@ -47,6 +48,8 @@ public class MetricoCommonMethods extends RouteBuilder { private String CATALOG_UPDADD_RESOURCESPEC = ""; @Value("${PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING}") private String PM_MEASUREMENT_COLLECTION_JOB_GET_INPROGRESS_OR_PENDING; + @Value("${CATALOG_GET_SERVICESPEC_BY_ID}") + private String CATALOG_GET_SERVICESPEC_BY_ID = ""; private ProducerTemplate template; @@ -362,4 +365,22 @@ public class MetricoCommonMethods extends RouteBuilder { } return null; } + + public ServiceSpecification retrieveServiceSpecificationById(String serviceSpecId) { + + logger.debug("will retrieve Service Specification with id = {}.", serviceSpecId); + try { + Object response = template.requestBody(CATALOG_GET_SERVICESPEC_BY_ID, serviceSpecId); + if (!(response instanceof String)) { + logger.error("Service Specification object is wrong."); + return null; + } + logger.debug("retrieveServiceSpecificationById response is: {}", response); + ServiceSpecification serviceSpec = JsonUtil.toJsonObj((String) response, ServiceSpecification.class); + return serviceSpec; + } catch (Exception e) { + logger.error("Cannot retrieve Service Specification details from database. " + e.toString()); + } + return null; + } } diff --git a/src/main/java/org/etsi/osl/metrico/services/MetricoService.java b/src/main/java/org/etsi/osl/metrico/services/MetricoService.java index a7fa9e9eadc93ad93caec77bf1ae352d173a0f5b..a82a3ab1b25c0e8830f3a78eeb3edb7050d48bde 100644 --- a/src/main/java/org/etsi/osl/metrico/services/MetricoService.java +++ b/src/main/java/org/etsi/osl/metrico/services/MetricoService.java @@ -9,13 +9,21 @@ import org.etsi.osl.metrico.model.Job; import org.etsi.osl.metrico.prometheus.PrometheusQueries; import org.etsi.osl.tmf.common.model.ELifecycle; import org.etsi.osl.tmf.common.model.EValueType; +import org.etsi.osl.tmf.common.model.Notification; +import org.etsi.osl.tmf.common.model.service.ServiceStateType; import org.etsi.osl.tmf.pm628.model.*; import org.etsi.osl.tmf.rcm634.model.LogicalResourceSpecification; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecification; import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationCreate; +import org.etsi.osl.tmf.rcm634.model.ResourceSpecificationRef; +import org.etsi.osl.tmf.scm633.model.ServiceSpecification; +import org.etsi.osl.tmf.sim638.model.ServiceDeleteNotification; +import org.etsi.osl.tmf.sim638.model.ServiceStateChangeNotification; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.context.event.EventListener; + import org.springframework.stereotype.Service; import java.time.OffsetDateTime; @@ -31,7 +39,7 @@ public class MetricoService extends RouteBuilder { public static final String OSL_METRICO_RSPEC_CATEGORY = "metrico.osl.etsi.org/v1"; public static final String OSL_METRICO_RSPEC_TYPE = "LogicalResourceSpecification"; public static final String OSL_METRICO_RSPEC_DESCRIPTION = "This Specification is used to describe a generic METRICO job resource"; - + private static String OSL_METRICO_RSPEC_ID = null; private final MetricoCommonMethods metricoCommonMethods; private final PrometheusQueries prometheusQueries; @@ -83,6 +91,7 @@ public class MetricoService extends RouteBuilder { rsc.addResourceSpecificationCharacteristicItemShort("_MT_URL", "", EValueType.TEXT.getValue(), "The monitoring source URL (e.g. https://prom.osl.etsi.org:9090)", false); LogicalResourceSpecification result = metricoCommonMethods.createOrUpdateResourceSpecByNameCategoryVersion(rsc); + while (result == null) { try { logger.info("Cannot get resource for registerMetricoResourceSpec. Retrying in 10 seconds"); @@ -92,6 +101,7 @@ public class MetricoService extends RouteBuilder { } result = metricoCommonMethods.createOrUpdateResourceSpecByNameCategoryVersion(rsc); } + OSL_METRICO_RSPEC_ID = result.getId(); } public void restartPendingOrInProgressJobs() { @@ -198,4 +208,40 @@ public class MetricoService extends RouteBuilder { logger.error("=======> CANNOT retrieve Measurement Collection Job with mcjId = " + mcjevent.getEvent().getMeasurementCollectionJob().getId() + " from activeMQ"); } } + + public void handleServiceEvent(final Notification n){ + + org.etsi.osl.tmf.sim638.model.Service service = null; + + if (n instanceof ServiceStateChangeNotification){ + service = ((ServiceStateChangeNotification) n).getEvent().getService(); + } else if (n instanceof ServiceDeleteNotification){ + service = ((ServiceDeleteNotification) n).getEvent().getService(); + } + + ServiceSpecification serviceSpec = null; + if (service != null && service.getServiceSpecificationRef() != null) { + serviceSpec = metricoCommonMethods.retrieveServiceSpecificationById(service.getServiceSpecificationRef().getId()); + } + + if(serviceSpec != null){ + // Check if it is an RFS SPEC + if(serviceSpec.getResourceSpecification().size() == 1) { + ResourceSpecificationRef rSpec = serviceSpec.getResourceSpecification().iterator().next(); + if (rSpec.getId().equalsIgnoreCase(OSL_METRICO_RSPEC_ID)) { + if (service.getState() == ServiceStateType.TERMINATED) { + logger.debug("Service {} is a METRICO service with state TERMINATED. Terminating related job.", service.getId()); + jobService.stopJob(String.valueOf(service.getServiceCharacteristicByName("_MT_MCJ_REFID").getValue().getValue())); + } + if (n instanceof ServiceDeleteNotification){ + logger.debug("Service {} is a METRICO service that was deleted. Terminating related job.", service.getId()); + jobService.stopJob(String.valueOf(service.getServiceCharacteristicByName("_MT_MCJ_REFID").getValue().getValue())); + } + } else { + logger.debug("Service {} is not a METRICO service, skipping.", service.getId()); + return; + } + } + } + } } diff --git a/src/main/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilder.java b/src/main/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilder.java index b6ae5e5862d8d4e834c5b5a0b7b6c898f2c06d1c..d9f4f38cf0b668c5a2c9321f2116cac893f2e87b 100644 --- a/src/main/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilder.java +++ b/src/main/java/org/etsi/osl/metrico/services/MetricoServiceRouteBuilder.java @@ -6,6 +6,8 @@ import org.apache.camel.model.dataformat.JsonLibrary; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.etsi.osl.tmf.pm628.model.MeasurementCollectionJobCreateEvent; +import org.etsi.osl.tmf.sim638.model.ServiceDeleteNotification; +import org.etsi.osl.tmf.sim638.model.ServiceStateChangeNotification; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.context.annotation.Configuration; @@ -23,6 +25,12 @@ public class MetricoServiceRouteBuilder extends RouteBuilder { @Value("${EVENT_MEASUREMENT_COLLECTION_JOB_CREATE}") private String EVENT_MEASUREMENT_COLLECTION_JOB_CREATE = ""; + @Value("${EVENT_SERVICE_STATE_CHANGED}") + private String EVENT_SERVICE_STATE_CHANGED = ""; + + @Value("${EVENT_SERVICE_DELETE}") + private String EVENT_SERVICE_DELETE = ""; + public void configure() throws Exception { from(EVENT_MEASUREMENT_COLLECTION_JOB_CREATE) @@ -32,7 +40,19 @@ public class MetricoServiceRouteBuilder extends RouteBuilder { .json(JsonLibrary.Jackson, MeasurementCollectionJobCreateEvent.class, true) .bean(metricoService, "startPeriodicQueryToPrometheusEvent(${body})"); - } + from(EVENT_SERVICE_STATE_CHANGED) + .log(LoggingLevel.INFO, log, EVENT_SERVICE_STATE_CHANGED + " message received!") + .to("log:DEBUG?showBody=true&showHeaders=true") + .unmarshal() + .json(JsonLibrary.Jackson, ServiceStateChangeNotification.class, true) + .bean(metricoService, "handleServiceEvent"); + from(EVENT_SERVICE_DELETE) + .log(LoggingLevel.INFO, log, EVENT_SERVICE_DELETE + " message received!") + .to("log:DEBUG?showBody=true&showHeaders=true") + .unmarshal() + .json(JsonLibrary.Jackson, ServiceDeleteNotification.class, true) + .bean(metricoService, "handleServiceEvent"); + } } diff --git a/src/main/resources/application-testing.yml b/src/main/resources/application-testing.yml index 8b11b03fcd281c0ab0b7d2351dd81a464d75e71b..4e39bc3ec47f7a3d09bd010f8a2a207700cbf73f 100644 --- a/src/main/resources/application-testing.yml +++ b/src/main/resources/application-testing.yml @@ -60,5 +60,9 @@ EVENT_MEASUREMENT_COLLECTION_JOB_ATTRIBUTE_VALUE_CHANGED: "direct:topic:EVENT.ME CATALOG_UPDADD_RESOURCESPEC: "direct:CATALOG.UPDADD.RESOURCESPEC" CATALOG_GET_SERVICE_BY_ID: "direct:CATALOG.GET.SERVICE" CATALOG_GET_RESOURCE_BY_ID: "direct:CATALOG.GET.RESOURCE" +CATALOG_GET_SERVICESPEC_BY_ID: "jms:queue:CATALOG.GET.SERVICESPEC_BY_ID" CATALOG_UPD_RESOURCE: "direct:CATALOG.UPD.RESOURCE" CATALOG_UPD_SERVICE: "direct:CATALOG.UPD.SERVICE" + +EVENT_SERVICE_STATE_CHANGED: "jms:topic:EVENT.SERVICE.STATECHANGED" +EVENT_SERVICE_DELETE: "jms:topic:EVENT.SERVICE.DELETE" \ No newline at end of file diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml index 150f340f3deda67fb54b2716511813f42588bf64..7bfdb494b42789b95dd907e419d2529c129cf9e5 100644 --- a/src/main/resources/application.yml +++ b/src/main/resources/application.yml @@ -56,6 +56,10 @@ EVENT_MEASUREMENT_COLLECTION_JOB_ATTRIBUTE_VALUE_CHANGED: "jms:topic:EVENT.MEASU CATALOG_UPDADD_RESOURCESPEC: "jms:queue:CATALOG.UPDADD.RESOURCESPEC" CATALOG_GET_SERVICE_BY_ID: "jms:queue:CATALOG.GET.SERVICE" +CATALOG_GET_SERVICESPEC_BY_ID: "jms:queue:CATALOG.GET.SERVICESPEC_BY_ID" CATALOG_GET_RESOURCE_BY_ID: "jms:queue:CATALOG.GET.RESOURCE" CATALOG_UPD_RESOURCE: "jms:queue:CATALOG.UPD.RESOURCE" CATALOG_UPD_SERVICE: "jms:queue:CATALOG.UPD.SERVICE" + +EVENT_SERVICE_STATE_CHANGED: "jms:topic:EVENT.SERVICE.STATECHANGED" +EVENT_SERVICE_DELETE: "jms:topic:EVENT.SERVICE.DELETE" \ No newline at end of file