Add reason for rApp instance deploy/undeploy failure
[nonrtric/plt/rappmanager.git] / rapp-manager-dme / src / main / java / com / oransc / rappmanager / dme / service / DmeDeployer.java
1 /*-
2  * ============LICENSE_START======================================================================
3  * Copyright (C) 2023 Nordix Foundation. All rights reserved.
4  * ===============================================================================================
5  * Licensed under the Apache License, Version 2.0 (the "License");
6  * you may not use this file except in compliance with the License.
7  * You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  * ============LICENSE_END========================================================================
17  */
18
19 package com.oransc.rappmanager.dme.service;
20
21 import com.fasterxml.jackson.databind.ObjectMapper;
22 import com.oransc.rappmanager.dme.data.ConsumerJob;
23 import com.oransc.rappmanager.dme.data.ProducerInfoTypeInfo;
24 import com.oransc.rappmanager.dme.data.ProducerRegistrationInfo;
25 import com.oransc.rappmanager.dme.rest.DataConsumerApiClient;
26 import com.oransc.rappmanager.dme.rest.DataProducerRegistrationApiClient;
27 import com.oransc.rappmanager.models.RappDeployer;
28 import com.oransc.rappmanager.models.csar.RappCsarConfigurationHandler;
29 import com.oransc.rappmanager.models.rapp.Rapp;
30 import com.oransc.rappmanager.models.rapp.RappEvent;
31 import com.oransc.rappmanager.models.rappinstance.RappInstance;
32 import com.oransc.rappmanager.models.statemachine.RappInstanceStateMachine;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.Map;
36 import java.util.Set;
37 import lombok.RequiredArgsConstructor;
38 import org.slf4j.Logger;
39 import org.slf4j.LoggerFactory;
40 import org.springframework.http.ResponseEntity;
41 import org.springframework.stereotype.Service;
42
43 @Service
44 @RequiredArgsConstructor
45 public class DmeDeployer implements RappDeployer {
46
47     Logger logger = LoggerFactory.getLogger(DmeDeployer.class);
48
49     private final DataProducerRegistrationApiClient dataProducerRegistrationApiClient;
50
51     private final DataConsumerApiClient dataConsumerApiClient;
52
53     private final RappCsarConfigurationHandler rappCsarConfigurationHandler;
54
55     private final ObjectMapper objectMapper;
56
57     private final RappInstanceStateMachine rappInstanceStateMachine;
58
59     @Override
60     public boolean deployRappInstance(Rapp rapp, RappInstance rappInstance) {
61         logger.debug("Deploying DME functions for RappInstance {}", rappInstance.getRappInstanceId());
62         boolean deployState = true;
63         if (rappInstance.getDme().getInfoTypesProducer() != null
64                     || rappInstance.getDme().getInfoTypeConsumer() != null) {
65             Set<String> infoTypes = new HashSet<>();
66             if (rappInstance.getDme().getInfoTypesProducer() != null) {
67                 infoTypes.addAll(rappInstance.getDme().getInfoTypesProducer());
68             }
69             if (rappInstance.getDme().getInfoTypeConsumer() != null) {
70                 infoTypes.add(rappInstance.getDme().getInfoTypeConsumer());
71             }
72             deployState = createInfoTypes(rapp, infoTypes);
73         }
74         if (rappInstance.getDme().getInfoProducer() != null) {
75             deployState = deployState && createInfoProducer(rapp, rappInstance.getDme().getInfoProducer());
76         }
77         if (rappInstance.getDme().getInfoConsumer() != null) {
78             deployState = deployState && createInfoConsumer(rapp, rappInstance.getDme().getInfoConsumer());
79         }
80         if (deployState) {
81             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEDEPLOYED);
82         } else {
83             rappInstance.setReason("Unable to deploy DME");
84             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEDEPLOYFAILED);
85         }
86         return deployState;
87     }
88
89     @Override
90     public boolean undeployRappInstance(Rapp rapp, RappInstance rappInstance) {
91         logger.debug("Undeploying DME functions for RappInstance {}", rappInstance.getRappInstanceId());
92         boolean undeployState = true;
93         if (rappInstance.getDme().getInfoConsumer() != null) {
94             undeployState = deleteInfoConsumer(rapp, rappInstance.getDme().getInfoConsumer());
95         }
96         if (rappInstance.getDme().getInfoProducer() != null) {
97             undeployState = undeployState && deleteInfoProducer(rapp, rappInstance.getDme().getInfoProducer());
98         }
99         if (undeployState) {
100             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEUNDEPLOYED);
101         } else {
102             rappInstance.setReason("Unable to undeploy DME");
103             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEUNDEPLOYFAILED);
104         }
105         return undeployState;
106     }
107
108     @Override
109     public boolean primeRapp(Rapp rapp) {
110         logger.debug("Priming DME functions for rApp {}", rapp.getRappId());
111         try {
112             Set<String> requiredInfoTypes = new HashSet<>();
113             for (String producerResourceName : rapp.getRappResources().getDme().getInfoProducers()) {
114                 String producerPayload =
115                         rappCsarConfigurationHandler.getDmeInfoProducerPayload(rapp, producerResourceName);
116                 ProducerRegistrationInfo producerRegistrationInfo =
117                         objectMapper.readValue(producerPayload, ProducerRegistrationInfo.class);
118                 requiredInfoTypes.addAll(producerRegistrationInfo.getSupportedInfoTypes());
119             }
120             for (String consumerResourceName : rapp.getRappResources().getDme().getInfoConsumers()) {
121                 String consumerPayload =
122                         rappCsarConfigurationHandler.getDmeInfoConsumerPayload(rapp, consumerResourceName);
123                 ConsumerJob consumerJob = objectMapper.readValue(consumerPayload, ConsumerJob.class);
124                 requiredInfoTypes.add(consumerJob.getInfoTypeId());
125             }
126             Set<String> allInfoTypes = new HashSet<>(rapp.getRappResources().getDme().getInfoTypes());
127             requiredInfoTypes.removeAll(allInfoTypes);
128             if (!requiredInfoTypes.isEmpty()) {
129                 allInfoTypes.addAll(dataProducerRegistrationApiClient.getInfoTypdentifiers());
130                 requiredInfoTypes.removeAll(allInfoTypes);
131                 if (!requiredInfoTypes.isEmpty()) {
132                     rapp.setReason(String.format("Invalid rapp package as the following info types cannot be found %s",
133                                     requiredInfoTypes));
134                 }
135             }
136             return true;
137         } catch (Exception e) {
138             logger.warn("Failed to prime DME", e);
139             rapp.setReason("Failed to prime DME");
140             return false;
141         }
142     }
143
144     @Override
145     public boolean deprimeRapp(Rapp rapp) {
146         logger.debug("Depriming DME functions for rApp {}", rapp.getRappId());
147         return true;
148     }
149
150     boolean createInfoTypes(Rapp rApp, Set<String> infoTypes) {
151         logger.debug("Creating DME info types {} for rApp {}", infoTypes, rApp.getRappId());
152         try {
153             Map<String, ProducerInfoTypeInfo> producerInfoTypeInfoMap = new HashMap<>();
154             for (String infoType : infoTypes) {
155                 String infoTypePayload = rappCsarConfigurationHandler.getDmeInfoTypePayload(rApp, infoType);
156                 if (infoTypePayload != null && !infoTypePayload.isEmpty()) {
157                     producerInfoTypeInfoMap.put(infoType,
158                             objectMapper.readValue(infoTypePayload, ProducerInfoTypeInfo.class));
159                 }
160             }
161             return producerInfoTypeInfoMap.entrySet().stream().map(stringProducerInfoTypeInfoEntry -> {
162                 ResponseEntity<Object> objectResponseEntity = dataProducerRegistrationApiClient.putInfoTypeWithHttpInfo(
163                         stringProducerInfoTypeInfoEntry.getKey(), stringProducerInfoTypeInfoEntry.getValue());
164                 return objectResponseEntity.getStatusCode().is2xxSuccessful();
165             }).reduce(true, (a, b) -> a && b);
166         } catch (Exception e) {
167             logger.warn("Error in creating info types {} for rApp {}", infoTypes, rApp.getRappId(), e);
168             return false;
169         }
170     }
171
172     boolean createInfoProducer(Rapp rApp, String producerResource) {
173         logger.debug("Creating DME info producer {} for rApp {}", producerResource, rApp.getRappId());
174         try {
175             String infoProducerPayload = rappCsarConfigurationHandler.getDmeInfoProducerPayload(rApp, producerResource);
176             ProducerRegistrationInfo producerRegistrationInfo =
177                     objectMapper.readValue(infoProducerPayload, ProducerRegistrationInfo.class);
178
179             ResponseEntity<Object> objectResponseEntity =
180                     dataProducerRegistrationApiClient.putInfoProducerWithHttpInfo(producerResource,
181                             producerRegistrationInfo);
182             return objectResponseEntity.getStatusCode().is2xxSuccessful();
183         } catch (Exception e) {
184             logger.warn("Error in creating info producer {} for rApp {}", producerResource, rApp.getRappId(), e);
185             return false;
186         }
187     }
188
189     boolean createInfoConsumer(Rapp rApp, String consumerResource) {
190         logger.debug("Creating DME info consumer {} for rApp {}", consumerResource, rApp.getRappId());
191         try {
192             String infoJobPayload = rappCsarConfigurationHandler.getDmeInfoConsumerPayload(rApp, consumerResource);
193             ConsumerJob consumerJob = objectMapper.readValue(infoJobPayload, ConsumerJob.class);
194             ResponseEntity<Object> objectResponseEntity =
195                     dataConsumerApiClient.putIndividualInfoJobWithHttpInfo(consumerResource, consumerJob);
196             return objectResponseEntity.getStatusCode().is2xxSuccessful();
197         } catch (Exception e) {
198             logger.warn("Error in creating info consumer {} for rApp {}", consumerResource, rApp.getRappId(), e);
199             return false;
200         }
201     }
202
203     boolean deleteInfoProducer(Rapp rApp, String producerResource) {
204         logger.debug("Deleting DME info producer {} for rApp {}", producerResource, rApp.getRappId());
205         try {
206             ResponseEntity<Object> objectResponseEntity =
207                     dataProducerRegistrationApiClient.deleteInfoProducerWithHttpInfo(producerResource);
208             return objectResponseEntity.getStatusCode().is2xxSuccessful();
209         } catch (Exception e) {
210             logger.warn("Error in deleting info producer {} for rApp {}", producerResource, rApp.getRappId(), e);
211             return false;
212         }
213     }
214
215     boolean deleteInfoConsumer(Rapp rApp, String consumerResource) {
216         logger.debug("Deleting DME info consumer {} for rApp {}", consumerResource, rApp.getRappId());
217         try {
218             ResponseEntity<Object> objectResponseEntity =
219                     dataConsumerApiClient.deleteIndividualInfoJobWithHttpInfo(consumerResource);
220             return objectResponseEntity.getStatusCode().is2xxSuccessful();
221         } catch (Exception e) {
222             logger.warn("Error in deleting info consumer {} for rApp {}", consumerResource, rApp.getRappId(), e);
223             return false;
224         }
225     }
226 }