Add info types for producer and consumer in rApp package
[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 java.util.function.BiFunction;
38 import lombok.RequiredArgsConstructor;
39 import org.slf4j.Logger;
40 import org.slf4j.LoggerFactory;
41 import org.springframework.http.ResponseEntity;
42 import org.springframework.stereotype.Service;
43
44 @Service
45 @RequiredArgsConstructor
46 public class DmeDeployer implements RappDeployer {
47
48     Logger logger = LoggerFactory.getLogger(DmeDeployer.class);
49
50     private final DataProducerRegistrationApiClient dataProducerRegistrationApiClient;
51
52     private final DataConsumerApiClient dataConsumerApiClient;
53
54     private final RappCsarConfigurationHandler rappCsarConfigurationHandler;
55
56     private final ObjectMapper objectMapper;
57
58     private final RappInstanceStateMachine rappInstanceStateMachine;
59
60     @Override
61     public boolean deployRappInstance(Rapp rapp, RappInstance rappInstance) {
62         logger.debug("Deploying DME functions for RappInstance {}", rappInstance.getRappInstanceId());
63         boolean deployState = true;
64         if (rappInstance.getDme().getInfoTypesProducer() != null) {
65             deployState = createProducerInfoTypes(rapp, rappInstance.getDme().getInfoTypesProducer());
66         }
67         if (rappInstance.getDme().getInfoTypeConsumer() != null) {
68             deployState =
69                     deployState && createConsumerInfoTypes(rapp, Set.of(rappInstance.getDme().getInfoTypeConsumer()));
70         }
71         if (rappInstance.getDme().getInfoProducer() != null) {
72             deployState = deployState && createInfoProducer(rapp, rappInstance.getDme().getInfoProducer());
73         }
74         if (rappInstance.getDme().getInfoConsumer() != null) {
75             deployState = deployState && createInfoConsumer(rapp, rappInstance.getDme().getInfoConsumer());
76         }
77         if (deployState) {
78             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEDEPLOYED);
79         } else {
80             rappInstance.setReason("Unable to deploy DME");
81             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEDEPLOYFAILED);
82         }
83         return deployState;
84     }
85
86     @Override
87     public boolean undeployRappInstance(Rapp rapp, RappInstance rappInstance) {
88         logger.debug("Undeploying DME functions for RappInstance {}", rappInstance.getRappInstanceId());
89         boolean undeployState = true;
90         if (rappInstance.getDme().getInfoConsumer() != null) {
91             undeployState = deleteInfoConsumer(rapp, rappInstance.getDme().getInfoConsumer());
92         }
93         if (rappInstance.getDme().getInfoProducer() != null) {
94             undeployState = undeployState && deleteInfoProducer(rapp, rappInstance.getDme().getInfoProducer());
95         }
96         if (undeployState) {
97             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEUNDEPLOYED);
98         } else {
99             rappInstance.setReason("Unable to undeploy DME");
100             rappInstanceStateMachine.sendRappInstanceEvent(rappInstance, RappEvent.DMEUNDEPLOYFAILED);
101         }
102         return undeployState;
103     }
104
105     @Override
106     public boolean primeRapp(Rapp rapp) {
107         logger.debug("Priming DME functions for rApp {}", rapp.getRappId());
108         try {
109             Set<String> requiredInfoTypes = new HashSet<>();
110             for (String producerResourceName : rapp.getRappResources().getDme().getInfoProducers()) {
111                 String producerPayload =
112                         rappCsarConfigurationHandler.getDmeInfoProducerPayload(rapp, producerResourceName);
113                 ProducerRegistrationInfo producerRegistrationInfo =
114                         objectMapper.readValue(producerPayload, ProducerRegistrationInfo.class);
115                 requiredInfoTypes.addAll(producerRegistrationInfo.getSupportedInfoTypes());
116             }
117             for (String consumerResourceName : rapp.getRappResources().getDme().getInfoConsumers()) {
118                 String consumerPayload =
119                         rappCsarConfigurationHandler.getDmeInfoConsumerPayload(rapp, consumerResourceName);
120                 ConsumerJob consumerJob = objectMapper.readValue(consumerPayload, ConsumerJob.class);
121                 requiredInfoTypes.add(consumerJob.getInfoTypeId());
122             }
123             Set<String> allInfoTypes = new HashSet<>(rapp.getRappResources().getDme().getProducerInfoTypes());
124             allInfoTypes.addAll(rapp.getRappResources().getDme().getConsumerInfoTypes());
125             requiredInfoTypes.removeAll(allInfoTypes);
126             if (!requiredInfoTypes.isEmpty()) {
127                 allInfoTypes.addAll(dataProducerRegistrationApiClient.getInfoTypdentifiers());
128                 requiredInfoTypes.removeAll(allInfoTypes);
129                 if (!requiredInfoTypes.isEmpty()) {
130                     rapp.setReason(String.format("Invalid rapp package as the following info types cannot be found %s",
131                             requiredInfoTypes));
132                 }
133             }
134             return true;
135         } catch (Exception e) {
136             logger.warn("Failed to prime DME", e);
137             rapp.setReason("Failed to prime DME");
138             return false;
139         }
140     }
141
142     @Override
143     public boolean deprimeRapp(Rapp rapp) {
144         logger.debug("Depriming DME functions for rApp {}", rapp.getRappId());
145         return true;
146     }
147
148     boolean createProducerInfoTypes(Rapp rApp, Set<String> infoTypes) {
149         logger.debug("Creating DME producer info types {} for rApp {}", infoTypes, rApp.getRappId());
150         return createInfoTypes(rApp, infoTypes, rappCsarConfigurationHandler::getDmeProducerInfoTypePayload);
151     }
152
153     boolean createConsumerInfoTypes(Rapp rApp, Set<String> infoTypes) {
154         logger.debug("Creating DME consumer info types {} for rApp {}", infoTypes, rApp.getRappId());
155         return createInfoTypes(rApp, infoTypes, rappCsarConfigurationHandler::getDmeConsumerInfoTypePayload);
156     }
157
158     boolean createInfoTypes(Rapp rApp, Set<String> infoTypes, BiFunction<Rapp, String, String> payloadReader) {
159         try {
160             Map<String, ProducerInfoTypeInfo> producerInfoTypeInfoMap = new HashMap<>();
161             for (String infoType : infoTypes) {
162                 String infoTypePayload = payloadReader.apply(rApp, infoType);
163                 if (infoTypePayload != null && !infoTypePayload.isEmpty()) {
164                     producerInfoTypeInfoMap.put(infoType,
165                             objectMapper.readValue(infoTypePayload, ProducerInfoTypeInfo.class));
166                 }
167             }
168             return producerInfoTypeInfoMap.entrySet().stream().map(stringProducerInfoTypeInfoEntry -> {
169                 ResponseEntity<Object> objectResponseEntity = dataProducerRegistrationApiClient.putInfoTypeWithHttpInfo(
170                         stringProducerInfoTypeInfoEntry.getKey(), stringProducerInfoTypeInfoEntry.getValue());
171                 return objectResponseEntity.getStatusCode().is2xxSuccessful();
172             }).reduce(true, (a, b) -> a && b);
173         } catch (Exception e) {
174             logger.warn("Error in creating info types {} for rApp {}", infoTypes, rApp.getRappId(), e);
175             return false;
176         }
177     }
178
179     boolean createInfoProducer(Rapp rApp, String producerResource) {
180         logger.debug("Creating DME info producer {} for rApp {}", producerResource, rApp.getRappId());
181         try {
182             String infoProducerPayload = rappCsarConfigurationHandler.getDmeInfoProducerPayload(rApp, producerResource);
183             ProducerRegistrationInfo producerRegistrationInfo =
184                     objectMapper.readValue(infoProducerPayload, ProducerRegistrationInfo.class);
185
186             ResponseEntity<Object> objectResponseEntity =
187                     dataProducerRegistrationApiClient.putInfoProducerWithHttpInfo(producerResource,
188                             producerRegistrationInfo);
189             return objectResponseEntity.getStatusCode().is2xxSuccessful();
190         } catch (Exception e) {
191             logger.warn("Error in creating info producer {} for rApp {}", producerResource, rApp.getRappId(), e);
192             return false;
193         }
194     }
195
196     boolean createInfoConsumer(Rapp rApp, String consumerResource) {
197         logger.debug("Creating DME info consumer {} for rApp {}", consumerResource, rApp.getRappId());
198         try {
199             String infoJobPayload = rappCsarConfigurationHandler.getDmeInfoConsumerPayload(rApp, consumerResource);
200             ConsumerJob consumerJob = objectMapper.readValue(infoJobPayload, ConsumerJob.class);
201             ResponseEntity<Object> objectResponseEntity =
202                     dataConsumerApiClient.putIndividualInfoJobWithHttpInfo(consumerResource, consumerJob);
203             return objectResponseEntity.getStatusCode().is2xxSuccessful();
204         } catch (Exception e) {
205             logger.warn("Error in creating info consumer {} for rApp {}", consumerResource, rApp.getRappId(), e);
206             return false;
207         }
208     }
209
210     boolean deleteInfoProducer(Rapp rApp, String producerResource) {
211         logger.debug("Deleting DME info producer {} for rApp {}", producerResource, rApp.getRappId());
212         try {
213             ResponseEntity<Object> objectResponseEntity =
214                     dataProducerRegistrationApiClient.deleteInfoProducerWithHttpInfo(producerResource);
215             return objectResponseEntity.getStatusCode().is2xxSuccessful();
216         } catch (Exception e) {
217             logger.warn("Error in deleting info producer {} for rApp {}", producerResource, rApp.getRappId(), e);
218             return false;
219         }
220     }
221
222     boolean deleteInfoConsumer(Rapp rApp, String consumerResource) {
223         logger.debug("Deleting DME info consumer {} for rApp {}", consumerResource, rApp.getRappId());
224         try {
225             ResponseEntity<Object> objectResponseEntity =
226                     dataConsumerApiClient.deleteIndividualInfoJobWithHttpInfo(consumerResource);
227             return objectResponseEntity.getStatusCode().is2xxSuccessful();
228         } catch (Exception e) {
229             logger.warn("Error in deleting info consumer {} for rApp {}", consumerResource, rApp.getRappId(), e);
230             return false;
231         }
232     }
233 }