aboutsummaryrefslogtreecommitdiffstats
path: root/tosca-controlloop/runtime/src
diff options
context:
space:
mode:
Diffstat (limited to 'tosca-controlloop/runtime/src')
-rw-r--r--tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java101
-rw-r--r--tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java351
-rw-r--r--tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java7
-rw-r--r--tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java70
-rw-r--r--tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java104
-rw-r--r--tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java273
-rw-r--r--tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java371
-rw-r--r--tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java202
8 files changed, 1444 insertions, 35 deletions
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java
new file mode 100644
index 000000000..ab917b74e
--- /dev/null
+++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/CommissioningHandler.java
@@ -0,0 +1,101 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.commissioning;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.core.Response;
+import lombok.Getter;
+import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler;
+import org.onap.policy.clamp.controlloop.runtime.commissioning.rest.CommissioningController;
+import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher;
+import org.onap.policy.common.utils.services.Registry;
+import org.onap.policy.models.base.PfModelRuntimeException;
+
+/**
+ * This class handles commissioning of control loop definitions.
+ */
+public final class CommissioningHandler extends ControlLoopHandler {
+
+ @Getter
+ private CommissioningProvider provider;
+
+ /**
+ * Gets the CommissioningHandler.
+ *
+ * @return CommissioningHandler
+ */
+ public static CommissioningHandler getInstance() {
+ return Registry.get(CommissioningHandler.class.getName());
+ }
+
+ /**
+ * Create a handler.
+ *
+ * @param controlLoopParameters the parameters for access to the database
+ */
+ public CommissioningHandler(ClRuntimeParameterGroup controlLoopParameters) {
+ super(controlLoopParameters.getDatabaseProviderParameters());
+ }
+
+ @Override
+ public Set<Class<?>> getProviderClasses() {
+ return Set.of(CommissioningController.class);
+ }
+
+ @Override
+ public void startAndRegisterListeners(MessageTypeDispatcher msgDispatcher) {
+ // No topic communication on this handler
+ }
+
+ @Override
+ public void startAndRegisterPublishers(List<TopicSink> topicSinks) {
+ // No topic communication on this handler
+ }
+
+ @Override
+ public void stopAndUnregisterPublishers() {
+ // No topic communication on this handler
+ }
+
+ @Override
+ public void stopAndUnregisterListeners(MessageTypeDispatcher msgDispatcher) {
+ // No topic communication on this handler
+ }
+
+ @Override
+ public void startProviders() {
+ provider = new CommissioningProvider(getDatabaseProviderParameters());
+ }
+
+ @Override
+ public void stopProviders() {
+ try {
+ provider.close();
+ } catch (IOException e) {
+ throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR,
+ "an error has occured while stopping commissioning providers", e);
+ }
+ }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java
new file mode 100644
index 000000000..cd6c08e30
--- /dev/null
+++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningController.java
@@ -0,0 +1,351 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.commissioning.rest;
+
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import io.swagger.annotations.Authorization;
+import io.swagger.annotations.Extension;
+import io.swagger.annotations.ExtensionProperty;
+import io.swagger.annotations.ResponseHeader;
+import java.util.List;
+import java.util.UUID;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import javax.ws.rs.core.Response.Status;
+import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse;
+import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler;
+import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningProvider;
+import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.errors.concepts.ErrorResponseInfo;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaNodeTemplate;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Class to provide REST end points for creating, deleting, querying commissioned control loops.
+ */
+public class CommissioningController extends RestController {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(CommissioningController.class);
+
+ private final CommissioningProvider provider;
+
+ /**
+ * create Commissioning Controller.
+ */
+ public CommissioningController() {
+ this.provider = CommissioningHandler.getInstance().getProvider();
+ }
+
+ /**
+ * Creates a control loop definition.
+ *
+ * @param requestId request ID used in ONAP logging
+ * @param body the body of control loop following TOSCA definition
+ * @return a response
+ */
+ // @formatter:off
+ @POST
+ @Path("/commission")
+ @ApiOperation(
+ value = "Commissions control loop definitions",
+ notes = "Commissions control loop definitions, returning the commissioned control loop definition IDs",
+ response = CommissioningResponse.class,
+ tags = {
+ "Control Loop Commissioning API"
+ },
+ authorizations = @Authorization(value = AUTHORIZATION_TYPE),
+ responseHeaders = {
+ @ResponseHeader(
+ name = VERSION_MINOR_NAME,
+ description = VERSION_MINOR_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(
+ name = VERSION_PATCH_NAME,
+ description = VERSION_PATCH_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(
+ name = VERSION_LATEST_NAME,
+ description = VERSION_LATEST_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(
+ name = REQUEST_ID_NAME,
+ description = REQUEST_ID_HDR_DESCRIPTION,
+ response = UUID.class)
+ },
+ extensions = {
+ @Extension(
+ name = EXTENSION_NAME,
+ properties = {
+ @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
+ @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
+ }
+ )
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
+ @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
+ @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
+ }
+ )
+ // @formatter:on
+ public Response create(
+ @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Entity Body of Control Loop", required = true) ToscaServiceTemplate body) {
+
+ try {
+ CommissioningResponse response = provider.createControlLoopDefinitions(body);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId)
+ .entity(response).build();
+
+ } catch (PfModelRuntimeException | PfModelException e) {
+ LOGGER.warn("Commissioning of the control loops failed", e);
+ return createCommissioningErrorResponse(e, requestId);
+ }
+
+ }
+
+ /**
+ * Deletes a control loop definition.
+ *
+ * @param requestId request ID used in ONAP logging
+ * @param name the name of the control loop definition to delete
+ * @param version the version of the control loop definition to delete
+ * @return a response
+ */
+ // @formatter:off
+ @DELETE
+ @Path("/commission")
+ @ApiOperation(value = "Delete a commissioned control loop",
+ notes = "Deletes a Commissioned Control Loop, returning optional error details",
+ response = CommissioningResponse.class,
+ tags = {
+ "Clamp Control Loop Commissioning API"
+ },
+ authorizations = @Authorization(value = AUTHORIZATION_TYPE),
+ responseHeaders = {
+ @ResponseHeader(
+ name = VERSION_MINOR_NAME,
+ description = VERSION_MINOR_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(
+ name = VERSION_PATCH_NAME,
+ description = VERSION_PATCH_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(
+ name = VERSION_LATEST_NAME,
+ description = VERSION_LATEST_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(
+ name = REQUEST_ID_NAME,
+ description = REQUEST_ID_HDR_DESCRIPTION,
+ response = UUID.class)},
+ extensions = {
+ @Extension(
+ name = EXTENSION_NAME,
+ properties = {
+ @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
+ @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
+ }
+ )
+ }
+ )
+ @ApiResponses(value = {
+ @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
+ @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
+ @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
+ }
+ )
+ // @formatter:on
+ public Response delete(
+ @HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Control Loop definition name", required = true) @QueryParam("name") String name,
+ @ApiParam(value = "Control Loop definition version", required = true)
+ @QueryParam("version") String version) {
+
+ try {
+ CommissioningResponse response = provider.deleteControlLoopDefinition(name, version);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId)
+ .entity(response).build();
+
+ } catch (PfModelRuntimeException | PfModelException e) {
+ LOGGER.warn("Decommisssioning of control loop failed", e);
+ return createCommissioningErrorResponse(e, requestId);
+ }
+
+ }
+
+ /**
+ * Queries details of all or specific control loop definitions.
+ *
+ * @param requestId request ID used in ONAP logging
+ * @param name the name of the control loop definition to get, null for all definitions
+ * @param version the version of the control loop definition to get, null for all definitions
+ * @return the control loop definitions
+ */
+ // @formatter:off
+ @GET
+ @Path("/commission")
+ @ApiOperation(value = "Query details of the requested commissioned control loop definitions",
+ notes = "Queries details of the requested commissioned control loop definitions, "
+ + "returning all control loop details",
+ response = ToscaNodeTemplate.class,
+ tags = {
+ "Clamp Control Loop Commissioning API"
+ },
+ authorizations = @Authorization(value = AUTHORIZATION_TYPE),
+ responseHeaders = {
+ @ResponseHeader(
+ name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
+ response = UUID.class)},
+ extensions = {
+ @Extension(
+ name = EXTENSION_NAME,
+ properties = {
+ @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
+ @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
+ }
+ )
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
+ @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
+ @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
+ }
+ )
+ // @formatter:on
+ public Response query(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Control Loop definition name", required = true)
+ @QueryParam("name") String name,
+ @ApiParam(value = "Control Loop definition version", required = true)
+ @QueryParam("version") String version) {
+
+ try {
+ List<ToscaNodeTemplate> response = provider.getControlLoopDefinitions(name, version);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
+ .build();
+
+ } catch (PfModelRuntimeException | PfModelException e) {
+ LOGGER.warn("Get of control loop definitions failed", e);
+ return createCommissioningErrorResponse(e, requestId);
+ }
+
+ }
+
+ /**
+ * Queries the elements of a specific control loop.
+ *
+ * @param requestId request ID used in ONAP logging
+ * @param name the name of the control loop definition to get
+ * @param version the version of the control loop definition to get
+ * @return the control loop element definitions
+ */
+ // @formatter:off
+ @GET
+ @Path("/commission/elements")
+ @ApiOperation(value = "Query details of the requested commissioned control loop element definitions",
+ notes = "Queries details of the requested commissioned control loop element definitions, "
+ + "returning all control loop elements' details",
+ response = ToscaNodeTemplate.class,
+ tags = {
+ "Clamp Control Loop Commissioning API"
+ },
+ authorizations = @Authorization(value = AUTHORIZATION_TYPE),
+ responseHeaders = {
+ @ResponseHeader(
+ name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
+ response = UUID.class)},
+ extensions = {
+ @Extension(
+ name = EXTENSION_NAME,
+ properties = {
+ @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
+ @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
+ }
+ )
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
+ @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
+ @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
+ }
+ )
+ // @formatter:on
+ public Response queryElements(@HeaderParam(REQUEST_ID_NAME) @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Control Loop definition name", required = true)
+ @QueryParam("name") String name,
+ @ApiParam(value = "Control Loop definition version", required = true)
+ @QueryParam("version") String version) throws Exception {
+
+ try {
+ List<ToscaNodeTemplate> nodeTemplate = provider.getControlLoopDefinitions(name, version);
+ //Prevent ambiguous queries with multiple returns
+ if (nodeTemplate.size() > 1) {
+ throw new Exception();
+ }
+ List<ToscaNodeTemplate> response = provider.getControlLoopElementDefinitions(nodeTemplate.get(0));
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(Status.OK)), requestId).entity(response)
+ .build();
+
+ } catch (PfModelRuntimeException | PfModelException e) {
+ LOGGER.warn("Get of control loop element definitions failed", e);
+ return createCommissioningErrorResponse(e, requestId);
+ }
+
+ }
+
+ private Response createCommissioningErrorResponse(ErrorResponseInfo e, UUID requestId) {
+ CommissioningResponse resp = new CommissioningResponse();
+ resp.setErrorDetails(e.getErrorResponse().getErrorMessage());
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())),
+ requestId).entity(resp).build();
+ }
+
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java
index c4b0955f9..fd5288fda 100644
--- a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java
+++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/instantiation/InstantiationHandler.java
@@ -27,6 +27,7 @@ import java.util.Set;
import javax.ws.rs.core.Response;
import lombok.Getter;
import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler;
+import org.onap.policy.clamp.controlloop.runtime.commissioning.rest.CommissioningController;
import org.onap.policy.clamp.controlloop.runtime.instantiation.rest.InstantiationController;
import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
import org.onap.policy.common.endpoints.event.comm.TopicSink;
@@ -66,11 +67,7 @@ public final class InstantiationHandler extends ControlLoopHandler {
@Override
public Set<Class<?>> getProviderClasses() {
- Set<Class<?>> providerClasses = new HashSet<>();
-
- providerClasses.add(InstantiationController.class);
-
- return providerClasses;
+ return Set.of(InstantiationController.class);
}
@Override
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java
index d3a5c5810..0078f6129 100644
--- a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java
+++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/main/startstop/ClRuntimeActivator.java
@@ -20,11 +20,14 @@
package org.onap.policy.clamp.controlloop.runtime.main.startstop;
+import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import javax.ws.rs.core.Response.Status;
import org.onap.policy.clamp.controlloop.common.exception.ControlLoopRuntimeException;
+import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler;
+import org.onap.policy.clamp.controlloop.runtime.commissioning.CommissioningHandler;
import org.onap.policy.clamp.controlloop.runtime.instantiation.InstantiationHandler;
import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
import org.onap.policy.clamp.controlloop.runtime.main.rest.ControlLoopAafFilter;
@@ -61,7 +64,6 @@ public class ClRuntimeActivator extends ServiceManagerContainer {
* @param clRuntimeParameterGroup the parameters for the control loop runtime service
*/
public ClRuntimeActivator(final ClRuntimeParameterGroup clRuntimeParameterGroup) {
-
if (clRuntimeParameterGroup == null || !clRuntimeParameterGroup.isValid()) {
throw new ControlLoopRuntimeException(Status.INTERNAL_SERVER_ERROR, "ParameterGroup not valid");
}
@@ -81,53 +83,61 @@ public class ClRuntimeActivator extends ServiceManagerContainer {
"topic message dispatcher failed to start", e);
}
- final AtomicReference<InstantiationHandler> instantiationHandler = new AtomicReference<>();
- final AtomicReference<RestServer> restServer = new AtomicReference<>();
+ final AtomicReference<ControlLoopHandler> commissioningHandler = new AtomicReference<>();
+ final AtomicReference<ControlLoopHandler> instantiationHandler = new AtomicReference<>();
+ final AtomicReference<RestServer> restServer = new AtomicReference<>();
// @formatter:off
addAction("Control loop runtime parameters",
- () -> ParameterService.register(clRuntimeParameterGroup),
- () -> ParameterService.deregister(clRuntimeParameterGroup.getName()));
-
+ () -> ParameterService.register(clRuntimeParameterGroup),
+ () -> ParameterService.deregister(clRuntimeParameterGroup.getName()));
addAction("Topic endpoint management",
- () -> TopicEndpointManager.getManager().start(),
- () -> TopicEndpointManager.getManager().shutdown());
-
+ () -> TopicEndpointManager.getManager().start(),
+ () -> TopicEndpointManager.getManager().shutdown());
+ addAction("Commissioning Handler",
+ () -> commissioningHandler.set(new CommissioningHandler(clRuntimeParameterGroup)),
+ () -> commissioningHandler.get().close());
addAction("Instantiation Handler",
- () -> instantiationHandler.set(new InstantiationHandler(clRuntimeParameterGroup)),
- () -> instantiationHandler.get().close());
-
- addAction("Providers",
- () -> instantiationHandler.get().startProviders(),
- () -> instantiationHandler.get().stopProviders());
+ () -> instantiationHandler.set(new InstantiationHandler(clRuntimeParameterGroup)),
+ () -> instantiationHandler.get().close());
- addAction("Listeners",
- () -> instantiationHandler.get().startAndRegisterListeners(msgDispatcher),
- () -> instantiationHandler.get().stopAndUnregisterListeners(msgDispatcher));
-
- addAction("Publishers",
- () -> instantiationHandler.get().startAndRegisterPublishers(topicSinks),
- () -> instantiationHandler.get().stopAndUnregisterPublishers());
+ addHandlerActions("Commissioning", commissioningHandler);
+ addHandlerActions("Instantiation", instantiationHandler);
addAction("Topic Message Dispatcher", this::registerMsgDispatcher, this::unregisterMsgDispatcher);
clRuntimeParameterGroup.getRestServerParameters().setName(clRuntimeParameterGroup.getName());
addAction("REST server",
- () -> {
- Set<Class<?>> providerClasses = instantiationHandler.get().getProviderClasses();
+ () -> {
+ Set<Class<?>> providerClasses = new HashSet<>();
+ providerClasses.addAll(commissioningHandler.get().getProviderClasses());
+ providerClasses.addAll(instantiationHandler.get().getProviderClasses());
- RestServer server = new RestServer(clRuntimeParameterGroup.getRestServerParameters(),
+ RestServer server = new RestServer(clRuntimeParameterGroup.getRestServerParameters(),
ControlLoopAafFilter.class,
providerClasses.toArray(new Class<?>[providerClasses.size()]));
-
- restServer.set(server);
- restServer.get().start();
- },
- () -> restServer.get().stop());
+ restServer.set(server);
+ restServer.get().start();
+ },
+ () -> restServer.get().stop());
// @formatter:on
}
+ private void addHandlerActions(final String name, final AtomicReference<ControlLoopHandler> handler) {
+ addAction(name + " Providers",
+ () -> handler.get().startProviders(),
+ () -> handler.get().stopProviders());
+
+ addAction(name + " Listeners",
+ () -> handler.get().startAndRegisterListeners(msgDispatcher),
+ () -> handler.get().stopAndUnregisterListeners(msgDispatcher));
+
+ addAction(name + " Publishers",
+ () -> handler.get().startAndRegisterPublishers(topicSinks),
+ () -> handler.get().stopAndUnregisterPublishers());
+ }
+
/**
* Registers the dispatcher with the topic source(s).
*/
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java
new file mode 100644
index 000000000..04f458e7d
--- /dev/null
+++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringHandler.java
@@ -0,0 +1,104 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.monitoring;
+
+import java.io.IOException;
+import java.util.List;
+import java.util.Set;
+import javax.ws.rs.core.Response;
+import lombok.Getter;
+import org.onap.policy.clamp.controlloop.common.handler.ControlLoopHandler;
+import org.onap.policy.clamp.controlloop.runtime.main.parameters.ClRuntimeParameterGroup;
+import org.onap.policy.clamp.controlloop.runtime.monitoring.rest.MonitoringQueryController;
+import org.onap.policy.common.endpoints.event.comm.TopicSink;
+import org.onap.policy.common.endpoints.listeners.MessageTypeDispatcher;
+import org.onap.policy.common.utils.services.Registry;
+import org.onap.policy.models.base.PfModelRuntimeException;
+
+/**
+ * This class handles monitoring of control loop definitions,
+ * so only one object of this type should be built at a time.
+ *
+ * <p/>
+ * It is effectively a singleton that is started at system start.
+ */
+public class MonitoringHandler extends ControlLoopHandler {
+
+ @Getter
+ private MonitoringProvider monitoringProvider;
+
+ /**
+ * Gets the Monitoring Handler.
+ *
+ * @return MonitoringHandler
+ */
+ public static MonitoringHandler getInstance() {
+ return Registry.get(MonitoringHandler.class.getName());
+ }
+
+ /**
+ * Create a handler.
+ *
+ * @param controlLoopParameters the parameters for access to the database
+ */
+ public MonitoringHandler(ClRuntimeParameterGroup controlLoopParameters) {
+ super(controlLoopParameters.getDatabaseProviderParameters());
+ }
+
+ @Override
+ public Set<Class<?>> getProviderClasses() {
+ return Set.of(MonitoringQueryController.class);
+ }
+
+ @Override
+ public void startAndRegisterListeners(MessageTypeDispatcher msgDispatcher) {
+ // No topic communication on this handler
+ }
+
+ @Override
+ public void startAndRegisterPublishers(List<TopicSink> topicSinks) {
+ // No topic communication on this handler
+ }
+
+ @Override
+ public void stopAndUnregisterPublishers() {
+ // No topic communication on this handler
+ }
+
+ @Override
+ public void stopAndUnregisterListeners(MessageTypeDispatcher msgDispatcher) {
+ // No topic communication on this handler
+ }
+
+ @Override
+ public void startProviders() {
+ monitoringProvider = new MonitoringProvider(getDatabaseProviderParameters());
+ }
+
+ @Override
+ public void stopProviders() {
+ try {
+ monitoringProvider.close();
+ } catch (IOException e) {
+ throw new PfModelRuntimeException(Response.Status.INTERNAL_SERVER_ERROR, "Cannot stop provider", e);
+ }
+ }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java
new file mode 100644
index 000000000..aeabce7a5
--- /dev/null
+++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/MonitoringProvider.java
@@ -0,0 +1,273 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.monitoring;
+
+import java.io.Closeable;
+import java.io.IOException;
+import java.time.Instant;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import lombok.NonNull;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatistics;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoop;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ControlLoopElement;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatistics;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatisticsList;
+import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ClElementStatisticsProvider;
+import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ControlLoopProvider;
+import org.onap.policy.clamp.controlloop.models.controlloop.persistence.provider.ParticipantStatisticsProvider;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.onap.policy.models.provider.PolicyModelsProviderParameters;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaConceptIdentifier;
+
+/**
+ * This class provides information about statistics data of CL elements and CL Participants in database to callers.
+ */
+public class MonitoringProvider implements Closeable {
+
+ private static final String DESC_ORDER = "DESC";
+ private final ParticipantStatisticsProvider participantStatisticsProvider;
+ private final ClElementStatisticsProvider clElementStatisticsProvider;
+ private final ControlLoopProvider controlLoopProvider;
+
+ /**
+ * Create a Monitoring provider.
+ *
+ */
+ public MonitoringProvider(PolicyModelsProviderParameters parameters) {
+
+ try {
+ participantStatisticsProvider = new ParticipantStatisticsProvider(parameters);
+ clElementStatisticsProvider = new ClElementStatisticsProvider(parameters);
+ controlLoopProvider = new ControlLoopProvider(parameters);
+ } catch (PfModelException e) {
+ throw new PfModelRuntimeException(e);
+ }
+ }
+
+ @Override
+ public void close() throws IOException {
+ controlLoopProvider.close();
+ clElementStatisticsProvider.close();
+ participantStatisticsProvider.close();
+ }
+
+ /**
+ * Create participant statistics.
+ *
+ * @param participantStatistics the participant statistics
+ * @return the result of create operation
+ * @throws PfModelException on creation errors
+ */
+ public ParticipantStatisticsList createParticipantStatistics(List<ParticipantStatistics> participantStatistics)
+ throws PfModelException {
+ ParticipantStatisticsList participantStatisticsList = new ParticipantStatisticsList();
+ participantStatisticsList.setStatisticsList(participantStatisticsProvider
+ .createParticipantStatistics(participantStatistics));
+
+ return participantStatisticsList;
+ }
+
+ /**
+ * Create clElement statistics.
+ *
+ * @param clElementStatisticsList the clElement statistics
+ * @return the result of create operation
+ * @throws PfModelException on creation errors
+ */
+ public ClElementStatisticsList createClElementStatistics(List<ClElementStatistics> clElementStatisticsList)
+ throws PfModelException {
+ ClElementStatisticsList elementStatisticsList = new ClElementStatisticsList();
+ elementStatisticsList.setClElementStatistics(clElementStatisticsProvider
+ .createClElementStatistics(clElementStatisticsList));
+
+ return elementStatisticsList;
+ }
+
+ /**
+ * Get participant statistics based on specific filters.
+ *
+ * @param name the name of the participant statistics to get, null to get all statistics
+ * @param version the version of the participant statistics to get, null to get all statistics
+ * @param recordCount number of records to be fetched.
+ * @param startTime start of the timestamp, from statistics to be filtered
+ * @param endTime end of the timestamp up to which statistics to be filtered
+ * @return the participant found
+ */
+ public ParticipantStatisticsList fetchFilteredParticipantStatistics(@NonNull final String name,
+ final String version, int recordCount,
+ Instant startTime, Instant endTime) {
+ ParticipantStatisticsList participantStatisticsList = new ParticipantStatisticsList();
+
+ //Additional parameters can be added in filterMap for filtering data.
+ Map<String, Object> filterMap = null;
+ participantStatisticsList.setStatisticsList(participantStatisticsProvider.getFilteredParticipantStatistics(
+ name, version, startTime, endTime, filterMap, DESC_ORDER, recordCount));
+
+ return participantStatisticsList;
+ }
+
+ /**
+ * Get all participant statistics records found for a specific control loop. *
+ *
+ * @param controlLoopName name of the control loop
+ * @param controlLoopVersion version of the control loop
+ * @return All the participant statistics found
+ * @throws PfModelException on errors getting participant statistics
+ */
+ public ParticipantStatisticsList fetchParticipantStatsPerControlLoop(@NonNull final String controlLoopName,
+ @NonNull final String controlLoopVersion)
+ throws PfModelException {
+ ParticipantStatisticsList statisticsList = new ParticipantStatisticsList();
+ List<ParticipantStatistics> participantStatistics = new ArrayList<>();
+ try {
+ //Fetch all participantIds for a specific control loop
+ List<ToscaConceptIdentifier> participantIds = getAllParticipantIdsPerControlLoop(controlLoopName,
+ controlLoopVersion);
+ for (ToscaConceptIdentifier id: participantIds) {
+ participantStatistics.addAll(participantStatisticsProvider.getFilteredParticipantStatistics(
+ id.getName(), id.getVersion(), null, null, null, DESC_ORDER, 0));
+ }
+ statisticsList.setStatisticsList(participantStatistics);
+ } catch (PfModelException e) {
+ throw new PfModelRuntimeException(e);
+ }
+ return statisticsList;
+ }
+
+
+
+ /**
+ * Get clElement statistics based on specific filters.
+ *
+ * @param name the name of the clElement statistics to get, null to get all statistics
+ * @param version the version of the clElement statistics to get, null to get all statistics
+ * @param id UUID of the control loop element
+ * @param startTime start of the timestamp, from statistics to be filtered
+ * @param endTime end of the timestamp up to which statistics to be filtered
+ * @param recordCount number of records to be fetched.
+ * @return the participant found
+ * @throws PfModelException on errors getting control loop statistics
+ */
+ public ClElementStatisticsList fetchFilteredClElementStatistics(@NonNull final String name, final String version,
+ final String id, Instant startTime, Instant endTime,
+ int recordCount) throws PfModelException {
+ ClElementStatisticsList clElementStatisticsList = new ClElementStatisticsList();
+ Map<String, Object> filterMap = new HashMap<>();
+ //Adding UUID in filter if present
+ if (id != null) {
+ filterMap.put("localName", id);
+ }
+ clElementStatisticsList.setClElementStatistics(clElementStatisticsProvider.getFilteredClElementStatistics(
+ name, version, startTime, endTime, filterMap, DESC_ORDER, recordCount));
+
+ return clElementStatisticsList;
+ }
+
+
+ /**
+ * Get clElement statistics per control loop.
+ *
+ * @param name the name of the control loop
+ * @param version the version of the control loop
+ * @return the clElement statistics found
+ * @throws PfModelException on errors getting control loop statistics
+ */
+ public ClElementStatisticsList fetchClElementStatsPerControlLoop(@NonNull final String name,
+ @NonNull final String version)
+ throws PfModelException {
+ ClElementStatisticsList clElementStatisticsList = new ClElementStatisticsList();
+ List<ClElementStatistics> clElementStats = new ArrayList<>();
+ try {
+ List<ControlLoopElement> clElements = new ArrayList<>();
+ //Fetch all control loop elements for the control loop
+ ControlLoop controlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(name,
+ version));
+ clElements.addAll(controlLoop.getElements());
+
+ //Collect control loop element statistics for each cl element.
+ for (ControlLoopElement clElement : clElements) {
+ clElementStats.addAll(fetchFilteredClElementStatistics(clElement.getParticipantId().getName(),
+ clElement.getParticipantId().getVersion(), clElement.getId().toString(), null,
+ null, 0).getClElementStatistics());
+ }
+ clElementStatisticsList.setClElementStatistics(clElementStats);
+ } catch (PfModelException e) {
+ throw new PfModelRuntimeException(e);
+ }
+
+ return clElementStatisticsList;
+ }
+
+ /**
+ * If required, REST end point can be defined for this method to fetch associated participant Ids
+ * for a control loop.
+ *
+ * @param name the name of the control loop
+ * @param version the version of the control loop
+ * @return List of participant Id
+ * @throws PfModelException on errors
+ */
+ public List<ToscaConceptIdentifier> getAllParticipantIdsPerControlLoop(String name, String version)
+ throws PfModelException {
+ List<ToscaConceptIdentifier> participantIds = new ArrayList<>();
+ ControlLoop controlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(name, version));
+ if (controlLoop != null) {
+ for (ControlLoopElement clElement : controlLoop.getElements()) {
+ participantIds.add(clElement.getParticipantId());
+ }
+ }
+ return participantIds;
+ }
+
+ /**
+ * If required, REST end point can be defined for this method to fetch associated control loop element Ids
+ * for a control loop.
+ *
+ * @param name the name of the control loop
+ * @param version the version of the control loop
+ * @return Map of control loop Id and participant details
+ * @throws PfModelException on errors
+ */
+ public Map<String, ToscaConceptIdentifier> getAllClElementsIdPerControlLoop(String name, String version)
+ throws PfModelException {
+ Map<String, ToscaConceptIdentifier> clElementId = new HashMap<>();
+ ControlLoop controlLoop = controlLoopProvider.getControlLoop(new ToscaConceptIdentifier(name, version));
+ for (ControlLoopElement clElement : controlLoop.getElements()) {
+ clElementId.put(clElement.getId().toString(), clElement.getParticipantId());
+ }
+ return clElementId;
+ }
+
+
+
+ public void updateClElementStatistics(List<ClElementStatistics> clElementStatistics) {
+ // TODO Auto-generated method stub
+ }
+
+ public void updateParticipantStatistics(List<ParticipantStatistics> statisticsList) {
+ // TODO Auto-generated method stub
+ }
+}
diff --git a/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java
new file mode 100644
index 000000000..2e19ffe3a
--- /dev/null
+++ b/tosca-controlloop/runtime/src/main/java/org/onap/policy/clamp/controlloop/runtime/monitoring/rest/MonitoringQueryController.java
@@ -0,0 +1,371 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.monitoring.rest;
+
+import io.swagger.annotations.ApiOperation;
+import io.swagger.annotations.ApiParam;
+import io.swagger.annotations.ApiResponse;
+import io.swagger.annotations.ApiResponses;
+import io.swagger.annotations.Authorization;
+import io.swagger.annotations.Extension;
+import io.swagger.annotations.ExtensionProperty;
+import io.swagger.annotations.ResponseHeader;
+import java.time.Instant;
+import java.util.UUID;
+import javax.ws.rs.DefaultValue;
+import javax.ws.rs.GET;
+import javax.ws.rs.HeaderParam;
+import javax.ws.rs.Path;
+import javax.ws.rs.QueryParam;
+import javax.ws.rs.core.Response;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ClElementStatisticsList;
+import org.onap.policy.clamp.controlloop.models.controlloop.concepts.ParticipantStatisticsList;
+import org.onap.policy.clamp.controlloop.runtime.main.rest.RestController;
+import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringHandler;
+import org.onap.policy.clamp.controlloop.runtime.monitoring.MonitoringProvider;
+import org.onap.policy.models.base.PfModelException;
+import org.onap.policy.models.base.PfModelRuntimeException;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * This class handles REST endpoints for CL Statistics monitoring.
+ */
+public class MonitoringQueryController extends RestController {
+
+ private static final Logger LOGGER = LoggerFactory.getLogger(MonitoringQueryController.class);
+ private final MonitoringProvider provider;
+
+ /**
+ * Create Monitoring Controller.
+ */
+ public MonitoringQueryController() {
+ this.provider = MonitoringHandler.getInstance().getMonitoringProvider();
+ }
+
+
+ /**
+ * Queries details of control loop participants statistics.
+ *
+ * @param requestId request ID used in ONAP logging
+ * @param name the name of the participant to get, null for all participants statistics
+ * @param recordCount the record count to be fetched
+ * @return the participant statistics
+ */
+ // @formatter:off
+ @GET
+ @Path("/monitoring/participant")
+ @ApiOperation(value = "Query details of the requested participant stats",
+ notes = "Queries details of the requested participant stats, returning all participant stats",
+ response = ParticipantStatisticsList.class,
+ tags = {
+ "Clamp control loop Monitoring API"
+ },
+ authorizations = @Authorization(value = AUTHORIZATION_TYPE),
+ responseHeaders = {
+ @ResponseHeader(
+ name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
+ response = UUID.class)},
+ extensions = {
+ @Extension(
+ name = EXTENSION_NAME,
+ properties = {
+ @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
+ @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
+ }
+ )
+ }
+ )
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
+ @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
+ @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
+ }
+ )
+ // @formatter:on
+ public Response queryParticipantStatistics(@HeaderParam(REQUEST_ID_NAME)
+ @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Control Loop participant name", required = true)
+ @QueryParam("name") final String name,
+ @ApiParam(value = "Control Loop participant version", required = true)
+ @QueryParam("version") final String version,
+ @ApiParam(value = "Record count", required = false) @DefaultValue("0")
+ @QueryParam("recordCount") final int recordCount,
+ @ApiParam(value = "start time", required = false)
+ @QueryParam("startTime") final String startTime,
+ @ApiParam(value = "end time", required = false)
+ @QueryParam("endTime") final String endTime) {
+
+ try {
+ Instant startTimestamp = null;
+ Instant endTimestamp = null;
+
+ if (startTime != null) {
+ startTimestamp = Instant.parse(startTime);
+ }
+ if (endTime != null) {
+ endTimestamp = Instant.parse(endTime);
+ }
+ ParticipantStatisticsList response = provider.fetchFilteredParticipantStatistics(name, version, recordCount,
+ startTimestamp, endTimestamp);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
+ .entity(response)
+ .build();
+
+ } catch (PfModelRuntimeException e) {
+ LOGGER.warn("Monitoring of participants statistics failed", e);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())),
+ requestId).build();
+ }
+
+ }
+
+ /**
+ * Queries details of all participant statistics per control loop.
+ *
+ * @param requestId request ID used in ONAP logging
+ * @param name the name of the control loop
+ * @param version version of the control loop
+ * @return the control loop element statistics
+ */
+ // @formatter:off
+ @GET
+ @Path("/monitoring/participants/controlloop")
+ @ApiOperation(value = "Query details of all the participant stats in a control loop",
+ notes = "Queries details of the participant stats, returning all participant stats",
+ response = ClElementStatisticsList.class,
+ tags = {
+ "Clamp control loop Monitoring API"
+ },
+ authorizations = @Authorization(value = AUTHORIZATION_TYPE),
+ responseHeaders = {
+ @ResponseHeader(
+ name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
+ response = UUID.class)},
+ extensions = {
+ @Extension(
+ name = EXTENSION_NAME,
+ properties = {
+ @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
+ @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
+ }
+ )
+ })
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
+ @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
+ @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
+ }
+ )
+ // @formatter:on
+ public Response queryParticipantStatisticsPerControlLoop(@HeaderParam(REQUEST_ID_NAME)
+ @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Control Loop name", required = true)
+ @QueryParam("name") final String name,
+ @ApiParam(value = "Control Loop version", required = true)
+ @QueryParam("version") final String version) {
+
+ try {
+ ParticipantStatisticsList response = provider.fetchParticipantStatsPerControlLoop(name, version);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
+ .entity(response)
+ .build();
+
+ } catch (PfModelRuntimeException | PfModelException e) {
+ LOGGER.warn("Monitoring of Cl participant statistics failed", e);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())),
+ requestId).build();
+ }
+
+ }
+
+
+
+ /**
+ * Queries details of all control loop element statistics per control loop.
+ *
+ * @param requestId request ID used in ONAP logging
+ * @param name the name of the control loop
+ * @param version version of the control loop
+ * @return the control loop element statistics
+ */
+ // @formatter:off
+ @GET
+ @Path("/monitoring/clelements/controlloop")
+ @ApiOperation(value = "Query details of the requested cl element stats in a control loop",
+ notes = "Queries details of the requested cl element stats, returning all clElement stats",
+ response = ClElementStatisticsList.class,
+ tags = {
+ "Clamp control loop Monitoring API"
+ },
+ authorizations = @Authorization(value = AUTHORIZATION_TYPE),
+ responseHeaders = {
+ @ResponseHeader(
+ name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
+ response = UUID.class)},
+ extensions = {
+ @Extension(
+ name = EXTENSION_NAME,
+ properties = {
+ @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
+ @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
+ }
+ )
+ })
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
+ @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
+ @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
+ }
+ )
+ // @formatter:on
+ public Response queryElementStatisticsPerControlLoop(@HeaderParam(REQUEST_ID_NAME)
+ @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Control Loop name", required = true)
+ @QueryParam("name") final String name,
+ @ApiParam(value = "Control Loop version", required = true)
+ @QueryParam("version") final String version) {
+
+ try {
+ ClElementStatisticsList response = provider.fetchClElementStatsPerControlLoop(name, version);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
+ .entity(response)
+ .build();
+
+ } catch (PfModelRuntimeException | PfModelException e) {
+ LOGGER.warn("Monitoring of Cl Element statistics failed", e);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())),
+ requestId).build();
+ }
+
+ }
+
+
+
+
+ /**
+ * Queries details of all control loop element statistics per control loop.
+ *
+ * @param requestId request ID used in ONAP logging
+ * @param name the name of the control loop
+ * @param version version of the control loop
+ * @param id Id of the control loop element
+ * @param recordCount the record count to be fetched
+ * @return the control loop element statistics
+ */
+ // @formatter:off
+ @GET
+ @Path("/monitoring/clelement")
+ @ApiOperation(value = "Query details of the requested cl element stats",
+ notes = "Queries details of the requested cl element stats, returning all clElement stats",
+ response = ClElementStatisticsList.class,
+ tags = {
+ "Clamp control loop Monitoring API"
+ },
+ authorizations = @Authorization(value = AUTHORIZATION_TYPE),
+ responseHeaders = {
+ @ResponseHeader(
+ name = VERSION_MINOR_NAME, description = VERSION_MINOR_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_PATCH_NAME, description = VERSION_PATCH_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = VERSION_LATEST_NAME, description = VERSION_LATEST_DESCRIPTION,
+ response = String.class),
+ @ResponseHeader(name = REQUEST_ID_NAME, description = REQUEST_ID_HDR_DESCRIPTION,
+ response = UUID.class)},
+ extensions = {
+ @Extension(
+ name = EXTENSION_NAME,
+ properties = {
+ @ExtensionProperty(name = API_VERSION_NAME, value = API_VERSION),
+ @ExtensionProperty(name = LAST_MOD_NAME, value = LAST_MOD_RELEASE)
+ }
+ )
+ })
+ @ApiResponses(
+ value = {
+ @ApiResponse(code = AUTHENTICATION_ERROR_CODE, message = AUTHENTICATION_ERROR_MESSAGE),
+ @ApiResponse(code = AUTHORIZATION_ERROR_CODE, message = AUTHORIZATION_ERROR_MESSAGE),
+ @ApiResponse(code = SERVER_ERROR_CODE, message = SERVER_ERROR_MESSAGE)
+ }
+ )
+ // @formatter:on
+ public Response queryElementStatistics(@HeaderParam(REQUEST_ID_NAME)
+ @ApiParam(REQUEST_ID_PARAM_DESCRIPTION) UUID requestId,
+ @ApiParam(value = "Participant name", required = true)
+ @QueryParam("name") final String name,
+ @ApiParam(value = "Participant version", required = true)
+ @QueryParam("version") final String version,
+ @ApiParam(value = "Record count", required = false)
+ @DefaultValue("0") @QueryParam("recordCount") final int recordCount,
+ @ApiParam(value = "Control Loop element id", required = false)
+ @QueryParam("id") final String id,
+ @ApiParam(value = "start time", required = false)
+ @QueryParam("startTime") final String startTime,
+ @ApiParam(value = "end time", required = false)
+ @QueryParam("endTime") final String endTime) {
+
+ try {
+ Instant startTimestamp = null;
+ Instant endTimestamp = null;
+
+ if (startTime != null) {
+ startTimestamp = Instant.parse(startTime);
+ }
+ if (endTime != null) {
+ endTimestamp = Instant.parse(endTime);
+ }
+ ClElementStatisticsList response = provider.fetchFilteredClElementStatistics(name, version, id,
+ startTimestamp, endTimestamp, recordCount);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(Response.Status.OK)), requestId)
+ .entity(response)
+ .build();
+
+ } catch (PfModelRuntimeException | PfModelException e) {
+ LOGGER.warn("Monitoring of Cl Element statistics failed", e);
+ return addLoggingHeaders(addVersionControlHeaders(Response.status(e.getErrorResponse().getResponseCode())),
+ requestId).build();
+ }
+
+ }
+
+}
diff --git a/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java b/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java
new file mode 100644
index 000000000..fa146635d
--- /dev/null
+++ b/tosca-controlloop/runtime/src/test/java/org/onap/policy/clamp/controlloop/runtime/commissioning/rest/CommissioningControllerTest.java
@@ -0,0 +1,202 @@
+/*-
+ * ============LICENSE_START=======================================================
+ * Copyright (C) 2021 Nordix Foundation.
+ * ================================================================================
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+
+package org.onap.policy.clamp.controlloop.runtime.commissioning.rest;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import java.util.List;
+import javax.ws.rs.client.Entity;
+import javax.ws.rs.client.Invocation;
+import javax.ws.rs.core.Response;
+import org.junit.AfterClass;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.onap.policy.clamp.controlloop.models.messages.rest.commissioning.CommissioningResponse;
+import org.onap.policy.clamp.controlloop.runtime.util.rest.CommonRestController;
+import org.onap.policy.common.utils.coder.YamlJsonTranslator;
+import org.onap.policy.common.utils.resources.ResourceUtils;
+import org.onap.policy.models.provider.PolicyModelsProvider;
+import org.onap.policy.models.provider.PolicyModelsProviderFactory;
+import org.onap.policy.models.tosca.authorative.concepts.ToscaServiceTemplate;
+
+public class CommissioningControllerTest extends CommonRestController {
+
+ private static final String TOSCA_SERVICE_TEMPLATE_YAML =
+ "src/test/resources/servicetemplates/pmsh_multiple_cl_tosca.yaml";
+ private static final YamlJsonTranslator yamlTranslator = new YamlJsonTranslator();
+ private static final String COMMISSIONING_ENDPOINT = "commission";
+ private static ToscaServiceTemplate serviceTemplate = new ToscaServiceTemplate();
+
+ /**
+ * starts Main and inserts a commissioning template.
+ *
+ * @throws Exception if an error occurs
+ */
+ @BeforeClass
+ public static void setUpBeforeClass() throws Exception {
+ CommonRestController.setUpBeforeClass("CommissioningApi");
+
+ serviceTemplate = yamlTranslator.fromYaml(ResourceUtils.getResourceAsString(TOSCA_SERVICE_TEMPLATE_YAML),
+ ToscaServiceTemplate.class);
+ }
+
+ @AfterClass
+ public static void teardownAfterClass() {
+ CommonRestController.teardownAfterClass();
+ }
+
+ @Test
+ public void testSwagger() throws Exception {
+ super.testSwagger(COMMISSIONING_ENDPOINT);
+ }
+
+ @Test
+ public void testUnauthorizedCreate() throws Exception {
+ assertUnauthorizedPost(COMMISSIONING_ENDPOINT, Entity.json(serviceTemplate));
+ }
+
+ @Test
+ public void testUnauthorizedQuery() throws Exception {
+ assertUnauthorizedGet(COMMISSIONING_ENDPOINT);
+ }
+
+ @Test
+ public void testUnauthorizedQueryElements() throws Exception {
+ assertUnauthorizedGet(COMMISSIONING_ENDPOINT + "/elements");
+ }
+
+ @Test
+ public void testUnauthorizedDelete() throws Exception {
+ assertUnauthorizedDelete(COMMISSIONING_ENDPOINT);
+ }
+
+ @Test
+ public void testCreateBadRequest() throws Exception {
+ Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
+ Response resp = invocationBuilder.post(Entity.json("NotToscaServiceTempalte"));
+
+ assertEquals(Response.Status.BAD_REQUEST.getStatusCode(), resp.getStatus());
+ CommissioningResponse commissioningResponse = resp.readEntity(CommissioningResponse.class);
+ assertNotNull(commissioningResponse.getErrorDetails());
+ assertNull(commissioningResponse.getAffectedControlLoopDefinitions());
+ }
+
+ @Test
+ public void testCreate() throws Exception {
+ Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
+ Response resp = invocationBuilder.post(Entity.json(serviceTemplate));
+ assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus());
+ CommissioningResponse commissioningResponse = resp.readEntity(CommissioningResponse.class);
+
+ assertNotNull(commissioningResponse);
+ assertNull(commissioningResponse.getErrorDetails());
+ // Response should return the number of node templates present in the service template
+ assertThat(commissioningResponse.getAffectedControlLoopDefinitions()).hasSize(13);
+ for (String nodeTemplateName : serviceTemplate.getToscaTopologyTemplate().getNodeTemplates().keySet()) {
+ assertTrue(commissioningResponse.getAffectedControlLoopDefinitions().stream()
+ .anyMatch(ac -> ac.getName().equals(nodeTemplateName)));
+ }
+ }
+
+ @Test
+ public void testQuery_NoResultWithThisName() throws Exception {
+ createEntryInDB();
+
+ Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name=noResultWithThisName");
+ Response rawresp = invocationBuilder.buildGet().invoke();
+ assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
+ List entityList = rawresp.readEntity(List.class);
+ assertThat(entityList).isEmpty();
+ }
+
+ @Test
+ public void testQuery() throws Exception {
+ createEntryInDB();
+
+ Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
+ Response rawresp = invocationBuilder.buildGet().invoke();
+ assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
+ List entityList = rawresp.readEntity(List.class);
+ assertNotNull(entityList);
+ assertThat(entityList).hasSize(2);
+ }
+
+ @Test
+ public void testQueryElementsBadRequest() throws Exception {
+ createEntryInDB();
+
+ //Call get elements with no info
+ Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/elements");
+ Response resp = invocationBuilder.buildGet().invoke();
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), resp.getStatus());
+ }
+
+ @Test
+ public void testQueryElements() throws Exception {
+ createEntryInDB();
+
+ Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "/elements"
+ + "?name=org.onap.domain.pmsh.PMSHControlLoopDefinition");
+ Response rawresp = invocationBuilder.buildGet().invoke();
+ assertEquals(Response.Status.OK.getStatusCode(), rawresp.getStatus());
+ List entityList = rawresp.readEntity(List.class);
+ assertNotNull(entityList);
+ assertThat(entityList).hasSize(4);
+ }
+
+ @Test
+ public void testDeleteBadRequest() throws Exception {
+ createEntryInDB();
+
+ Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT);
+ //Call delete with no info
+ Response resp = invocationBuilder.delete();
+ assertEquals(Response.Status.INTERNAL_SERVER_ERROR.getStatusCode(), resp.getStatus());
+ }
+
+ @Test
+ public void testDelete() throws Exception {
+ createEntryInDB();
+
+ Invocation.Builder invocationBuilder = super.sendRequest(COMMISSIONING_ENDPOINT + "?name="
+ + serviceTemplate.getName() + "&version=" + serviceTemplate.getVersion());
+ //Call delete with no info
+ Response resp = invocationBuilder.delete();
+ assertEquals(Response.Status.OK.getStatusCode(), resp.getStatus());
+
+ try (PolicyModelsProvider modelsProvider = new PolicyModelsProviderFactory()
+ .createPolicyModelsProvider(CommonRestController.getParameters())) {
+ List<ToscaServiceTemplate> templatesInDB = modelsProvider.getServiceTemplateList(null, null);
+ assertThat(templatesInDB).isEmpty();
+ }
+ }
+
+ private synchronized void createEntryInDB() throws Exception {
+ try (PolicyModelsProvider modelsProvider = new PolicyModelsProviderFactory()
+ .createPolicyModelsProvider(CommonRestController.getParameters())) {
+ modelsProvider.createServiceTemplate(serviceTemplate);
+ }
+ }
+}