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