1 package org.onap.so.svnfm.simulator.services;
 
   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;
 
  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;
 
  58 public abstract class OperationProgressor implements Runnable {
 
  60     private static final Logger LOGGER = LoggerFactory.getLogger(OperationProgressor.class);
 
  61     private static final String CERTIFICATE_TO_TRUST = "so-vnfm-adapter.crt.pem";
 
  63     private Resource keyStoreResource = new ClassPathResource("so-vnfm-simulator.p12");
 
  64     private String keyStorePassword = "7Em3&j4.19xYiMelhD5?xbQ.";
 
  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;
 
  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;
 
  83         this.subscriptionService = subscriptionService;
 
  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);
 
  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);
 
 102     private InputStream getCertificateToTrust() {
 
 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);
 
 111     private KeyManager[] getKeyManagers() {
 
 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",
 
 123             return new KeyManager[0];
 
 130             final VnfLcmOperationOccurrenceNotification notificationOfStarting =
 
 131                     buildNotification(NotificationStatusEnum.START, OperationStateEnum.STARTING);
 
 132             sendNotification(notificationOfStarting);
 
 135             setState(InlineResponse200.OperationStateEnum.PROCESSING);
 
 136             final VnfLcmOperationOccurrenceNotification notificationOfProcessing =
 
 137                     buildNotification(NotificationStatusEnum.START, OperationStateEnum.PROCESSING);
 
 138             sendNotification(notificationOfProcessing);
 
 141             final GrantRequest grantRequest = buildGrantRequest();
 
 142             final InlineResponse201 grantResponse = sendGrantRequest(grantRequest);
 
 143             final List<InlineResponse201InstantiatedVnfInfoVnfcResourceInfo> vnfcs = handleGrantResponse(grantResponse);
 
 145             svnfmService.getVnf(operation.getVnfInstanceId()).getInstantiatedVnfInfo();
 
 148             setState(InlineResponse200.OperationStateEnum.COMPLETED);
 
 149             final VnfLcmOperationOccurrenceNotification notificationOfCompleted =
 
 150                     buildNotification(NotificationStatusEnum.RESULT, OperationStateEnum.COMPLETED);
 
 151             notificationOfCompleted.setAffectedVnfcs(getVnfcs(vnfcs));
 
 153             sendNotification(notificationOfCompleted);
 
 154         } catch (final Exception exception) {
 
 155             LOGGER.error("Error in OperationProgressor ", exception);
 
 160     private void sleep(final long milliSeconds) {
 
 162             Thread.sleep(milliSeconds);
 
 163         } catch (final InterruptedException e) {
 
 164             operation.setOperationState(InlineResponse200.OperationStateEnum.FAILED);
 
 165             // Restore interrupted state
 
 166             Thread.currentThread().interrupt();
 
 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);
 
 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());
 
 187         final LcnVnfLcmOperationOccurrenceNotificationLinks links = new LcnVnfLcmOperationOccurrenceNotificationLinks();
 
 188         final LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance vnfInstanceLink =
 
 189                 new LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance();
 
 190         vnfInstanceLink.setHref(getVnfLink());
 
 191         links.setVnfInstance(vnfInstanceLink);
 
 194         final LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance operationLink =
 
 195                 new LcnVnfLcmOperationOccurrenceNotificationLinksVnfInstance();
 
 196         operationLink.setHref(getOperationLink());
 
 197         links.setVnfLcmOpOcc(operationLink);
 
 199         notification.setLinks(links);
 
 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());
 
 221     private void sendNotification(final VnfLcmOperationOccurrenceNotification notification) {
 
 222         LOGGER.info("Sending notification: {}", notification);
 
 224             final SubscriptionsAuthenticationParamsBasic subscriptionAuthentication =
 
 225                     subscriptionService.getSubscriptions().iterator().next().getAuthentication().getParamsBasic();
 
 227                     subscriptionAuthentication.getUserName() + ":" + subscriptionAuthentication.getPassword();
 
 228             final byte[] encodedAuth = Base64.encodeBase64(auth.getBytes(StandardCharsets.ISO_8859_1));
 
 229             String authHeader = "Basic " + new String(encodedAuth);
 
 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());
 
 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());
 
 251                 .setOperation(org.onap.so.adapters.vnfmadapter.extclients.vnfm.grant.model.GrantRequest.OperationEnum
 
 252                         .fromValue(operation.getOperation().getValue()));
 
 253         grantRequest.setIsAutomaticInvocation(false);
 
 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);
 
 266     protected abstract List<GrantsAddResources> getAddResources(final String vnfdId);
 
 268     protected abstract List<GrantsAddResources> getRemoveResources(final String vnfdId);
 
 270     protected abstract List<InlineResponse201InstantiatedVnfInfoVnfcResourceInfo> handleGrantResponse(
 
 271             InlineResponse201 grantResponse);
 
 273     protected abstract ChangeTypeEnum getVnfcChangeType();
 
 275     private InlineResponse201 sendGrantRequest(final GrantRequest grantRequest) {
 
 276         LOGGER.info("Sending grant request: {}", grantRequest);
 
 279             final SubscriptionsAuthenticationParamsOauth2ClientCredentials subscriptionAuthentication =
 
 280                     subscriptionService.getSubscriptions().iterator().next().getAuthentication()
 
 281                             .getParamsOauth2ClientCredentials();
 
 283             final String authHeader = applicationConfig.getGrantAuth().equals("oauth")
 
 284                     ? "Bearer " + getToken(notificationClient.getApiClient(), subscriptionAuthentication)
 
 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);
 
 297     private String getVnfLink() {
 
 298         return getLinkBaseUrl() + "/vnf_instances/" + operation.getVnfInstanceId();
 
 301     private String getOperationLink() {
 
 302         return getLinkBaseUrl() + "/vnf_lcm_op_occs/" + operation.getId();
 
 305     private String getLinkBaseUrl() {
 
 306         return applicationConfig.getBaseUrl() + "/vnflcm/v1";
 
 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";
 
 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);
 
 321             connection.connect();
 
 323             return getResponse(connection).get("access_token").getAsString();
 
 325         } catch (IOException exception) {
 
 326             LOGGER.error("Error getting token", exception);
 
 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);
 
 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) {
 
 345         connection.getInputStream().close();
 
 347         JsonObject jsonObject = new JsonParser().parse(data).getAsJsonObject();