From caa20b8a6ff641b9c72fdffaf5fc1ca47452accd Mon Sep 17 00:00:00 2001 From: George Tziavas Date: Thu, 19 Jun 2025 16:47:18 +0300 Subject: [PATCH 1/2] listen service events and handle them --- .../osl/metrico/MetricoCommonMethods.java | 21 +++++++++ .../osl/metrico/services/MetricoService.java | 47 ++++++++++++++++++- .../services/MetricoServiceRouteBuilder.java | 22 ++++++++- src/main/resources/application-testing.yml | 4 ++ src/main/resources/application.yml | 4 ++ 5 files changed, 96 insertions(+), 2 deletions(-) diff --git a/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java b/src/main/java/org/etsi/osl/metrico/MetricoCommonMethods.java index c8219a6..0664b5a 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 a7fa9e9..5b98cff 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,39 @@ 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)) { + logger.debug("Service {} is a METRICO service, processing.", service.getId()); + if (service.getState() == ServiceStateType.TERMINATED) { + jobService.stopJob(String.valueOf(service.getServiceCharacteristicByName("_MT_MCJ_REFID").getValue().getValue())); + } + if (n instanceof ServiceDeleteNotification){ + 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 b6ae5e5..d9f4f38 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 8b11b03..4e39bc3 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 150f340..7bfdb49 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 -- GitLab From 7ba4731fbc00cd783cfb9e060f7b8064aa1a1697 Mon Sep 17 00:00:00 2001 From: George Tziavas Date: Thu, 19 Jun 2025 17:20:14 +0300 Subject: [PATCH 2/2] improved logging --- .../java/org/etsi/osl/metrico/services/MetricoService.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) 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 5b98cff..a82a3ab 100644 --- a/src/main/java/org/etsi/osl/metrico/services/MetricoService.java +++ b/src/main/java/org/etsi/osl/metrico/services/MetricoService.java @@ -229,11 +229,12 @@ public class MetricoService extends RouteBuilder { if(serviceSpec.getResourceSpecification().size() == 1) { ResourceSpecificationRef rSpec = serviceSpec.getResourceSpecification().iterator().next(); if (rSpec.getId().equalsIgnoreCase(OSL_METRICO_RSPEC_ID)) { - logger.debug("Service {} is a METRICO service, processing.", service.getId()); 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 { -- GitLab