From 2ccd5e6a5dc191f574dc7509bb507e294c7a0afa Mon Sep 17 00:00:00 2001 From: waynedunican Date: Tue, 29 Jul 2025 14:42:11 +0100 Subject: [PATCH] Add endpoint for participant restart Issue-ID: POLICY-5436 Change-Id: Ie7828d5475366d21b22bc7e04131069cfbc1595a Signed-off-by: waynedunican --- .../runtime/main/rest/ParticipantController.java | 12 ++ .../main/rest/stub/ParticipantControllerStub.java | 10 ++ .../participants/AcmParticipantProvider.java | 27 +++ .../supervision/SupervisionParticipantHandler.java | 18 +- .../src/main/resources/openapi/openapi.yaml | 183 +++++++++++++++++++++ .../contract/ParticipantControllerStubTest.java | 21 +++ .../participant/ParticipantControllerTest.java | 32 ++++ 7 files changed, 302 insertions(+), 1 deletion(-) diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java index 51b3baa00..3f96afa84 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/ParticipantController.java @@ -66,4 +66,16 @@ public class ParticipantController extends AbstractRestController implements Par var participantInformationList = acmParticipantProvider.getAllParticipants(pageable); return ResponseEntity.ok().body(participantInformationList); } + + @Override + public ResponseEntity manualRestartAllParticipants(UUID onapRequestId) { + acmParticipantProvider.restartAllParticipants(); + return new ResponseEntity<>(HttpStatus.ACCEPTED); + } + + @Override + public ResponseEntity manualRestartParticipant(UUID participantId, UUID requestId) { + acmParticipantProvider.restartParticipant(participantId); + return new ResponseEntity<>(HttpStatus.ACCEPTED); + } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/ParticipantControllerStub.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/ParticipantControllerStub.java index 4b753892c..ad7df7146 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/ParticipantControllerStub.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/main/rest/stub/ParticipantControllerStub.java @@ -65,4 +65,14 @@ public class ParticipantControllerStub extends AbstractRestController implements Integer page, Integer size, UUID xonaprequestid) { return stubUtils.getResponseList(pathToParticipantList); } + + @Override + public ResponseEntity manualRestartAllParticipants(UUID xonaprequestid) { + return new ResponseEntity<>(HttpStatus.ACCEPTED); + } + + @Override + public ResponseEntity manualRestartParticipant(UUID participantId, UUID xonaprequestid) { + return new ResponseEntity<>(HttpStatus.ACCEPTED); + } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java index a2e35d788..c4ddbd011 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/participants/AcmParticipantProvider.java @@ -20,18 +20,21 @@ package org.onap.policy.clamp.acm.runtime.participants; +import jakarta.ws.rs.core.Response; import java.util.List; import java.util.Map; import java.util.UUID; import java.util.function.Function; import java.util.stream.Collectors; import lombok.RequiredArgsConstructor; +import org.onap.policy.clamp.acm.runtime.supervision.SupervisionParticipantHandler; import org.onap.policy.clamp.acm.runtime.supervision.comm.ParticipantStatusReqPublisher; import org.onap.policy.clamp.models.acm.concepts.AutomationCompositionElement; import org.onap.policy.clamp.models.acm.concepts.NodeTemplateState; import org.onap.policy.clamp.models.acm.concepts.Participant; import org.onap.policy.clamp.models.acm.concepts.ParticipantInformation; import org.onap.policy.clamp.models.acm.persistence.provider.ParticipantProvider; +import org.onap.policy.models.base.PfModelRuntimeException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.data.domain.Pageable; @@ -45,6 +48,7 @@ public class AcmParticipantProvider { private static final Logger LOGGER = LoggerFactory.getLogger(AcmParticipantProvider.class); private final ParticipantProvider participantProvider; + private final SupervisionParticipantHandler supervisionParticipantHandler; private final ParticipantStatusReqPublisher participantStatusReqPublisher; /** @@ -113,4 +117,27 @@ public class AcmParticipantProvider { return acNodeTemplateStates .stream().collect(Collectors.toMap(NodeTemplateState::getNodeTemplateStateId, Function.identity())); } + + /** + * Restart specific participant. + * + * @param participantId ID of participant to restart + */ + public void restartParticipant(UUID participantId) { + if (participantProvider.findParticipant(participantId).isEmpty()) { + throw new PfModelRuntimeException(Response.Status.NOT_FOUND, + "Participant Not Found with ID: " + participantId); + } + supervisionParticipantHandler.handleRestart(participantId, null); + LOGGER.debug("Restarting participant with ID: {}", participantId); + } + + + /** + * Restart all participants. + */ + public void restartAllParticipants() { + supervisionParticipantHandler.handleRestartOfAllParticipants(); + LOGGER.debug("Restarting all participants"); + } } diff --git a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java index 26374c1a3..ba223d273 100644 --- a/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java +++ b/runtime-acm/src/main/java/org/onap/policy/clamp/acm/runtime/supervision/SupervisionParticipantHandler.java @@ -172,7 +172,13 @@ public class SupervisionParticipantHandler { participantProvider.saveParticipantReplica(replica); } - private void handleRestart(UUID participantId, UUID replicaId) { + /** + * Handle restart of a participant. + * + * @param participantId ID of the participant to restart + * @param replicaId ID of the participant replica + */ + public void handleRestart(UUID participantId, UUID replicaId) { var compositionIds = participantProvider.getCompositionIds(participantId); for (var compositionId : compositionIds) { var acDefinition = acDefinitionProvider.getAcDefinition(compositionId); @@ -196,6 +202,16 @@ public class SupervisionParticipantHandler { participantSyncPublisher.sendRestartMsg(participantId, replicaId, acDefinition, automationCompositions); } + /** + * Handle restart of all participants. + */ + public void handleRestartOfAllParticipants() { + var participants = participantProvider.getParticipants(); + for (var participant:participants) { + handleRestart(participant.getParticipantId(), null); + } + } + private boolean isAcToBeSyncRestarted(UUID participantId, AutomationComposition automationComposition) { for (var element : automationComposition.getElements().values()) { if (participantId.equals(element.getParticipantId())) { diff --git a/runtime-acm/src/main/resources/openapi/openapi.yaml b/runtime-acm/src/main/resources/openapi/openapi.yaml index 6bc692efe..d070178fa 100644 --- a/runtime-acm/src/main/resources/openapi/openapi.yaml +++ b/runtime-acm/src/main/resources/openapi/openapi.yaml @@ -447,6 +447,189 @@ paths: api-version: 8.2.1 last-mod-release: Paris x-codegen-request-body-name: body + /participants/sync: + put: + tags: + - Participant Monitoring + summary: Manually restart (sync) all registered participants + description: Initiates a manual sync (restart) operation for all registered participants. + Each participant will restart and report its status and the status of its AC element types and instances. + The result will be available through subsequent GET requests to the "participants" endpoint. + operationId: manualRestartAllParticipants + parameters: + - name: X-onap-RequestId + in: header + description: RequestID for http transaction + required: false + schema: + type: string + format: uuid + responses: + 202: + description: Accepted, sync request has been accepted and forwarded to all participants + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + 400: + description: Bad Request, returns an instance of SimpleResponse + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + content: + application/json: + schema: + $ref: '#/components/schemas/SimpleResponse' + 401: + description: Authentication Error, returns an instance of SimpleResponse + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + content: + application/json: + schema: + $ref: '#/components/schemas/SimpleResponse' + 500: + description: Internal Server Error, returns an instance of SimpleResponse + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + content: + application/json: + schema: + $ref: '#/components/schemas/SimpleResponse' + security: + - basicAuth: [] + x-interface info: + api-version: 8.2.1 + last-mod-release: Paris + x-codegen-request-body-name: body + + /participants/sync/{participantId}: + put: + tags: + - Participant Monitoring + summary: Manually restart (sync) the specified participant + description: Initiates a manual sync (restart) operation for the specified participant. + The participant will restart and report its status and the status of its AC element types and instances. + The result will be available through subsequent GET requests to the "participants" endpoint. + operationId: manualRestartParticipant + parameters: + - name: participantId + in: path + description: The UUID of the participant to manually sync + required: true + schema: + type: string + format: uuid + - name: X-onap-RequestId + in: header + description: RequestID for http transaction + required: false + schema: + type: string + format: uuid + responses: + 202: + description: Accepted, sync request has been accepted and forwarded to the participant + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + 400: + description: Bad Request, returns an instance of SimpleResponse + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + content: + application/json: + schema: + $ref: '#/components/schemas/SimpleResponse' + 401: + description: Authentication Error, returns an instance of SimpleResponse + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + content: + application/json: + schema: + $ref: '#/components/schemas/SimpleResponse' + 404: + description: Specified participant not found, returns an instance of SimpleResponse + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + content: + application/json: + schema: + $ref: '#/components/schemas/SimpleResponse' + 500: + description: Internal Server Error, returns an instance of SimpleResponse + headers: + X-LatestVersion: + $ref: '#/components/headers/X-LatestVersion' + X-PatchVersion: + $ref: '#/components/headers/X-PatchVersion' + X-MinorVersion: + $ref: '#/components/headers/X-MinorVersion' + X-onap-RequestId: + $ref: '#/components/headers/X-onap-RequestId' + content: + application/json: + schema: + $ref: '#/components/schemas/SimpleResponse' + security: + - basicAuth: [] + x-interface info: + api-version: 8.2.1 + last-mod-release: Paris + x-codegen-request-body-name: body /compositions: get: tags: diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/contract/ParticipantControllerStubTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/contract/ParticipantControllerStubTest.java index b15a5bd75..736f1306e 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/contract/ParticipantControllerStubTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/contract/ParticipantControllerStubTest.java @@ -21,10 +21,12 @@ package org.onap.policy.clamp.acm.runtime.contract; import static org.assertj.core.api.Assertions.assertThat; +import static org.junit.jupiter.api.Assertions.assertEquals; import jakarta.ws.rs.client.Entity; import jakarta.ws.rs.core.MediaType; import jakarta.ws.rs.core.Response; +import java.util.UUID; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.junit.jupiter.api.extension.ExtendWith; @@ -82,4 +84,23 @@ class ParticipantControllerStubTest extends CommonRestController { assertThat(Response.Status.ACCEPTED.getStatusCode()).isEqualTo(respPost.getStatus()); respPost.close(); } + + @Test + void testRestartParticipants() { + var invocationBuilder = super.sendRequest(PARTICIPANT_ENDPOINT + "/sync"); + + var response = invocationBuilder.header("Content-Length", 0) + .put(Entity.entity("", MediaType.APPLICATION_JSON)); + assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); + } + + @Test + void testRestartParticipantById() { + var invocationBuilder = super.sendRequest(PARTICIPANT_ENDPOINT + "/sync/" + + UUID.randomUUID()); + + var response = invocationBuilder.header("Content-Length", 0) + .put(Entity.entity("", MediaType.APPLICATION_JSON)); + assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); + } } diff --git a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java index 81dce9ad1..ed6097773 100644 --- a/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java +++ b/runtime-acm/src/test/java/org/onap/policy/clamp/acm/runtime/participant/ParticipantControllerTest.java @@ -277,4 +277,36 @@ class ParticipantControllerTest extends CommonRestController { assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); } } + + @Test + void testRestartParticipants() { + inputParticipants.forEach(participantProvider::saveParticipant); + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + "/sync"); + try (var response = invocationBuilder.header("Content-Length", 0) + .put(Entity.entity("", MediaType.APPLICATION_JSON))) { + assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); + } + } + + @Test + void testRestartParticipantById() { + inputParticipants.forEach(participantProvider::saveParticipant); + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + "/sync/" + + "82fd8ef9-1d1e-4343-9b28-7f9564ee3de6"); + try (var response = invocationBuilder.header("Content-Length", 0) + .put(Entity.entity("", MediaType.APPLICATION_JSON))) { + assertEquals(Response.Status.ACCEPTED.getStatusCode(), response.getStatus()); + } + } + + @Test + void testRestartParticipantFailure() { + inputParticipants.forEach(participantProvider::saveParticipant); + var invocationBuilder = super.sendRequest(PARTICIPANTS_ENDPOINT + "/sync/" + + UUID.randomUUID()); + try (var response = invocationBuilder.header("Content-Length", 0) + .put(Entity.entity("", MediaType.APPLICATION_JSON))) { + assertEquals(Response.Status.NOT_FOUND.getStatusCode(), response.getStatus()); + } + } } -- 2.16.6