1 .. This work is licensed under a Creative Commons Attribution 4.0 International License.
2 .. http://creativecommons.org/licenses/by/4.0
3 .. Copyright (c) Nordix Foundation. All rights reserved.
5 .. _acm-participant-guide-label:
7 Participant developer guide
8 ###########################
13 The ACM runtime delegates the user requests to the participants for performing the actual operations.
14 Hence the participant module in ACM is implemented adhering to a list of ACM protocols along with their own functional logic.
15 It works in a contract with the Participant Intermediary module for communicating with ACM-R.
16 This guide explains the design considerations for a new participant implementation in ACM.
18 Please refer the following section for a detailed understanding of Inbound and outbound messages a participant interacts with.
23 design-impl/participants/participants
25 Design considerations for a participant
26 ---------------------------------------
28 In ONAP, the ACM-runtime and participant modules are implemented in Java spring boot. The participant Intermediary module
29 which is added as a maven dependency to the participants has the default implementations available for listening the kafka
30 events coming in from the ACM-runtime, process them and delegate them to the appropriate handler class. Similarly the
31 Intermediary module also has the publisher class implementations for publishing events back from the participants to the ACM-runtime.
33 Hence the new participants has to have this Participant Intermediary module as a dependency and should:
35 * Configure SpringBoot to scan the components located into the package "org.onap.policy.clamp.acm.participant.intermediary".
36 * Implement the following interfaces from the Participant Intermediary.
37 * Provide the following mandatory properties in order to make the participant work in synchronisation with ACM-runtime.
39 The participant application should be provided with the following Intermediary parameter values in the application properties
40 and the same is configured for the 'ParticipantIntermediaryParameters' object in the code.
42 1. participantId - A unique participant UUID that is used by the runtime to identify the participant.
43 2. ReportingTimeIntervalMs - Time inertval the participant should report the status/heartbeat to the runtime.
44 3. clampAutomationCompositionTopics - This property takes in the kafka topic names and servers for the intermediary module to use.
45 These values should be provided for both source and sink configs. The following example shows the topic parameters set for using DMaap.
49 clampAutomationCompositionTopics:
52 topic: POLICY-ACRUNTIME-PARTICIPANT
54 - ${topicServer:localhost}
55 topicCommInfrastructure: dmaap
59 topic: POLICY-ACRUNTIME-PARTICIPANT
61 - ${topicServer:localhost}
62 topicCommInfrastructure: dmaap
64 4. participantSupportedElementTypes - This property takes a list of typeName and typeVersion fields to define the types of AC elements the participant deals with.
65 These are user defined name and version and the same should be defined for the AC elements that are included in the TOSCA based AC definitions.
69 participantSupportedElementTypes:
71 typeName: org.onap.policy.clamp.acm.PolicyAutomationCompositionElement
74 Interfaces to Implement
75 -----------------------
76 AutomationCompositionElementListener:
77 Every participant should implement a handler class that implements the AutomationCompositionElementListener interface
78 from the Participant Intermediary. The intermediary listener class listens for the incoming events from the ACM-runtime
79 and invoke the handler class implementations for various operations. This class implements the methods for deploying,
80 undeploying, locking, unlocking , deleting, updating, priming, depriming requests that are coming from the ACM-runtime.
81 The methods are as follows.
85 1. void undeploy(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException;
86 2. void deploy(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> inProperties) throws PfModelException;
87 3. void lock(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException;
88 4. void unlock(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException;
89 5. void delete(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException;
90 6. void update(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> inProperties) throws PfModelException;
91 7. void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList) throws PfModelException;
92 8. void deprime(UUID compositionId) throws PfModelException;
94 These method from the interface are implemented independently as per the user requirement. These methods after handling the
95 appropriate requests should also invoke the intermediary's publisher apis to notify the ACM-runtime with the acknowledgement events.
97 ParticipantParameters:
98 Every participant should implement a properties class that contains the values of all Intermediary parameter properties.
99 This class implements the method getIntermediaryParameters that returns 'ParticipantIntermediaryParameters' object. The method is as follows.
103 ParticipantIntermediaryParameters getIntermediaryParameters()
108 ParticipantIntermediaryApi:
109 The participant intermediary api has the following methods that can be invoked from the participant for the following purposes.
111 #. The requested operations are completed in the handler class and the ACM-runtime needs to be notified.
112 #. Collect all instances data.
113 #. Send out Properties to ACM-runtime.
115 The methods are as follows:
117 This following method is invoked to update the AC element state after each operation is completed in the participant.
121 1. void updateAutomationCompositionElementState(UUID automationCompositionId, UUID elementId, DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message);
122 2. Map<UUID, AutomationComposition> getAutomationCompositions();
123 3. void sendAcElementInfo(UUID automationCompositionId, UUID elementId, String useState, String operationalState, Map<String, Object> outProperties);
124 4. void updateCompositionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult, String message);
128 The 'In Properties' could be created or updated by ACM-runtime. Participants will receive that Properties during deploy and update events.
130 The 'Out Properties' could be created or updated by participants. ACM-runtime will receive that Properties during ParticipantStatus event.
131 The participant can trigger this event using the method sendAcElementInfo.
132 The 'useState' and 'operationalState' can be used as well.
134 Is allowed to the participant to read all In/Out Properties and state of all instances handled by the participant using the method getAutomationCompositions.
135 The following code is an example how to update the property 'myProperty' and send to ACM-runtime:
139 var automationCompositions = intermediaryApi.getAutomationCompositions();
140 var automationComposition = automationCompositions.get(automationCompositionId);
141 var acElement = automationComposition.getElements().get(elementId);
142 var outProperties = acElement.getOutProperties();
143 outProperties.put("myProperty", myProperty);
144 intermediaryApi.sendAcElementInfo(automationCompositionId, elementId, acElement.getUseState(), acElement.getOperationalState(), outProperties);
148 In ONAP, the following participants are already implemented in java spring boot for various requirements. The maven modules
149 can be referred here:
151 * `HTTP participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-http>`_.
152 * `Kubernetes participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-kubernetes>`_.
153 * `Policy participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-policy>`_.
154 * `A1PMS participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-a1pms>`_.
155 * `Kserve participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-kserve>`_.
157 Example of Implementation
158 -------------------------
160 This following code is an example of My First Participant:
165 The Application class is configured to add the "org.onap.policy.clamp.acm.participant.intermediary" package in SpringBoot component scanning.
169 @SpringBootApplication
171 "org.onap.policy.clamp.acm.participant.myfirstparticipant",
172 "org.onap.policy.clamp.acm.participant.intermediary"
174 @ConfigurationPropertiesScan("org.onap.policy.clamp.acm.participant.myfirstparticipant.parameters")
175 public class MyFirstParticipantApplication {
177 public static void main(String[] args) {
178 SpringApplication.run(Application.class, args);
182 The Participant Parameters class implements the mandatory interface ParticipantParameters.
183 It could contains additional parameters.
190 @ConfigurationProperties(prefix = "participant")
191 public class ParticipantSimParameters implements ParticipantParameters {
194 private String myparameter;
198 private ParticipantIntermediaryParameters intermediaryParameters;
201 The following example shows the topic parameters and the additional 'myparameter'.
206 myparameter: my parameter
207 intermediaryParameters:
208 reportingTimeIntervalMs: 120000
209 description: Participant Description
210 participantId: 101c62b3-8918-41b9-a747-d21eb79c6c90
211 clampAutomationCompositionTopics:
213 - topic: POLICY-ACRUNTIME-PARTICIPANT
215 - ${topicServer:localhost}
216 topicCommInfrastructure: dmaap
219 - topic: POLICY-ACRUNTIME-PARTICIPANT
221 - ${topicServer:localhost}
222 topicCommInfrastructure: dmaap
223 participantSupportedElementTypes:
225 typeName: org.onap.policy.clamp.acm.MyFirstAutomationCompositionElement
229 The following example shows the Handler implementation and how could be the implemented the mandatory notifications.
234 @RequiredArgsConstructor
235 public class MyFirstAcElementHandler implements AutomationCompositionElementListener {
237 private final ParticipantIntermediaryApi intermediaryApi;
240 public void deploy(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> properties)
241 throws PfModelException {
243 // TODO deploy process
245 if (isDeploySuccess()) {
246 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
247 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Deployed");
249 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
250 DeployState.UNDEPLOYED, null, StateChangeResult.FAILED, "Deploy failed!");
255 public void undeploy(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
256 LOGGER.debug("undeploy call");
258 // TODO undeploy process
260 if (isUndeploySuccess()) {
261 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
262 automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR,
265 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
266 automationCompositionElementId, DeployState.DEPLOYED, null, StateChangeResult.FAILED,
272 public void lock(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
276 if (isLockSuccess()) {
277 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
278 automationCompositionElementId, null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
280 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
281 automationCompositionElementId, null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!");
286 public void unlock(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
288 // TODO unlock process
290 if (isUnlockSuccess()) {
291 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
292 automationCompositionElementId, null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
294 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
295 automationCompositionElementId, null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!");
300 public void delete(UUID automationCompositionId, UUID automationCompositionElementId) throws PfModelException {
302 // TODO delete process
304 if (isDeleteSuccess()) {
305 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
306 automationCompositionElementId, DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
308 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId,
309 automationCompositionElementId, DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
315 public void update(UUID automationCompositionId, AcElementDeploy element, Map<String, Object> properties)
316 throws PfModelException {
318 // TODO update process
320 if (isUpdateSuccess()) {
321 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
322 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated");
324 intermediaryApi.updateAutomationCompositionElementState(automationCompositionId, element.getId(),
325 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!");
330 public void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList)
331 throws PfModelException {
333 // TODO prime process
335 if (isPrimeSuccess()) {
336 intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.NO_ERROR,
339 intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.FAILED,
345 public void deprime(UUID compositionId) throws PfModelException {
347 // TODO deprime process
349 if (isDeprimeSuccess()) {
350 intermediaryApi.updateCompositionState(compositionId, AcTypeState.COMMISSIONED, StateChangeResult.NO_ERROR,
353 intermediaryApi.updateCompositionState(compositionId, AcTypeState.PRIMED, StateChangeResult.FAILED,