Implement SOL002 specific changes to CSIT vnfm-simulator
[integration/csit.git] / plans / so / integration-etsi-testing / so-simulators / vnfm-simulator / vnfm-service / src / main / java / org / onap / so / svnfm / simulator / services / OperationProgressor.java
1 package org.onap.so.svnfm.simulator.services;
2
3 import com.google.gson.JsonObject;
4 import com.google.gson.JsonParser;
5 import java.io.BufferedReader;
6 import java.io.IOException;
7 import java.io.InputStream;
8 import java.io.InputStreamReader;
9 import java.net.URL;
10 import java.nio.charset.StandardCharsets;
11 import java.security.KeyStore;
12 import java.security.KeyStoreException;
13 import java.security.NoSuchAlgorithmException;
14 import java.security.UnrecoverableKeyException;
15 import java.security.cert.CertificateException;
16 import java.util.ArrayList;
17 import java.util.List;
18 import java.util.UUID;
19 import javax.net.ssl.HttpsURLConnection;
20 import javax.net.ssl.KeyManager;
21 import javax.net.ssl.KeyManagerFactory;
22 import javax.ws.rs.core.MediaType;
23 import org.apache.commons.codec.binary.Base64;
24 import org.modelmapper.ModelMapper;
25 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.ApiResponse;
26 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.model.GrantRequest;
27 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.model.GrantsAddResources;
28 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.model.GrantsLinks;
29 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.model.GrantsLinksVnfLcmOpOcc;
30 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.model.InlineResponse201;
31 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.ApiClient;
32 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.ApiException;
33 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.api.DefaultApi;
34 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs;
35 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs.ChangeTypeEnum;
36 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.LcnVnfLcmOperationOccurrenceNotificationLinks;
37 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance;
38 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification;
39 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification.NotificationStatusEnum;
40 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification.NotificationTypeEnum;
41 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification.OperationEnum;
42 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.lcn.model.VnfLcmOperationOccurrenceNotification.OperationStateEnum;
43 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse200;
44 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.InlineResponse201InstantiatedVnfInfoVnfcResourceInfo;
45 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.SubscriptionsAuthenticationParamsBasic;
46 import org.onap.so.adapters.vnfmadapter.extclients.vnfm.model.SubscriptionsAuthenticationParamsOauth2ClientCredentials;
47 import org.onap.so.svnfm.simulator.api.VeVnfmApi;
48 import org.onap.so.svnfm.simulator.model.Vnfds;
49 import org.onap.so.svnfm.simulator.repository.VnfOperationRepository;
50 import org.onap.so.svnfm.simulator.config.ApplicationConfig;
51 import org.onap.so.svnfm.simulator.model.VnfOperation;
52 import org.onap.so.svnfm.simulator.util.PatternContainedChecker;
53 import org.slf4j.Logger;
54 import org.slf4j.LoggerFactory;
55 import org.springframework.core.io.ClassPathResource;
56 import org.springframework.core.io.Resource;
57
58 public abstract class OperationProgressor implements Runnable {
59
60     private static final Logger LOGGER = LoggerFactory.getLogger(OperationProgressor.class);
61     private static final String CERTIFICATE_TO_TRUST = "so-vnfm-adapter.crt.pem";
62
63     private Resource keyStoreResource = new ClassPathResource("so-vnfm-simulator.p12");
64     private String keyStorePassword = "7Em3&j4.19xYiMelhD5?xbQ.";
65
66     protected final VnfOperation operation;
67     protected final SvnfmService svnfmService;
68     private final VnfOperationRepository vnfOperationRepository;
69     private final ApplicationConfig applicationConfig;
70     protected final Vnfds vnfds;
71     private final SubscriptionService subscriptionService;
72     private final DefaultApi notificationClient;
73     private final org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.api.DefaultApi grantClient;
74
75     public OperationProgressor(final VnfOperation operation, final SvnfmService svnfmService,
76             final VnfOperationRepository vnfOperationRepository, final ApplicationConfig applicationConfig,
77             final Vnfds vnfds, final SubscriptionService subscriptionService) {
78         this.operation = operation;
79         this.svnfmService = svnfmService;
80         this.vnfOperationRepository = vnfOperationRepository;
81         this.applicationConfig = applicationConfig;
82         this.vnfds = vnfds;
83         this.subscriptionService = subscriptionService;
84
85         final ApiClient apiClient = new ApiClient();
86         String callBackUrl = subscriptionService.getSubscriptions().iterator().next().getCallbackUri();
87         final PatternContainedChecker checker = new PatternContainedChecker("/lcn/", callBackUrl);
88         callBackUrl = checker.getText();
89         apiClient.setBasePath(callBackUrl);
90         apiClient.setKeyManagers(getKeyManagers());
91         apiClient.setSslCaCert(getCertificateToTrust());
92         notificationClient = checker.isContained() ? new DefaultApi(apiClient) : new VeVnfmApi(apiClient);
93
94         final org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.ApiClient grantApiClient =
95                 new org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.ApiClient();
96         grantApiClient.setBasePath(callBackUrl);
97         grantApiClient.setKeyManagers(getKeyManagers());
98         grantApiClient.setSslCaCert(getCertificateToTrust());
99         grantClient = new org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.api.DefaultApi(grantApiClient);
100     }
101
102     private InputStream getCertificateToTrust() {
103         try {
104             return new ClassPathResource(CERTIFICATE_TO_TRUST).getInputStream();
105         } catch (final IOException exception) {
106             LOGGER.error("Error reading certificate to trust, https calls to VNFM adapter will fail", exception);
107             return null;
108         }
109     }
110
111     private KeyManager[] getKeyManagers() {
112         KeyStore keystore;
113         try {
114             keystore = KeyStore.getInstance("pkcs12");
115             keystore.load(keyStoreResource.getInputStream(), keyStorePassword.toCharArray());
116             KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("SunX509");
117             keyManagerFactory.init(keystore, keyStorePassword.toCharArray());
118             return keyManagerFactory.getKeyManagers();
119         } catch (KeyStoreException | NoSuchAlgorithmException | CertificateException | IOException
120                 | UnrecoverableKeyException exception) {
121             LOGGER.error("Error reading certificate, https calls using two way TLS to VNFM adapter will fail",
122                     exception);
123             return new KeyManager[0];
124         }
125     }
126
127     @Override
128     public void run() {
129         try {
130             final VnfLcmOperationOccurrenceNotification notificationOfStarting =
131                     buildNotification(NotificationStatusEnum.START, OperationStateEnum.STARTING);
132             sendNotification(notificationOfStarting);
133
134             sleep(2000);
135             setState(InlineResponse200.OperationStateEnum.PROCESSING);
136             final VnfLcmOperationOccurrenceNotification notificationOfProcessing =
137                     buildNotification(NotificationStatusEnum.START, OperationStateEnum.PROCESSING);
138             sendNotification(notificationOfProcessing);
139
140
141             final GrantRequest grantRequest = buildGrantRequest();
142             final InlineResponse201 grantResponse = sendGrantRequest(grantRequest);
143             final List<InlineResponse201InstantiatedVnfInfoVnfcResourceInfo> vnfcs = handleGrantResponse(grantResponse);
144
145             svnfmService.getVnf(operation.getVnfInstanceId()).getInstantiatedVnfInfo();
146
147             sleep(10000);
148             setState(InlineResponse200.OperationStateEnum.COMPLETED);
149             final VnfLcmOperationOccurrenceNotification notificationOfCompleted =
150                     buildNotification(NotificationStatusEnum.RESULT, OperationStateEnum.COMPLETED);
151             notificationOfCompleted.setAffectedVnfcs(getVnfcs(vnfcs));
152
153             sendNotification(notificationOfCompleted);
154         } catch (final Exception exception) {
155             LOGGER.error("Error in OperationProgressor ", exception);
156         }
157
158     }
159
160     private void sleep(final long milliSeconds) {
161         try {
162             Thread.sleep(milliSeconds);
163         } catch (final InterruptedException e) {
164             operation.setOperationState(InlineResponse200.OperationStateEnum.FAILED);
165             // Restore interrupted state
166             Thread.currentThread().interrupt();
167         }
168     }
169
170     private void setState(final InlineResponse200.OperationStateEnum state) {
171         LOGGER.info("Setting state to {} for operation {}", state, operation.getId());
172         operation.setOperationState(state);
173         vnfOperationRepository.save(operation);
174     }
175
176     private VnfLcmOperationOccurrenceNotification buildNotification(final NotificationStatusEnum status,
177             final OperationStateEnum operationState) {
178         final VnfLcmOperationOccurrenceNotification notification = new VnfLcmOperationOccurrenceNotification();
179         notification.setId(UUID.randomUUID().toString());
180         notification.setNotificationType(NotificationTypeEnum.VNFLCMOPERATIONOCCURRENCENOTIFICATION);
181         notification.setNotificationStatus(status);
182         notification.setOperationState(operationState);
183         notification.setOperation(OperationEnum.fromValue(operation.getOperation().toString()));
184         notification.setVnfInstanceId(operation.getVnfInstanceId());
185         notification.setVnfLcmOpOccId(operation.getId());
186
187         final LcnVnfLcmOperationOccurrenceNotificationLinks links = new LcnVnfLcmOperationOccurrenceNotificationLinks();
188         final LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance vnfInstanceLink =
189                 new LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance();
190         vnfInstanceLink.setHref(getVnfLink());
191         links.setVnfInstance(vnfInstanceLink);
192
193
194         final LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance operationLink =
195                 new LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance();
196         operationLink.setHref(getOperationLink());
197         links.setVnfLcmOpOcc(operationLink);
198
199         notification.setLinks(links);
200
201         return notification;
202     }
203
204     private List<LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs> getVnfcs(
205             final List<InlineResponse201InstantiatedVnfInfoVnfcResourceInfo> instantiatedVnfcs) {
206         final List<LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs> vnfcs = new ArrayList<>();
207         if (instantiatedVnfcs != null) {
208             for (final InlineResponse201InstantiatedVnfInfoVnfcResourceInfo instantiatedVnfc : instantiatedVnfcs) {
209                 LOGGER.info("VNFC TO BE CONVERTED: {}", instantiatedVnfc);
210                 final ModelMapper mapper = new ModelMapper();
211                 final LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs vnfc =
212                         mapper.map(instantiatedVnfc, LcnVnfLcmOperationOccurrenceNotificationAffectedVnfcs.class);
213                 LOGGER.info("VNFC FROM CONVERSION: {}", vnfc);
214                 vnfc.setChangeType(getVnfcChangeType());
215                 vnfcs.add(vnfc);
216             }
217         }
218         return vnfcs;
219     }
220
221     private void sendNotification(final VnfLcmOperationOccurrenceNotification notification) {
222         LOGGER.info("Sending notification: {}", notification);
223         try {
224             final SubscriptionsAuthenticationParamsBasic subscriptionAuthentication =
225                     subscriptionService.getSubscriptions().iterator().next().getAuthentication().getParamsBasic();
226             final String auth =
227                     subscriptionAuthentication.getUserName() + ":" + subscriptionAuthentication.getPassword();
228             final byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1));
229             String authHeader = "Basic " + new String(encodedAuth);
230
231             notificationClient.lcnVnfLcmOperationOccurrenceNotificationPostWithHttpInfo(notification,
232                     MediaType.APPLICATION_JSON, authHeader);
233         } catch (final ApiException exception) {
234             LOGGER.error("Error sending notification: " + notification, exception);
235             LOGGER.error("Response code: {}, body: {}, basePath: {}", exception.getCode(), exception.getResponseBody(),
236                     notificationClient.getApiClient().getBasePath());
237
238         }
239     }
240
241
242     public GrantRequest buildGrantRequest() {
243         final GrantRequest grantRequest = new GrantRequest();
244         grantRequest.setVnfInstanceId(operation.getVnfInstanceId());
245         final String vnfdId = svnfmService.getVnf(operation.getVnfInstanceId()).getVnfdId();
246         grantRequest.setVnfdId(vnfdId);
247         grantRequest.setAddResources(getAddResources(vnfdId));
248         grantRequest.setRemoveResources(getRemoveResources(vnfdId));
249         grantRequest.setVnfLcmOpOccId(operation.getId());
250         grantRequest
251                 .setOperation(org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.model.GrantRequest.OperationEnum
252                         .fromValue(operation.getOperation().getValue()));
253         grantRequest.setIsAutomaticInvocation(false);
254
255         final GrantsLinksVnfLcmOpOcc vnfInstanceLink = new GrantsLinksVnfLcmOpOcc();
256         vnfInstanceLink.setHref(getVnfLink());
257         final GrantsLinksVnfLcmOpOcc operationInstanceLink = new GrantsLinksVnfLcmOpOcc();
258         operationInstanceLink.setHref(getOperationLink());
259         final GrantsLinks links = new GrantsLinks();
260         links.setVnfInstance(vnfInstanceLink);
261         links.setVnfLcmOpOcc(operationInstanceLink);
262         grantRequest.setLinks(links);
263         return grantRequest;
264     }
265
266     protected abstract List<GrantsAddResources> getAddResources(final String vnfdId);
267
268     protected abstract List<GrantsAddResources> getRemoveResources(final String vnfdId);
269
270     protected abstract List<InlineResponse201InstantiatedVnfInfoVnfcResourceInfo> handleGrantResponse(
271             InlineResponse201 grantResponse);
272
273     protected abstract ChangeTypeEnum getVnfcChangeType();
274
275     private InlineResponse201 sendGrantRequest(final GrantRequest grantRequest) {
276         LOGGER.info("Sending grant request: {}", grantRequest);
277         try {
278
279             final SubscriptionsAuthenticationParamsOauth2ClientCredentials subscriptionAuthentication =
280                     subscriptionService.getSubscriptions().iterator().next().getAuthentication()
281                             .getParamsOauth2ClientCredentials();
282
283             final String authHeader = applicationConfig.getGrantAuth().equals("oauth")
284                     ? "Bearer " + getToken(notificationClient.getApiClient(), subscriptionAuthentication)
285                     : null;
286
287             final ApiResponse<InlineResponse201> response = grantClient.grantsPostWithHttpInfo(grantRequest,
288                     MediaType.APPLICATION_JSON, MediaType.APPLICATION_JSON, authHeader);
289             LOGGER.info("Grant Response: {}", response);
290             return response.getData();
291         } catch (final org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.ApiException exception) {
292             LOGGER.error("Error sending notification: " + grantRequest, exception);
293             return null;
294         }
295     }
296
297     private String getVnfLink() {
298         return getLinkBaseUrl() + "/vnf_instances/" + operation.getVnfInstanceId();
299     }
300
301     private String getOperationLink() {
302         return getLinkBaseUrl() + "/vnf_lcm_op_occs/" + operation.getId();
303     }
304
305     private String getLinkBaseUrl() {
306         return applicationConfig.getBaseUrl() + "/vnflcm/v1";
307     }
308
309     private String getToken(final ApiClient apiClient,
310             final SubscriptionsAuthenticationParamsOauth2ClientCredentials oauthClientCredentials) {
311         final String basePath = apiClient.getBasePath().substring(0, apiClient.getBasePath().indexOf("/so/"));
312         final String tokenUrl = basePath + "/oauth/token?grant_type=client_credentials";
313
314         try {
315             URL url = new URL(tokenUrl);
316             HttpsURLConnection connection = (HttpsURLConnection) url.openConnection();
317             connection.setRequestMethod("POST");
318             final String authorizationHeader = getAuthorizationHeader(oauthClientCredentials);
319             connection.addRequestProperty("Authorization", authorizationHeader);
320
321             connection.connect();
322
323             return getResponse(connection).get("access_token").getAsString();
324
325         } catch (IOException exception) {
326             LOGGER.error("Error getting token", exception);
327             return null;
328         }
329     }
330
331     private String getAuthorizationHeader(
332             final SubscriptionsAuthenticationParamsOauth2ClientCredentials oauthClientCredentials) {
333         final String auth = oauthClientCredentials.getClientId() + ":" + oauthClientCredentials.getClientPassword();
334         final byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.UTF_8));
335         return "Basic " + new String(encodedAuth);
336     }
337
338     private JsonObject getResponse(HttpsURLConnection connection) throws IOException {
339         BufferedReader in = new BufferedReader(new InputStreamReader(connection.getInputStream()));
340         String line, data = "";
341         while ((line = in.readLine()) != null) {
342             data += line;
343         }
344         in.close();
345         connection.getInputStream().close();
346
347         JsonObject jsonObject = new JsonParser().parse(data).getAsJsonObject();
348         return jsonObject;
349     }
350
351 }