Update release data csv file after major release
[policy/parent.git] / docs / clamp / acm / acm-participant-guide.rst
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.
4
5 .. _acm-participant-guide-label:
6
7 Participant developer guide
8 ###########################
9
10 .. contents::
11     :depth: 4
12
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.
17
18 Please refer the following section for a detailed understanding of Inbound and outbound messages a participant interacts with.
19
20 .. toctree::
21    :maxdepth: 2
22
23    design-impl/participants/participants
24
25 Design considerations for a participant
26 ---------------------------------------
27
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.
32
33 Hence the new participants has to have this Participant Intermediary module as a dependency and should:
34
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.
38
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.
41
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.
46    (**Note**: In order to avoid a connection to Kafka when Unit Tests are running, set topicCommInfrastructure: NOOP in properties file for tests).
47    The following example shows the topic parameters set for using Kafka.
48
49 .. code-block:: bash
50
51     clampAutomationCompositionTopics:
52           topicSources:
53             -
54               topic: POLICY-ACRUNTIME-PARTICIPANT
55               servers:
56                 - ${topicServer:localhost}:9092
57               topicCommInfrastructure: kafka
58               fetchTimeout: 15000
59           topicSinks:
60             -
61               topic: POLICY-ACRUNTIME-PARTICIPANT
62               servers:
63                 - ${topicServer:localhost}:9092
64               topicCommInfrastructure: kafka
65
66 4. participantSupportedElementTypes - This property takes a list of typeName and typeVersion fields to define the types of AC elements the participant deals with.
67    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.
68
69 .. code-block:: bash
70
71     participantSupportedElementTypes:
72       -
73         typeName: org.onap.policy.clamp.acm.PolicyAutomationCompositionElement
74         typeVersion: 1.0.0
75
76 Interfaces to Implement
77 -----------------------
78 AutomationCompositionElementListener:
79   Every participant should implement a handler class that implements the AutomationCompositionElementListener interface
80   from the Participant Intermediary. The intermediary listener class listens for the incoming events from the ACM-runtime
81   and invoke the handler class implementations for various operations. This class implements the methods for deploying,
82   undeploying, locking, unlocking , deleting, updating, migrating, priming, depriming requests that are coming from the ACM-runtime.
83   The methods are as follows.
84
85 .. code-block:: java
86
87   1. void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
88   2. void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
89   3. void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
90   4. void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
91   5. void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException;
92   6. void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement, InstanceElementDto instanceElementUpdated) throws PfModelException;
93   7. void prime(CompositionDto composition) throws PfModelException;
94   8. void deprime(CompositionDto composition) throws PfModelException;
95   9. void handleRestartComposition(CompositionDto composition, AcTypeState state) throws PfModelException;
96   10. void handleRestartInstance(CompositionElementDto compositionElement, InstanceElementDto instanceElement, DeployState deployState, LockState lockState) throws PfModelException;
97   11. void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget, InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate) throws PfModelException;
98
99 These method from the interface are implemented independently as per the user requirement. These methods after handling the
100 appropriate requests should also invoke the intermediary's publisher apis to notify the ACM-runtime with the acknowledgement events.
101
102 ParticipantParameters:
103   Every participant should implement a properties class that contains the values of all Intermediary parameter properties.
104   This class implements the method getIntermediaryParameters that returns 'ParticipantIntermediaryParameters' object. The method is as follows.
105
106 .. code-block:: java
107
108   ParticipantIntermediaryParameters getIntermediaryParameters()
109
110 Abstract class AcElementListenerV1
111 ----------------------------------
112 This abstract class is introduced to help to maintain the java backward compatibility with AutomationCompositionElementListener implemented in 7.1.0 version.
113 So developers can decide to align to new functionality later. Any new functionality in the future will be wrapped by this class.
114
115 The Abstract class AcElementListenerV1 supports the follow methods.
116
117 .. code-block:: java
118
119   1. void undeploy(UUID instanceId, UUID elementId) throws PfModelException;
120   2. void deploy(UUID instanceId, AcElementDeploy element, Map<String, Object> inProperties) throws PfModelException;
121   3. void lock(UUID instanceId, UUID elementId) throws PfModelException;
122   4. void unlock(UUID instanceId, UUID elementId) throws PfModelException;
123   5. void delete(UUID instanceId, UUID elementId) throws PfModelException;
124   6. void update(UUID instanceId, AcElementDeploy element, Map<String, Object> inProperties) throws PfModelException;
125   7. void prime(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList) throws PfModelException;
126   8. void deprime(UUID compositionId) throws PfModelException;
127   9. void handleRestartComposition(UUID compositionId, List<AutomationCompositionElementDefinition> elementDefinitionList, AcTypeState state) throws PfModelException;
128   10. void handleRestartInstance(UUID instanceId, AcElementDeploy element, Map<String, Object> properties, DeployState deployState, LockState lockState) throws PfModelException;
129   11. void migrate(UUID instanceId, AcElementDeploy element, UUID compositionTargetId, Map<String, Object> properties) throws PfModelException;
130
131 **Note**: this class needs intermediaryApi and it should be passed by constructor. It is declared as protected and can be used.
132 Default implementation are supported for the methods: lock, unlock, update, migrate, delete, prime, deprime, handleRestartComposition and handleRestartInstance.
133
134 Un example of AutomationCompositionElementHandler implemented in 7.1.0 version and how to use AcElementListenerV1 abstract class:
135
136 .. code-block:: java
137
138   @Component
139   @RequiredArgsConstructor
140   public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
141
142     private final ParticipantIntermediaryApi intermediaryApi;
143     private final otherService otherService;
144     ..............................
145   }
146
147   @Component
148   public class AutomationCompositionElementHandler extends AcElementListenerV1 {
149
150     private final OtherService otherService;
151
152     public AutomationCompositionElementHandler(ParticipantIntermediaryApi intermediaryApi, OtherService otherService) {
153         super(intermediaryApi);
154         this.otherService = otherService;
155     }
156     ..............................
157   }
158
159
160
161 A second example:
162
163 .. code-block:: java
164
165   @Component
166   public class AutomationCompositionElementHandler implements AutomationCompositionElementListener {
167
168     @Autowired
169     private ParticipantIntermediaryApi intermediaryApi;
170
171     @Autowired
172     private otherService otherService;
173     ..............................
174   }
175
176   @Component
177   public class AutomationCompositionElementHandler extends AcElementListenerV1 {
178
179     @Autowired
180     private otherService otherService;
181
182     public AutomationCompositionElementHandler(ParticipantIntermediaryApi intermediaryApi) {
183         super(intermediaryApi);
184     }
185     ..............................
186   }
187
188 Abstract class AcElementListenerV2
189 ----------------------------------
190 This abstract class is introduced to help to maintain the java backward compatibility with AutomationCompositionElementListener from new releases.
191 Any new functionality in the future will be wrapped by this class.
192
193 **Note**: this class needs intermediaryApi and it should be passed by constructor. It is declared as protected and can be used.
194 Default implementation are supported for the methods: lock, unlock, update, migrate, delete, prime, deprime, handleRestartComposition and handleRestartInstance.
195
196
197 Methods: deploy, undeploy, lock, unlock and delete
198   compositionElement:
199     ======================  =======================================
200      **field**                       **description**
201     ======================  =======================================
202      compositionId           composition definition Id
203      elementDefinitionId     composition definition element Id
204      inProperties            composition definition in-properties
205      outProperties           composition definition out-properties
206     ======================  =======================================
207   instanceElement:
208     ==============================  ===========================
209      **field**                       **description**
210     ==============================  ===========================
211      instanceId                      instance id
212      elementId                       instance element id
213      toscaServiceTemplateFragment    policies and policy types
214      inProperties                    instance in-properties
215       outProperties                  instance out-properties
216     ==============================  ===========================
217
218 Method: update
219   compositionElement:
220     ======================  =======================================
221      **field**                       **description**
222     ======================  =======================================
223      compositionId           composition definition Id
224      elementDefinitionId     composition definition element Id
225      inProperties            composition definition in-properties
226      outProperties           composition definition out-properties
227     ======================  =======================================
228   instanceElement:
229     ==============================  ================================================
230      **field**                       **description**
231     ==============================  ================================================
232      instanceId                      instance id
233      elementId                       instance element id
234      toscaServiceTemplateFragment
235      inProperties                    instance in-properties **(before the update)**
236       outProperties                  instance out-properties
237     ==============================  ================================================
238   instanceElementUpdated:
239     ==============================  ======================================
240      **field**                       **description**
241     ==============================  ======================================
242      instanceId                      instance id
243      elementId                       instance element id
244      toscaServiceTemplateFragment
245      inProperties                    instance in-properties **(updated)**
246       outProperties                  instance out-properties
247     ==============================  ======================================
248
249 Methods: prime, deprime
250   composition:
251     ======================  ===================================================================
252      **field**                       **description**
253     ======================  ===================================================================
254      compositionId           composition definition Id
255      inProperties            composition definition in-properties for each definition element
256      outProperties           composition definition out-properties for each definition element
257     ======================  ===================================================================
258
259 Method: migrate
260   compositionElement:
261     ======================  =======================================
262      **field**                       **description**
263     ======================  =======================================
264      compositionId           composition definition Id
265      elementDefinitionId     composition definition element Id
266      inProperties            composition definition in-properties
267      outProperties           composition definition out-properties
268     ======================  =======================================
269   compositionElementTarget:
270     ======================  ==============================================
271      **field**                       **description**
272     ======================  ==============================================
273      compositionId           composition definition target Id
274      elementDefinitionId     composition definition target element Id
275      inProperties            composition definition target in-properties
276      outProperties           composition definition target out-properties
277     ======================  ==============================================
278   instanceElement:
279     ==============================  ===================================================
280      **field**                       **description**
281     ==============================  ===================================================
282      instanceId                      instance id
283      elementId                       instance element id
284      toscaServiceTemplateFragment
285      inProperties                    instance in-properties **(before the migration)**
286       outProperties                  instance out-properties
287     ==============================  ===================================================
288   instanceElementMigrate:
289     ==============================  ======================================
290      **field**                       **description**
291     ==============================  ======================================
292      instanceId                      instance id
293      elementId                       instance element id
294      toscaServiceTemplateFragment
295      inProperties                    instance in-properties **(updated)**
296       outProperties                  instance out-properties
297     ==============================  ======================================
298
299 APIs to invoke
300 --------------
301 ParticipantIntermediaryApi:
302   The participant intermediary api has the following methods that can be invoked from the participant for the following purposes.
303
304   #. The requested operations are completed in the handler class and the ACM-runtime needs to be notified.
305   #. Collect all instances data.
306   #. Send out Properties to ACM-runtime.
307
308   The methods are as follows:
309
310 This following methods could be invoked to fetch data during each operation in the participant.
311
312 .. code-block:: java
313
314   1.  Map<UUID, AutomationComposition> getAutomationCompositions();
315   2.  AutomationComposition getAutomationComposition(UUID instanceId);
316   3.  AutomationCompositionElement getAutomationCompositionElement(UUID instanceId, UUID elementId);
317   4.  Map<UUID, Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition>> getAcElementsDefinitions();
318   5.  Map<ToscaConceptIdentifier, AutomationCompositionElementDefinition> getAcElementsDefinitions(UUID compositionId);
319   6.  AutomationCompositionElementDefinition getAcElementDefinition(UUID compositionId, ToscaConceptIdentifier elementId);
320
321 This following methods are invoked to update the outProperties during each operation in the participant.
322
323 .. code-block:: java
324
325   1.  void sendAcDefinitionInfo(UUID compositionId, ToscaConceptIdentifier elementId, Map<String, Object> outProperties);
326   2.  void sendAcElementInfo(UUID instanceId, UUID elementId, String useState, String operationalState, Map<String, Object> outProperties);
327
328 This following methods are invoked to update the AC element state or AC element definition state after each operation is completed in the participant.
329
330 .. code-block:: java
331
332   1.  void updateAutomationCompositionElementState(UUID instanceId, UUID elementId, DeployState deployState, LockState lockState, StateChangeResult stateChangeResult, String message);
333   2.  void updateCompositionState(UUID compositionId, AcTypeState state, StateChangeResult stateChangeResult, String message);
334
335 In/Out composition Properties
336 -----------------------------
337 The 'Common Properties' could be created or updated by ACM-runtime.
338 Participants will receive that Properties during priming and deprime events by CompositionDto class.
339
340 .. code-block:: java
341
342   @Override
343   public void prime(CompositionDto composition) throws PfModelException {
344       for (var entry : composition.inPropertiesMap().entrySet()) {
345           var elementDefinitionId = entry.getKey();
346           var inProperties = entry.getValue();
347           .......
348       }
349       .......
350   }
351
352 Participants will receive the Properties related to the element definition by CompositionElementDto class.
353
354 .. code-block:: java
355
356   @Override
357   public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {
358       var inCompositionProperties = compositionElement.inProperties();
359       .......
360   }
361
362 The 'Out Properties' could be created or updated by participants. ACM-runtime will receive that Properties during ParticipantStatus event.
363 The participant can trigger this event using the method sendAcDefinitionInfo.
364
365 Participants will receive that outProperties during priming and deprime events by CompositionDto class.
366
367 .. code-block:: java
368
369   @Override
370   public void deprime(CompositionDto composition) throws PfModelException {
371       for (var entry : composition.outPropertiesMap().entrySet()) {
372           var elementDefinitionId = entry.getKey();
373           var outProperties = entry.getValue();
374           .......
375       }
376       .......
377   }
378
379 Participants will receive the outProperties related to the element definition by CompositionElementDto class.
380
381 .. code-block:: java
382
383   @Override
384   public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {
385       var outCompositionProperties = compositionElement.outProperties();
386       .......
387   }
388
389 Is allowed to the participant to read all In/Out Properties of all compositions handled by the participant using the method getAcElementsDefinitions.
390 The following code is an example how to update the property 'myProperty' and send to ACM-runtime:
391
392 .. code-block:: java
393
394   var acElement = intermediaryApi.getAcElementDefinition(compositionId, elementDefinitionId);
395   var outProperties = acElement.getOutProperties();
396   outProperties.put("myProperty", myProperty);
397   intermediaryApi.sendAcDefinitionInfo(compositionId, elementDefinitionId, outProperties);
398
399 In/Out instance Properties
400 --------------------------
401   The 'In/Out Properties' are stored into the instance elements, so each element has its own In/Out Properties.
402
403   The 'In Properties' could be created or updated by ACM-runtime. Participants will receive that Properties during deploy and update events.
404
405   The 'Out Properties' could be created or updated by participants. ACM-runtime will receive that Properties during ParticipantStatus event.
406   The participant can trigger this event using the method sendAcElementInfo. The 'useState' and 'operationalState' can be used as well.
407   The 'Out Properties' could be **cleaned**:
408
409   * by the participant using the method sendAcElementInfo
410   * by intermediary automatically during deleting of the instance
411   * by an update when the instance is in UNDEPLOYED state (changing the elementId)
412
413   The 'Out Properties' will be **not cleaned** by intermediary:
414
415   * during DEPLOIYNG (Out Properties will be take from last changes matching by elementId)
416   * during UNDEPLOING
417   * during LOCKING/UNLOCKING
418   * during UPDATING/MIGRATING
419
420 Participants will receive the in/out instance Properties related to the element by InstanceElementDto class.
421
422 .. code-block:: java
423
424   @Override
425   public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement) throws PfModelException {
426       var inProperties = instanceElement.inProperties();
427       var outProperties = instanceElement.outProperties();
428       .......
429   }
430
431 Is allowed to the participant to read all In/Out Properties and state of all instances handled by the participant using the method getAutomationCompositions.
432 The following code is an example how to update the property 'myProperty' and send to ACM-runtime:
433
434 .. code-block:: java
435
436   var acElement = intermediaryApi.getAutomationCompositionElement(instanceId, elementId);
437   var outProperties = acElement.getOutProperties();
438   outProperties.put("myProperty", myProperty);
439   intermediaryApi.sendAcElementInfo(instanceId, elementId, acElement.getUseState(), acElement.getOperationalState(), outProperties);
440
441 **Note**: In update and migrate Participants will receive the instance Properties before the merge (instanceElement) and the instance Properties merged (instanceElementUpdated / instanceElementMigrate).
442
443 Restart scenario
444 ----------------
445   Restart methods handle the scenario when participant shut down and restart.
446   During RESTARTING, compositions and instances will be stored in participant memory with In/Out Properties, 'useState' and 'operationalState'.
447   The method handleRestartComposition will be called for each composition and will be present the 'state' at the time the participant shut down.
448   The method handleRestartInstance will be called for each instance element and will be present the 'deployState' and the 'lockState' at the time the participant shut down.
449
450 In ONAP, the following participants are already implemented in java spring boot for various requirements. The maven modules
451 can be referred here:
452
453   * `HTTP participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-http>`_.
454   * `Kubernetes participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-kubernetes>`_.
455   * `Policy participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-policy>`_.
456   * `A1PMS participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-a1pms>`_.
457   * `Kserve participant <https://github.com/onap/policy-clamp/tree/master/participant/participant-impl/participant-impl-kserve>`_.
458
459 Example of Implementation
460 -------------------------
461
462 This following code is an example of My First Participant:
463   * Application
464   * Parameters
465   * Handler
466
467 The Application class is configured to add the "org.onap.policy.clamp.acm.participant.intermediary" package in SpringBoot component scanning.
468
469 .. code-block:: java
470
471   @SpringBootApplication
472   @ComponentScan({
473     "org.onap.policy.clamp.acm.participant.myfirstparticipant",
474     "org.onap.policy.clamp.acm.participant.intermediary"
475   })
476   @ConfigurationPropertiesScan("org.onap.policy.clamp.acm.participant.myfirstparticipant.parameters")
477   public class MyFirstParticipantApplication {
478
479     public static void main(String[] args) {
480       SpringApplication.run(Application.class, args);
481     }
482   }
483
484 The Participant Parameters class implements the mandatory interface ParticipantParameters.
485 It could contains additional parameters.
486
487 .. code-block:: java
488
489   @Validated
490   @Getter
491   @Setter
492   @ConfigurationProperties(prefix = "participant")
493   public class ParticipantSimParameters implements ParticipantParameters {
494
495     @NotBlank
496     private String myparameter;
497
498     @NotNull
499     @Valid
500     private ParticipantIntermediaryParameters intermediaryParameters;
501   }
502
503 The following example shows the topic parameters and the additional 'myparameter'.
504
505 .. code-block:: bash
506
507   participant:
508     myparameter: my parameter
509     intermediaryParameters:
510       reportingTimeIntervalMs: 120000
511       description: Participant Description
512       participantId: 101c62b3-8918-41b9-a747-d21eb79c6c90
513       clampAutomationCompositionTopics:
514         topicSources:
515           - topic: POLICY-ACRUNTIME-PARTICIPANT
516             servers:
517               - ${topicServer:localhost}:9092
518             topicCommInfrastructure: kafka
519             fetchTimeout: 15000
520         topicSinks:
521           - topic: POLICY-ACRUNTIME-PARTICIPANT
522             servers:
523               - ${topicServer:localhost}:9092
524             topicCommInfrastructure: kafka
525       participantSupportedElementTypes:
526         -
527           typeName: org.onap.policy.clamp.acm.MyFirstAutomationCompositionElement
528           typeVersion: 1.0.0
529
530
531 The following example shows the Handler implementation and how could be the implemented the mandatory notifications.
532
533 .. code-block:: java
534
535   @Component
536   public class AutomationCompositionElementHandler extends AcElementListenerV2 {
537
538     @Override
539     public void deploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
540             throws PfModelException {
541
542         // TODO deploy process
543
544         if (isDeploySuccess()) {
545             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
546                 instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR,
547                 "Deployed");
548         } else {
549             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
550                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
551                 "Deploy failed!");
552         }
553     }
554
555     @Override
556     public void undeploy(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
557             throws PfModelException {
558
559         // TODO undeploy process
560
561         if (isUndeploySuccess()) {
562             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
563                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.NO_ERROR,
564                     "Undeployed");
565         } else {
566             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
567                 instanceElement.elementId(), DeployState.DEPLOYED, null, StateChangeResult.FAILED,
568                     "Undeploy failed!");
569         }
570     }
571
572     @Override
573     public void lock(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
574             throws PfModelException {
575
576         // TODO lock process
577
578         if (isLockSuccess()) {
579             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
580                 instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.NO_ERROR, "Locked");
581         } else {
582             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
583                 instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.FAILED, "Lock failed!");
584         }
585     }
586
587     @Override
588     public void unlock(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
589             throws PfModelException {
590
591         // TODO unlock process
592
593         if (isUnlockSuccess()) {
594             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
595                 instanceElement.elementId(), null, LockState.UNLOCKED, StateChangeResult.NO_ERROR, "Unlocked");
596         } else {
597             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
598                 instanceElement.elementId(), null, LockState.LOCKED, StateChangeResult.FAILED, "Unlock failed!");
599         }
600     }
601
602     @Override
603     public void delete(CompositionElementDto compositionElement, InstanceElementDto instanceElement)
604             throws PfModelException {
605
606         // TODO delete process
607
608         if (isDeleteSuccess()) {
609             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
610                 instanceElement.elementId(), DeployState.DELETED, null, StateChangeResult.NO_ERROR, "Deleted");
611         } else {
612             intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
613                 instanceElement.elementId(), DeployState.UNDEPLOYED, null, StateChangeResult.FAILED,
614                 "Delete failed!");
615         }
616     }
617
618     @Override
619     public void update(CompositionElementDto compositionElement, InstanceElementDto instanceElement,
620                        InstanceElementDto instanceElementUpdated) throws PfModelException {
621
622         // TODO update process
623
624         if (isUpdateSuccess()) {
625             intermediaryApi.updateAutomationCompositionElementState(
626                 instanceElement.instanceId(), instanceElement.elementId(),
627                 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Updated");
628         } else {
629             intermediaryApi.updateAutomationCompositionElementState(
630                 instanceElement.instanceId(), instanceElement.elementId(),
631                 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Update failed!");
632         }
633     }
634
635     @Override
636     public void migrate(CompositionElementDto compositionElement, CompositionElementDto compositionElementTarget,
637                         InstanceElementDto instanceElement, InstanceElementDto instanceElementMigrate)
638         throws PfModelException
639
640         // TODO migrate process
641
642         if (isMigrateSuccess()) {
643             intermediaryApi.updateAutomationCompositionElementState(
644                 instanceElement.instanceId(), instanceElement.elementId(),
645                 DeployState.DEPLOYED, null, StateChangeResult.NO_ERROR, "Migrated");
646         } else {
647             intermediaryApi.updateAutomationCompositionElementState(
648                 instanceElement.instanceId(), instanceElement.elementId(),
649                 DeployState.DEPLOYED, null, StateChangeResult.FAILED, "Migrate failed!");
650         }
651     }
652
653     @Override
654     public void prime(CompositionDto composition) throws PfModelException {
655
656         // TODO prime process
657
658         if (isPrimeSuccess()) {
659             intermediaryApi.updateCompositionState(composition.compositionId(),
660                 AcTypeState.PRIMED, StateChangeResult.NO_ERROR, "Primed");
661         } else {
662             intermediaryApi.updateCompositionState(composition.compositionId(),
663                 AcTypeState.COMMISSIONED, StateChangeResult.FAILED, "Prime failed!");
664         }
665     }
666
667     @Override
668     public void deprime(CompositionDto composition) throws PfModelException {
669
670         // TODO deprime process
671
672         if (isDeprimeSuccess()) {
673             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.COMMISSIONED,
674                 StateChangeResult.NO_ERROR, "Deprimed");
675         } else {
676             intermediaryApi.updateCompositionState(composition.compositionId(), AcTypeState.PRIMED,
677                 StateChangeResult.FAILED, "Deprime failed!");
678         }
679     }
680
681
682     @Override
683     public void handleRestartComposition(CompositionDto composition, AcTypeState state) throws PfModelException {
684
685          // TODO restart process
686
687         switch (state) {
688             case PRIMING -> prime(composition);
689             case DEPRIMING -> deprime(composition);
690             default -> intermediaryApi
691                 .updateCompositionState(composition.compositionId(), state, StateChangeResult.NO_ERROR, "Restarted");
692         }
693     }
694
695     @Override
696     public void handleRestartInstance(CompositionElementDto compositionElement, InstanceElementDto instanceElement,
697         DeployState deployState, LockState lockState) throws PfModelException {
698
699          // TODO restart process
700
701         if (DeployState.DEPLOYING.equals(deployState)) {
702             deploy(compositionElement, instanceElement);
703             return;
704         }
705         if (DeployState.UNDEPLOYING.equals(deployState)) {
706             undeploy(compositionElement, instanceElement);
707             return;
708         }
709         if (DeployState.UPDATING.equals(deployState)) {
710             update(compositionElement, instanceElement, instanceElement);
711             return;
712         }
713         if (DeployState.DELETING.equals(deployState)) {
714             delete(compositionElement, instanceElement);
715             return;
716         }
717         if (LockState.LOCKING.equals(lockState)) {
718             lock(compositionElement, instanceElement);
719             return;
720         }
721         if (LockState.UNLOCKING.equals(lockState)) {
722             unlock(compositionElement, instanceElement);
723             return;
724         }
725         intermediaryApi.updateAutomationCompositionElementState(instanceElement.instanceId(),
726             instanceElement.elementId(), deployState, lockState, StateChangeResult.NO_ERROR, "Restarted");
727     }
728
729
730 AC Element states in failure scenarios
731 --------------------------------------
732
733 During the execution of any state change order, there is always a possibility of failures or exceptions that can occur in the participant.
734 This can be tackled by the followed approaches.
735
736 The participant implementation can handle the exception and revert back the appropriate AC element state, by invoking the
737 'updateAutomationCompositionElementState' api from the participant intermediary.
738
739 Alternatively, the participant can simply throw a PfModelException from its implementation which will be handled by the participant intermediary.
740 The intermediary handles this exception and rolls back the AC element to its previous state with the appropriate stateChange Result.
741 Please refer the following table for the state change reversion that happens in the participant intermediary for the AC elements.
742
743 ================== ==================
744 **Error Scenario** **State Reverted**
745 ================== ==================
746 Prime fails        Commissoned
747
748 Deprime fails      Primed
749
750 Deploy fails       Undeployed
751
752 Undeploy fails     Deployed
753
754 Update fails       Deployed
755
756 Delete fails       Undeployed
757
758 Lock fails         Unlocked
759
760 Unlock fails       Locked
761
762 Migrate fails      Deployed
763 ================== ==================
764
765 Considering the above mentioned behavior of the participant Intermediary, it is the responsibility of the developer to tackle the
766 error scenarios in the participant with the suitable approach.
767
768 Tips:
769 If the participant tries to undeploy an element which doesn’t exist in the system any more (due to various other external factors),
770 it could update the element state to ‘undeployed’ using the Intermediary api.