2  * ============LICENSE_START=======================================================
 
   3  * SOActorServiceProvider
 
   4  * ================================================================================
 
   5  * Copyright (C) 2017-2019 AT&T Intellectual Property. All rights reserved.
 
   6  * Modifications Copyright (C) 2019 Nordix Foundation.
 
   7  * ================================================================================
 
   8  * Licensed under the Apache License, Version 2.0 (the "License");
 
   9  * you may not use this file except in compliance with the License.
 
  10  * You may obtain a copy of the License at
 
  12  *      http://www.apache.org/licenses/LICENSE-2.0
 
  14  * Unless required by applicable law or agreed to in writing, software
 
  15  * distributed under the License is distributed on an "AS IS" BASIS,
 
  16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 
  17  * See the License for the specific language governing permissions and
 
  18  * limitations under the License.
 
  19  * ============LICENSE_END=========================================================
 
  22 package org.onap.policy.controlloop.actor.so;
 
  24 import com.google.common.collect.ImmutableList;
 
  25 import com.google.common.collect.ImmutableMap;
 
  26 import com.google.gson.reflect.TypeToken;
 
  27 import java.lang.reflect.Type;
 
  28 import java.util.Collections;
 
  29 import java.util.List;
 
  31 import org.onap.aai.domain.yang.CloudRegion;
 
  32 import org.onap.aai.domain.yang.GenericVnf;
 
  33 import org.onap.aai.domain.yang.ServiceInstance;
 
  34 import org.onap.aai.domain.yang.Tenant;
 
  35 import org.onap.policy.aai.AaiCqResponse;
 
  36 import org.onap.policy.controlloop.ControlLoopOperation;
 
  37 import org.onap.policy.controlloop.VirtualControlLoopEvent;
 
  38 import org.onap.policy.controlloop.actorserviceprovider.spi.Actor;
 
  39 import org.onap.policy.controlloop.policy.Policy;
 
  40 import org.onap.policy.so.SoCloudConfiguration;
 
  41 import org.onap.policy.so.SoManager;
 
  42 import org.onap.policy.so.SoModelInfo;
 
  43 import org.onap.policy.so.SoOperationType;
 
  44 import org.onap.policy.so.SoRelatedInstance;
 
  45 import org.onap.policy.so.SoRelatedInstanceListElement;
 
  46 import org.onap.policy.so.SoRequest;
 
  47 import org.onap.policy.so.SoRequestDetails;
 
  48 import org.onap.policy.so.SoRequestInfo;
 
  49 import org.onap.policy.so.SoRequestParameters;
 
  50 import org.onap.policy.so.util.Serialization;
 
  51 import org.slf4j.Logger;
 
  52 import org.slf4j.LoggerFactory;
 
  54 public class SoActorServiceProvider implements Actor {
 
  55     private static final Logger logger = LoggerFactory.getLogger(SoActorServiceProvider.class);
 
  57     private static final String TENANT_NOT_FOUND = "Tenant Item not found in AAI response {}";
 
  58     private static final String CONSTRUCTED_SO_MSG = "Constructed SO request: {}";
 
  60     // Strings for SO Actor
 
  61     private static final String SO_ACTOR = "SO";
 
  63     // Strings for targets
 
  64     private static final String TARGET_VFC = "VFC";
 
  66     // Strings for recipes
 
  67     private static final String RECIPE_VF_MODULE_CREATE = "VF Module Create";
 
  68     private static final String RECIPE_VF_MODULE_DELETE = "VF Module Delete";
 
  70     private static final ImmutableList<String> recipes =
 
  71             ImmutableList.of(RECIPE_VF_MODULE_CREATE, RECIPE_VF_MODULE_DELETE);
 
  72     private static final ImmutableMap<String, List<String>> targets =
 
  73             new ImmutableMap.Builder<String, List<String>>().put(RECIPE_VF_MODULE_CREATE, ImmutableList.of(TARGET_VFC))
 
  74                     .put(RECIPE_VF_MODULE_DELETE, ImmutableList.of(TARGET_VFC)).build();
 
  76     // name of request parameters within policy payload
 
  77     public static final String REQ_PARAM_NM = "requestParameters";
 
  79     // name of configuration parameters within policy payload
 
  80     public static final String CONFIG_PARAM_NM = "configurationParameters";
 
  82     // used to decode configuration parameters via gson
 
  83     private static final Type CONFIG_TYPE = new TypeToken<List<Map<String, String>>>() {}.getType();
 
  85     // Static variables required to hold the IDs of the last service item, VNF item and VF Module.
 
  87     // a multithreaded deployment this WILL break
 
  88     private static String lastVNFItemVnfId;
 
  89     private static String lastServiceItemServiceInstanceId;
 
  90     private static String lastVfModuleItemVfModuleInstanceId;
 
  93     public String actor() {
 
  98     public List<String> recipes() {
 
  99         return ImmutableList.copyOf(recipes);
 
 103     public List<String> recipeTargets(String recipe) {
 
 104         return ImmutableList.copyOf(targets.getOrDefault(recipe, Collections.emptyList()));
 
 108     public List<String> recipePayloads(String recipe) {
 
 109         return Collections.emptyList();
 
 112     private SoModelInfo prepareSoModelInfo(Policy policy) {
 
 114         if (policy.getTarget() == null || policy.getTarget().getModelCustomizationId() == null
 
 115                         || policy.getTarget().getModelInvariantId() == null) {
 
 119         if (policy.getTarget().getModelName() == null || policy.getTarget().getModelVersion() == null
 
 120                         || policy.getTarget().getModelVersionId() == null) {
 
 124         SoModelInfo soModelInfo = new SoModelInfo();
 
 125         soModelInfo.setModelCustomizationId(policy.getTarget().getModelCustomizationId());
 
 126         soModelInfo.setModelInvariantId(policy.getTarget().getModelInvariantId());
 
 127         soModelInfo.setModelName(policy.getTarget().getModelName());
 
 128         soModelInfo.setModelVersion(policy.getTarget().getModelVersion());
 
 129         soModelInfo.setModelVersionId(policy.getTarget().getModelVersionId());
 
 130         soModelInfo.setModelType("vfModule");
 
 135      * Construct requestInfo for the SO requestDetails.
 
 137      * @return SO request information
 
 139     private SoRequestInfo constructRequestInfo() {
 
 140         SoRequestInfo soRequestInfo = new SoRequestInfo();
 
 141         soRequestInfo.setSource("POLICY");
 
 142         soRequestInfo.setSuppressRollback(false);
 
 143         soRequestInfo.setRequestorId("policy");
 
 144         return soRequestInfo;
 
 148      * This method is needed to get the serviceInstanceId and vnfInstanceId which is used in the asyncSORestCall.
 
 150      * @param requestId the request Id
 
 151      * @param callback callback method
 
 152      * @param request the request
 
 153      * @param url SO REST URL
 
 154      * @param user username
 
 155      * @param password password
 
 157     public static void sendRequest(String requestId, SoManager.SoCallback callback, Object request, String url,
 
 158             String user, String password) {
 
 159         SoManager soManager = new SoManager(url, user, password);
 
 160         soManager.asyncSoRestCall(requestId, callback, lastServiceItemServiceInstanceId, lastVNFItemVnfId,
 
 161                 lastVfModuleItemVfModuleInstanceId, (SoRequest) request);
 
 166      * Builds the request parameters from the policy payload.
 
 168      * @param policy the policy
 
 169      * @param request request into which to stick the request parameters
 
 171     private void buildRequestParameters(Policy policy, SoRequestDetails request) {
 
 172         // assume null until proven otherwise
 
 173         request.setRequestParameters(null);
 
 175         if (policy.getPayload() == null) {
 
 179         String json = policy.getPayload().get(REQ_PARAM_NM);
 
 184         request.setRequestParameters(Serialization.gsonPretty.fromJson(json, SoRequestParameters.class));
 
 188      * Builds the configuration parameters from the policy payload.
 
 190      * @param policy the policy
 
 191      * @param request request into which to stick the configuration parameters
 
 193     private void buildConfigurationParameters(Policy policy, SoRequestDetails request) {
 
 194         // assume null until proven otherwise
 
 195         request.setConfigurationParameters(null);
 
 197         if (policy.getPayload() == null) {
 
 201         String json = policy.getPayload().get(CONFIG_PARAM_NM);
 
 206         request.setConfigurationParameters(Serialization.gsonPretty.fromJson(json, CONFIG_TYPE));
 
 210      * This method is called to remember the last service instance ID, VNF Item VNF ID and vf module ID. Note these
 
 211      * fields are static, beware for multithreaded deployments
 
 213      * @param vnfInstanceId update the last VNF instance ID to this value
 
 214      * @param serviceInstanceId update the last service instance ID to this value
 
 215      * @param vfModuleId update the vfModule instance ID to this value
 
 217     private static void preserveInstanceIds(final String vnfInstanceId, final String serviceInstanceId,
 
 218             final String vfModuleId) {
 
 219         lastVNFItemVnfId = vnfInstanceId;
 
 220         lastServiceItemServiceInstanceId = serviceInstanceId;
 
 221         lastVfModuleItemVfModuleInstanceId = vfModuleId;
 
 225      * Constructs a SO request conforming to the lcm API. The actual request is constructed and then placed in a wrapper
 
 226      * object used to send through DMAAP.
 
 228      * @param onset the event that is reporting the alert for policy to perform an action
 
 229      * @param operation the control loop operation specifying the actor, operation, target, etc.
 
 230      * @param policy the policy the was specified from the yaml generated by CLAMP or through the Policy GUI/API
 
 231      * @param aaiCqResponse response from A&AI custom query
 
 232      * @return a SO request conforming to the lcm API using the DMAAP wrapper
 
 234     public SoRequest constructRequestCq(VirtualControlLoopEvent onset, ControlLoopOperation operation, Policy policy,
 
 235             AaiCqResponse aaiCqResponse) {
 
 236         if (!SO_ACTOR.equals(policy.getActor()) || !recipes().contains(policy.getRecipe())) {
 
 240         // A&AI named query should have been performed by now. If not, return null
 
 241         if (aaiCqResponse == null) {
 
 245         SoModelInfo soModelInfo = prepareSoModelInfo(policy);
 
 247         // Report the error vf module is not found
 
 248         if (soModelInfo == null) {
 
 249             logger.error("vf module is not found.");
 
 254         ServiceInstance vnfServiceItem;
 
 256         CloudRegion cloudRegionItem;
 
 258         // Extract the items we're interested in from the response
 
 260             vnfItem = aaiCqResponse.getGenericVnfByVfModuleModelInvariantId(soModelInfo.getModelInvariantId());
 
 261             //Report VNF not found
 
 262             if (vnfItem == null) {
 
 263                 logger.error("Generic Vnf is not found.");
 
 266         } catch (Exception e) {
 
 267             logger.error("VNF Item not found in AAI response {}", Serialization.gsonPretty.toJson(aaiCqResponse), e);
 
 272             vnfServiceItem = aaiCqResponse.getServiceInstance();
 
 273         } catch (Exception e) {
 
 274             logger.error("VNF Service Item not found in AAI response {}",
 
 275                     Serialization.gsonPretty.toJson(aaiCqResponse), e);
 
 280             tenantItem = aaiCqResponse.getDefaultTenant();
 
 281         } catch (Exception e) {
 
 282             logger.error(TENANT_NOT_FOUND, Serialization.gsonPretty.toJson(aaiCqResponse), e);
 
 287             cloudRegionItem = aaiCqResponse.getDefaultCloudRegion();
 
 288         } catch (Exception e) {
 
 289             logger.error(TENANT_NOT_FOUND, Serialization.gsonPretty.toJson(aaiCqResponse), e);
 
 295         // Construct SO Request for a policy's recipe
 
 296         if (RECIPE_VF_MODULE_CREATE.equals(policy.getRecipe())) {
 
 297             return constructCreateRequestCq(aaiCqResponse, policy, tenantItem, vnfItem, vnfServiceItem, soModelInfo,
 
 299         } else if (RECIPE_VF_MODULE_DELETE.equals(policy.getRecipe())) {
 
 300             return constructDeleteRequestCq(tenantItem, vnfItem, vnfServiceItem, policy, cloudRegionItem);
 
 307      * Construct the So request, based on Custom Query response from A&AI.
 
 309      * @param aaiCqResponse Custom query response from A&AI
 
 310      * @param policy policy information
 
 311      * @param tenantItem Tenant from CQ response
 
 312      * @param vnfItem Generic VNF from CQ response
 
 313      * @param vnfServiceItem Service Instance from CQ response
 
 314      * @param vfModuleItem VF Module from CustomQuery response
 
 315      * @param cloudRegionItem Cloud Region from Custom query response
 
 316      * @return SoRequest well formed So Request
 
 318     private SoRequest constructCreateRequestCq(AaiCqResponse aaiCqResponse, Policy policy, Tenant tenantItem,
 
 319             GenericVnf vnfItem, ServiceInstance vnfServiceItem, SoModelInfo vfModuleItem, CloudRegion cloudRegionItem) {
 
 320         SoRequest request = new SoRequest();
 
 321         request.setOperationType(SoOperationType.SCALE_OUT);
 
 324         // Do NOT send So the requestId, they do not support this field
 
 326         request.setRequestDetails(new SoRequestDetails());
 
 327         request.getRequestDetails().setRequestParameters(new SoRequestParameters());
 
 328         request.getRequestDetails().getRequestParameters().setUserParams(null);
 
 330         // cloudConfiguration
 
 331         request.getRequestDetails().setCloudConfiguration(constructCloudConfigurationCq(tenantItem, cloudRegionItem));
 
 333         request.getRequestDetails().setModelInfo(vfModuleItem);
 
 337         request.getRequestDetails().setRequestInfo(constructRequestInfo());
 
 338         request.getRequestDetails().getRequestInfo().setInstanceName("vfModuleName");
 
 340         // relatedInstanceList
 
 341         SoRelatedInstanceListElement relatedInstanceListElement1 = new SoRelatedInstanceListElement();
 
 342         SoRelatedInstanceListElement relatedInstanceListElement2 = new SoRelatedInstanceListElement();
 
 343         relatedInstanceListElement1.setRelatedInstance(new SoRelatedInstance());
 
 344         relatedInstanceListElement2.setRelatedInstance(new SoRelatedInstance());
 
 347         relatedInstanceListElement1.getRelatedInstance().setInstanceId(vnfServiceItem.getServiceInstanceId());
 
 348         relatedInstanceListElement1.getRelatedInstance().setModelInfo(new SoModelInfo());
 
 349         relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelType("service");
 
 350         relatedInstanceListElement1.getRelatedInstance().getModelInfo()
 
 351                 .setModelInvariantId(vnfServiceItem.getModelInvariantId());
 
 352         relatedInstanceListElement1.getRelatedInstance().getModelInfo()
 
 353                 .setModelVersionId(vnfServiceItem.getModelVersionId());
 
 354         relatedInstanceListElement1.getRelatedInstance().getModelInfo()
 
 355                 .setModelName(aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelName());
 
 356         relatedInstanceListElement1.getRelatedInstance().getModelInfo().setModelVersion(
 
 357                 aaiCqResponse.getModelVerByVersionId(vnfServiceItem.getModelVersionId()).getModelVersion());
 
 361         relatedInstanceListElement2.getRelatedInstance().setInstanceId(vnfItem.getVnfId());
 
 362         relatedInstanceListElement2.getRelatedInstance().setModelInfo(new SoModelInfo());
 
 363         relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelType("vnf");
 
 364         relatedInstanceListElement2.getRelatedInstance().getModelInfo()
 
 365                 .setModelInvariantId(vnfItem.getModelInvariantId());
 
 366         relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersionId(vnfItem.getModelVersionId());
 
 368         relatedInstanceListElement2.getRelatedInstance().getModelInfo()
 
 369                 .setModelName(aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelName());
 
 370         relatedInstanceListElement2.getRelatedInstance().getModelInfo().setModelVersion(
 
 371                 aaiCqResponse.getModelVerByVersionId(vnfItem.getModelVersionId()).getModelVersion());
 
 374         relatedInstanceListElement2.getRelatedInstance().getModelInfo()
 
 375                 .setModelCustomizationId(vnfItem.getModelCustomizationId());
 
 378         // Insert the Service Item and VNF Item
 
 379         request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement1);
 
 380         request.getRequestDetails().getRelatedInstanceList().add(relatedInstanceListElement2);
 
 382         // Request Parameters
 
 383         buildRequestParameters(policy, request.getRequestDetails());
 
 385         // Configuration Parameters
 
 386         buildConfigurationParameters(policy, request.getRequestDetails());
 
 387         // Save the instance IDs for the VNF and service to static fields
 
 388         // vfModuleId is not required for the create vf-module
 
 389         preserveInstanceIds(vnfItem.getVnfId(), vnfServiceItem.getServiceInstanceId(), null);
 
 390         if (logger.isDebugEnabled()) {
 
 391             logger.debug(CONSTRUCTED_SO_MSG, Serialization.gsonPretty.toJson(request));
 
 397      * constructs delete request for So.
 
 399      * @param tenantItem Tenant from A&AI CQ request
 
 400      * @param vnfItem Generic VNF from A&AI CQ request
 
 401      * @param vnfServiceItem ServiceInstance from A&AI CQ request
 
 402      * @param policy policy information
 
 403      * @param cloudRegionItem CloudRegion from A&AI CQ request
 
 404      * @return SoRequest deleted
 
 406     private SoRequest constructDeleteRequestCq(Tenant tenantItem, GenericVnf vnfItem, ServiceInstance vnfServiceItem,
 
 407             Policy policy, CloudRegion cloudRegionItem) {
 
 408         SoRequest request = new SoRequest();
 
 409         request.setOperationType(SoOperationType.DELETE_VF_MODULE);
 
 410         request.setRequestDetails(new SoRequestDetails());
 
 411         request.getRequestDetails().setRelatedInstanceList(null);
 
 412         request.getRequestDetails().setConfigurationParameters(null);
 
 414         // cloudConfiguration
 
 415         request.getRequestDetails().setCloudConfiguration(constructCloudConfigurationCq(tenantItem, cloudRegionItem));
 
 417         request.getRequestDetails().setModelInfo(prepareSoModelInfo(policy));
 
 419         request.getRequestDetails().setRequestInfo(constructRequestInfo());
 
 420         // Save the instance IDs for the VNF, service and vfModule to static fields
 
 421         preserveInstanceIds(vnfItem.getVnfId(), vnfServiceItem.getServiceInstanceId(), null);
 
 423         if (logger.isDebugEnabled()) {
 
 424             logger.debug(CONSTRUCTED_SO_MSG, Serialization.gsonPretty.toJson(request));
 
 431      * Construct cloudConfiguration for the SO requestDetails. Overridden for custom query.
 
 433      * @param tenantItem tenant item from A&AI named-query response
 
 434      * @return SO cloud configuration
 
 436     private SoCloudConfiguration constructCloudConfigurationCq(Tenant tenantItem, CloudRegion cloudRegionItem) {
 
 437         SoCloudConfiguration cloudConfiguration = new SoCloudConfiguration();
 
 438         cloudConfiguration.setTenantId(tenantItem.getTenantId());
 
 439         cloudConfiguration.setLcpCloudRegionId(cloudRegionItem.getCloudRegionId());
 
 440         return cloudConfiguration;