Fix template generation for R2
[vfc/nfvo/driver/vnfm/svnfm.git] / nokiav2 / driver / src / main / java / org / onap / vfc / nfvo / driver / vnfm / svnfm / nokia / vnfm / LifecycleManager.java
index 94ab240..7c8e231 100644 (file)
 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm;
 
 
+import com.google.common.base.Joiner;
 import com.google.gson.Gson;
 import com.google.gson.JsonElement;
 import com.google.gson.JsonObject;
+import com.google.gson.JsonParser;
 import com.nokia.cbam.catalog.v1.model.CatalogAdapterVnfpackage;
 import com.nokia.cbam.lcm.v32.model.*;
 import com.nokia.cbam.lcm.v32.model.ScaleDirection;
@@ -30,22 +32,22 @@ import javax.servlet.http.HttpServletResponse;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IGrantManager;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VimInfoProvider;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.StoreLoader;
-import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.UserVisibleError;
 import org.onap.vnfmdriver.model.ExtVirtualLinkInfo;
 import org.onap.vnfmdriver.model.*;
 import org.onap.vnfmdriver.model.VimInfo;
 import org.onap.vnfmdriver.model.VnfInfo;
 import org.slf4j.Logger;
-import org.springframework.beans.factory.annotation.Autowired;
-import org.springframework.stereotype.Component;
 import org.yaml.snakeyaml.Yaml;
 
 import static java.lang.Integer.parseInt;
 import static java.nio.charset.StandardCharsets.UTF_8;
+import static java.util.stream.Collectors.toList;
 
 import static com.google.common.base.Splitter.on;
 import static com.google.common.collect.Iterables.find;
+import static com.google.common.collect.Iterables.transform;
 import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Ordering.natural;
 import static com.google.common.collect.Sets.newHashSet;
 import static com.nokia.cbam.lcm.v32.model.InstantiationState.INSTANTIATED;
 import static com.nokia.cbam.lcm.v32.model.OperationStatus.FINISHED;
@@ -61,7 +63,6 @@ import static org.springframework.util.StringUtils.isEmpty;
 /**
  * Responsible for executing lifecycle operation on the VNF
  */
-@Component
 public class LifecycleManager {
     public static final String ONAP_CSAR_ID = "onapCsarId";
     public static final long OPERATION_STATUS_POLLING_INTERVAL_IN_MS = 5000L;
@@ -70,6 +71,8 @@ public class LifecycleManager {
      */
     public static final String EXTERNAL_VNFM_ID = "externalVnfmId";
     public static final String SCALE_OPERATION_NAME = "scale";
+    public static final String ETSI_CONFIG = "etsi_config";
+    public static final String PROPERTIES = "properties";
     private static Logger logger = getLogger(LifecycleManager.class);
     private final CatalogManager catalogManager;
     private final IGrantManager grantManager;
@@ -83,7 +86,6 @@ public class LifecycleManager {
      */
     private ExecutorService executorService = Executors.newCachedThreadPool();
 
-    @Autowired
     LifecycleManager(CatalogManager catalogManager, IGrantManager grantManager, CbamRestApiProvider restApiProvider, VimInfoProvider vimInfoProvider, JobManager jobManager, ILifecycleChangeNotificationManager notificationManager) {
         this.vimInfoProvider = vimInfoProvider;
         this.grantManager = grantManager;
@@ -113,6 +115,10 @@ public class LifecycleManager {
         return find(NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions), op -> INSTANTIATE.equals(op.getOperationType()));
     }
 
+    public static String getVnfdIdFromModifyableAttributes(com.nokia.cbam.lcm.v32.model.VnfInfo vnf) {
+        return find(vnf.getExtensions(), p -> p.getName().equals(ONAP_CSAR_ID)).getValue().toString();
+    }
+
     /**
      * Create the VNF. It consists of the following steps
      * <ul>
@@ -123,7 +129,7 @@ public class LifecycleManager {
      * The rollback of the failed operation is not implemented
      * <ul>
      * <li>delete the VNF if error occurs before instantiation</li>
-     * <li>terminate & delete VNF if error occurs after instantiation</li>
+     * <li>terminateVnf & delete VNF if error occurs after instantiation</li>
      * </ul>
      *
      * @param vnfmId      the identifier of the VNFM
@@ -157,22 +163,25 @@ public class LifecycleManager {
     /**
      * Instantiate the VNF
      *
-     * @param vnfmId               the identifier of the VNFM
-     * @param request              the VNF instantiation request
-     * @param httpResponse         the HTTP response that corresponds to the VNF instantiation request
-     * @param additionalParameters additional parameters
-     * @param vnfId                thr identifier of the VNF
-     * @param vnfdId               the identifier of the VNF package in CBAM
+     * @param vnfmId                        the identifier of the VNFM
+     * @param externalVirtualLinks          the external virtual links of the VNF
+     * @param httpResponse                  the HTTP response that corresponds to the VNF instantiation request
+     * @param additionalParameters          additional parameters
+     * @param vnfId                         the identifier of the VNF
+     * @param vnfmVnfdId                    the identifier of the VNF package in CBAM
+     * @param operationAdditionalParameters the additional parameters of the operation
+     * @param onapVnfdId                    the identifier of the VNFD in the VNFM
      * @return the instantiation response
      */
-    public VnfInstantiateResponse instantiate(String vnfmId, VnfInstantiateRequest request, HttpServletResponse httpResponse, AdditionalParameters additionalParameters, String vnfId, String vnfdId) {
-        logOperationInput(vnfId, "instantiation", request);
+    @SuppressWarnings("squid:S00107") //wrapping them into an object makes the code less readable
+    public VnfInstantiateResponse instantiate(String vnfmId, List<ExtVirtualLinkInfo> externalVirtualLinks, HttpServletResponse httpResponse, Object operationAdditionalParameters, AdditionalParameters additionalParameters, String vnfId, String onapVnfdId, String vnfmVnfdId) {
+        logOperationInput(vnfId, "instantiation", additionalParameters);
         validateVimType(additionalParameters.getVimType());
         VnfInstantiateResponse response = new VnfInstantiateResponse();
         response.setVnfInstanceId(vnfId);
-        String vimId = getVimId(request.getAdditionalParam());
+        String vimId = getVimId(operationAdditionalParameters);
         JobInfo spawnJob = scheduleExecution(vnfId, httpResponse, "instantiate", jobInfo ->
-                instantiateVnf(vnfmId, request, additionalParameters, vnfdId, vnfId, vimId, jobInfo)
+                instantiateVnf(vnfmId, externalVirtualLinks, additionalParameters, onapVnfdId, vnfmVnfdId, vnfId, vimId, jobInfo)
         );
         response.setJobId(spawnJob.getJobId());
         return response;
@@ -193,7 +202,7 @@ public class LifecycleManager {
      * The rollback of the failed operation is not implemented
      * <ul>
      * <li>delete the VNF if error occurs before instantiation</li>
-     * <li>terminate & delete VNf if error occurs after instantiation</li>
+     * <li>terminateVnf & delete VNf if error occurs after instantiation</li>
      * </ul>
      *
      * @param vnfmId       the identifier of the VNFM
@@ -205,18 +214,18 @@ public class LifecycleManager {
         AdditionalParameters additionalParameters = convertInstantiationAdditionalParams(request.getVnfPackageId(), request.getAdditionalParam());
         validateVimType(additionalParameters.getVimType());
         VnfCreationResult creationResult = create(vnfmId, request.getVnfDescriptorId(), request.getVnfInstanceName(), request.getVnfInstanceDescription());
-        return instantiate(vnfmId, request, httpResponse, additionalParameters, creationResult.vnfInfo.getId(), creationResult.vnfdId);
+        return instantiate(vnfmId, request.getExtVirtualLink(), httpResponse, request.getAdditionalParam(), additionalParameters, creationResult.vnfInfo.getId(), request.getVnfPackageId(), creationResult.vnfdId);
     }
 
-    private void instantiateVnf(String vnfmId, VnfInstantiateRequest request, AdditionalParameters additionalParameters, String vnfdId, String vnfId, String vimId, JobInfo jobInfo) {
-        String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, vnfdId);
-        GrantVNFResponseVim vim = grantManager.requestGrantForInstantiate(vnfmId, vnfId, vimId, request.getVnfPackageId(), additionalParameters.getInstantiationLevel(), vnfdContent, jobInfo.getJobId());
-        if (vim.getVimId() == null) {
-            throw buildFatalFailure(logger, "VF-C did not send VIM identifier in grant response");
-        }
+    @SuppressWarnings("squid:S00107") //wrapping them into an object makes the code less readable
+    private void instantiateVnf(String vnfmId, List<ExtVirtualLinkInfo> extVirtualLinkInfos, AdditionalParameters additionalParameters, String onapVnfdId, String vnfmVnfdId, String vnfId, String vimId, JobInfo jobInfo) {
+        String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, vnfmVnfdId);
+        addSpecifiedExtensions(vnfmId, vnfId, additionalParameters);
+        GrantVNFResponseVim vim = grantManager.requestGrantForInstantiate(vnfmId, vnfId, vimId, onapVnfdId, additionalParameters.getInstantiationLevel(), vnfdContent, jobInfo.getJobId());
+        handleBackwardIncompatibleApiChangesInVfc(vim);
         VimInfo vimInfo = vimInfoProvider.getVimInfo(vim.getVimId());
         InstantiateVnfRequest instantiationRequest = new InstantiateVnfRequest();
-        addExternalLinksToRequest(request.getExtVirtualLink(), additionalParameters, instantiationRequest, vimId);
+        addExternalLinksToRequest(extVirtualLinkInfos, additionalParameters, instantiationRequest, vimId);
         instantiationRequest.getVims().add(addVim(additionalParameters, vimId, vim, vimInfo));
         instantiationRequest.setFlavourId(getFlavorId(vnfdContent));
         instantiationRequest.setComputeResourceFlavours(additionalParameters.getComputeResourceFlavours());
@@ -241,13 +250,37 @@ public class LifecycleManager {
         waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
     }
 
+    private void handleBackwardIncompatibleApiChangesInVfc(GrantVNFResponseVim vim) {
+        if (vim.getVimId() == null) {
+            if (vim.getVimid() == null) {
+                throw buildFatalFailure(logger, "VF-C did not send VIM identifier in grant response");
+            } else {
+                vim.setVimId(vim.getVimid());
+            }
+        }
+        if (vim.getAccessInfo() == null) {
+            if (vim.getAccessinfo() == null) {
+                throw buildFatalFailure(logger, "VF-C did not send access info in grant response");
+            } else {
+                vim.setAccessInfo(vim.getAccessinfo());
+            }
+        }
+    }
+
     private com.nokia.cbam.lcm.v32.model.VimInfo addVim(AdditionalParameters additionalParameters, String vimId, GrantVNFResponseVim vim, VimInfo vimInfo) {
         if (additionalParameters.getVimType() == OPENSTACK_V2_INFO) {
             return buildOpenStackV2INFO(vimId, vim, vimInfo);
 
         } else if (additionalParameters.getVimType() == OPENSTACK_V3_INFO) {
-            return buildOpenStackV3INFO(vimId, additionalParameters, vim, vimInfo);
-
+            if (isEmpty(vimInfo.getDomain())) {
+                if (isEmpty(additionalParameters.getDomain())) {
+                    throw buildFatalFailure(logger, "The cloud did not supply the cloud domain (Amsterdam release) and was not supplied as additional data");
+                } else {
+                    logger.warn("Setting domain from additional parameters");
+                    vimInfo.setDomain(additionalParameters.getDomain());
+                }
+            }
+            return buildOpenStackV3INFO(vimId, vim, vimInfo);
         } else {
             //OTHER VIM TYPE is not possible
             return buildVcloudInfo(vimId, vimInfo);
@@ -265,26 +298,44 @@ public class LifecycleManager {
     }
 
     private AdditionalParameters convertInstantiationAdditionalParams(String csarId, Object additionalParams) {
-        JsonObject vnfParameters = child(child(new Gson().toJsonTree(additionalParams).getAsJsonObject(), "inputs"), "vnfs");
-        if (!vnfParameters.has(csarId)) {
-            throw buildFatalFailure(logger, "The additional parameter section does not contain setting for VNF with " + csarId + " CSAR id");
+        JsonObject root = new Gson().toJsonTree(additionalParams).getAsJsonObject();
+        if (root.has(PROPERTIES)) {
+            JsonObject properties = new JsonParser().parse(root.get(PROPERTIES).getAsString()).getAsJsonObject();
+            if (properties.has(ETSI_CONFIG)) {
+                JsonElement etsiConfig = properties.get(ETSI_CONFIG);
+                return new Gson().fromJson(etsiConfig.getAsString(), AdditionalParameters.class);
+            } else {
+                logger.info("The instantiation input for VNF with {} CSAR id does not have an " + ETSI_CONFIG + " section", csarId);
+            }
+        } else {
+            logger.info("The instantiation input for VNF with {} CSAR id does not have a properties section", csarId);
+        }
+        JsonObject inputs = child(root, "inputs");
+        if (!inputs.has(csarId)) {
+            return new Gson().fromJson(catalogManager.getEtsiConfiguration(csarId), AdditionalParameters.class);
         }
-        JsonElement additionalParamsForVnf = vnfParameters.get(csarId);
+        JsonElement additionalParamsForVnf = new JsonParser().parse(inputs.get(csarId).getAsString());
         return new Gson().fromJson(additionalParamsForVnf, AdditionalParameters.class);
     }
 
     private String getFlavorId(String vnfdContent) {
         JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject();
         JsonObject capabilities = child(child(child(root, "topology_template"), "substitution_mappings"), "capabilities");
-        JsonObject deploymentFlavorProperties = child(child(capabilities, "deployment_flavour"), "properties");
+        JsonObject deploymentFlavorProperties = child(child(capabilities, "deployment_flavour"), PROPERTIES);
         return childElement(deploymentFlavorProperties, "flavour_id").getAsString();
     }
 
-    private Set<Map.Entry<String, JsonElement>> getAcceptableOperationParameters(String vnfdContent, String categroryOfOperation, String operationName) {
+    private Set<Map.Entry<String, JsonElement>> getAcceptableOperationParameters(String vnfdContent, String operationName) {
         JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject();
         JsonObject interfaces = child(child(child(root, "topology_template"), "substitution_mappings"), "interfaces");
-        JsonObject additionalParameters = child(child(child(child(interfaces, categroryOfOperation), operationName), "inputs"), "additional_parameters");
-        return additionalParameters.entrySet();
+        List<List<Map.Entry<String, JsonElement>>> operations = interfaces.entrySet().stream().map(m -> m.getValue().getAsJsonObject().entrySet().stream().collect(toList())).collect(toList());
+        for (Map.Entry<String, JsonElement> operation : operations.stream().flatMap(List::stream).collect(toList())) {
+            if (operation.getKey().equals(operationName)) {
+                return child(child(operation.getValue().getAsJsonObject(), "inputs"), "additional_parameters").entrySet();
+            }
+        }
+
+        throw buildFatalFailure(logger, "Unable to find operation named " + operationName);
     }
 
     private void addExternalLinksToRequest(List<ExtVirtualLinkInfo> extVirtualLinks, AdditionalParameters additionalParameters, InstantiateVnfRequest instantiationRequest, String vimId) {
@@ -304,31 +355,46 @@ public class LifecycleManager {
 
     private void addVnfdIdToVnfModifyableAttributeExtensions(String vnfmId, String vnfId, String onapCsarId) {
         ModifyVnfInfoRequest request = new ModifyVnfInfoRequest();
+        request.setExtensions(new ArrayList<>());
         VnfProperty onapCsarIdProperty = new VnfProperty();
         onapCsarIdProperty.setName(ONAP_CSAR_ID);
         onapCsarIdProperty.setValue(onapCsarId);
-        request.setExtensions(new ArrayList<>());
         request.getExtensions().add(onapCsarIdProperty);
         VnfProperty externalVnfmIdProperty = new VnfProperty();
         externalVnfmIdProperty.setName(EXTERNAL_VNFM_ID);
         externalVnfmIdProperty.setValue(vnfmId);
         request.getExtensions().add(externalVnfmIdProperty);
-        request.setVnfConfigurableProperties(null);
+        executeModifyVnfInfo(vnfmId, vnfId, request);
+    }
+
+    private void executeModifyVnfInfo(String vnfmId, String vnfId, ModifyVnfInfoRequest request) {
         try {
             OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdPatch(vnfId, request, NOKIA_LCM_API_VERSION).blockingFirst();
             waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
         } catch (Exception e) {
-            throw buildFatalFailure(logger, "Unable to set the " + ONAP_CSAR_ID + " property on the VNF", e);
+            String properties = Joiner.on(",").join(natural().sortedCopy(transform(request.getExtensions(), VnfProperty::getName)));
+            throw buildFatalFailure(logger, "Unable to set the " + properties + " properties on the VNF with " + vnfId + " identifier", e);
+        }
+    }
+
+    private void addSpecifiedExtensions(String vnfmId, String vnfId, AdditionalParameters additionalParameters) {
+        if (!additionalParameters.getExtensions().isEmpty()) {
+            ModifyVnfInfoRequest request = new ModifyVnfInfoRequest();
+            request.setExtensions(new ArrayList<>());
+            request.getExtensions().addAll(additionalParameters.getExtensions());
+            executeModifyVnfInfo(vnfmId, vnfId, request);
+        } else {
+            logger.info("No extensions specified for VNF with {} identifier", vnfId);
         }
     }
 
-    private OPENSTACKV3INFO buildOpenStackV3INFO(String vimId, AdditionalParameters additionalParameters, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) {
+    private OPENSTACKV3INFO buildOpenStackV3INFO(String vimId, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) {
         OPENSTACKV3INFO openstackv3INFO = new OPENSTACKV3INFO();
         openstackv3INFO.setVimInfoType(OPENSTACK_V3_INFO);
         OpenStackAccessInfoV3 accessInfov3 = new OpenStackAccessInfoV3();
         openstackv3INFO.accessInfo(accessInfov3);
         accessInfov3.setPassword(vimInfo.getPassword());
-        accessInfov3.setDomain(additionalParameters.getDomain());
+        accessInfov3.setDomain(vimInfo.getDomain());
         accessInfov3.setProject(vim.getAccessInfo().getTenant());
         accessInfov3.setRegion(getRegionName(vimId));
         accessInfov3.setUsername(vimInfo.getUserName());
@@ -400,46 +466,73 @@ public class LifecycleManager {
      */
     public JobInfo terminateAndDelete(String vnfmId, String vnfId, VnfTerminateRequest request, HttpServletResponse httpResponse) {
         logOperationInput(vnfId, "termination", request);
-        return scheduleExecution(vnfId, httpResponse, "terminate", jobInfo -> {
-            TerminateVnfRequest cbamRequest = new TerminateVnfRequest();
-            if (request.getTerminationType() == null) {
-                cbamRequest.setTerminationType(TerminationType.FORCEFUL);
-            } else {
-                if (request.getTerminationType().equals(VnfTerminationType.GRACEFUL)) {
-                    cbamRequest.setTerminationType(TerminationType.GRACEFUL);
-                    cbamRequest.setGracefulTerminationTimeout(parseInt(request.getGracefulTerminationTimeout()));
-                } else {
-                    cbamRequest.setTerminationType(TerminationType.FORCEFUL);
-                }
-            }
-            cbamRequest.setAdditionalParams(new Gson().toJsonTree(jobInfo).getAsJsonObject());
-            com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst();
-            if (vnf.getInstantiationState() == INSTANTIATED) {
-                terminateAndDelete(vnfmId, vnfId, jobInfo, cbamRequest, vnf);
-            } else {
-                logger.debug("The VNF {} with identifier is not instantiated no termination required", vnf.getId());
-                deleteVnf(vnfmId, vnfId);
-            }
+        return scheduleExecution(vnfId, httpResponse, "terminateVnf", jobInfo -> {
+            terminateVnf(vnfmId, vnfId, request, jobInfo);
+            deleteVnf(vnfmId, vnfId);
         });
     }
 
-    private void terminateAndDelete(String vnfmId, String vnfId, JobInfo jobInfo, TerminateVnfRequest cbamRequest, com.nokia.cbam.lcm.v32.model.VnfInfo vnf) {
-        String vimId = getVimIdFromInstantiationRequest(vnfmId, vnf);
-        grantManager.requestGrantForTerminate(vnfmId, vnfId, vimId, getVnfdIdFromModifyableAttributes(vnf), vnf, jobInfo.getJobId());
-        OperationExecution terminationOperation = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdTerminatePost(vnfId, cbamRequest, NOKIA_LCM_API_VERSION).blockingFirst();
-        OperationExecution finishedOperation = waitForOperationToFinish(vnfmId, vnfId, terminationOperation.getId());
-        if (finishedOperation.getStatus() == FINISHED) {
-            notificationManager.waitForTerminationToBeProcessed(finishedOperation.getId());
-            deleteVnf(vnfmId, vnfId);
+    /**
+     * Terminates the VNF
+     * <ul>
+     * <li>fails if the VNF does not exist</li>
+     * <li>terminates if instantiated</li>
+     * <li>deletes the VNF</li>
+     * </ul>
+     *
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param request      the termination request
+     * @param httpResponse the HTTP response
+     * @return the job for polling the progress of the termination
+     */
+    public JobInfo terminate(String vnfmId, String vnfId, VnfTerminateRequest request, HttpServletResponse httpResponse) {
+        logOperationInput(vnfId, "termination", request);
+        return scheduleExecution(vnfId, httpResponse, "terminate", jobInfo -> terminateVnf(vnfmId, vnfId, request, jobInfo));
+    }
 
+    private void terminateVnf(String vnfmId, String vnfId, VnfTerminateRequest request, JobInfo jobInfo) {
+        TerminateVnfRequest cbamRequest = new TerminateVnfRequest();
+        setState(request, cbamRequest);
+        cbamRequest.setAdditionalParams(new Gson().toJsonTree(jobInfo).getAsJsonObject());
+        com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst();
+        if (vnf.getInstantiationState() == INSTANTIATED) {
+            String vimId = getVimIdFromInstantiationRequest(vnfmId, vnf);
+            grantManager.requestGrantForTerminate(vnfmId, vnfId, vimId, getVnfdIdFromModifyableAttributes(vnf), vnf, jobInfo.getJobId());
+            OperationExecution terminationOperation = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdTerminatePost(vnfId, cbamRequest, NOKIA_LCM_API_VERSION).blockingFirst();
+            OperationExecution finishedOperation = waitForOperationToFinish(vnfmId, vnfId, terminationOperation.getId());
+            if (finishedOperation.getStatus() == FINISHED) {
+                notificationManager.waitForTerminationToBeProcessed(finishedOperation.getId());
+            } else {
+                throw buildFatalFailure(logger, "Unable to terminate VNF the operation did not finish with success");
+            }
         } else {
-            logger.error("Unable to terminate VNF the operation did not finish with success");
+            logger.warn("The VNF with {} identifier is not instantiated no termination is required", vnfId);
         }
     }
 
-    private void deleteVnf(String vnfmId, String vnfId) {
+    private void setState(VnfTerminateRequest request, TerminateVnfRequest cbamRequest) {
+        if (request.getTerminationType() == null) {
+            cbamRequest.setTerminationType(TerminationType.FORCEFUL);
+        } else {
+            if (request.getTerminationType().equals(VnfTerminationType.GRACEFUL)) {
+                cbamRequest.setTerminationType(TerminationType.GRACEFUL);
+                cbamRequest.setGracefulTerminationTimeout(parseInt(request.getGracefulTerminationTimeout()));
+            } else {
+                cbamRequest.setTerminationType(TerminationType.FORCEFUL);
+            }
+        }
+    }
+
+    /**
+     * Delete the VNF
+     *
+     * @param vnfmId the identifier of the VNFM
+     * @param vnfId  the identifier fo the VNF
+     */
+    public void deleteVnf(String vnfmId, String vnfId) {
         logger.info("Deleting VNF with {} identifier", vnfId);
-        cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION).blockingFirst();
+        cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION).blockingFirst(null);
         logger.info("The VNF with {} identifier has been deleted", vnfId);
     }
 
@@ -450,10 +543,6 @@ public class LifecycleManager {
         return childElement(childElement(root, "vims").getAsJsonArray().get(0).getAsJsonObject(), "id").getAsString();
     }
 
-    private String getVnfdIdFromModifyableAttributes(com.nokia.cbam.lcm.v32.model.VnfInfo vnf) {
-        return find(vnf.getExtensions(), p -> p.getName().equals(ONAP_CSAR_ID)).getValue().toString();
-    }
-
     /**
      * @param vnfmId the identifier of the VNFM
      * @param vnfId  the identifier of the VNF
@@ -462,23 +551,27 @@ public class LifecycleManager {
     public VnfInfo queryVnf(String vnfmId, String vnfId) {
         try {
             com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst();
-            VnfInfo vnfInfo = new VnfInfo();
-            vnfInfo.setVersion(cbamVnfInfo.getVnfSoftwareVersion());
-            vnfInfo.setVnfInstanceId(vnfId);
-            String onapCsarId = getVnfdIdFromModifyableAttributes(cbamVnfInfo);
-            vnfInfo.setVnfdId(onapCsarId);
-            vnfInfo.setVnfPackageId(onapCsarId);
-            vnfInfo.setVnfInstanceDescription(cbamVnfInfo.getDescription());
-            vnfInfo.setVnfInstanceName(cbamVnfInfo.getName());
-            vnfInfo.setVnfProvider(cbamVnfInfo.getVnfProvider());
-            vnfInfo.setVnfStatus("ACTIVE");
-            vnfInfo.setVnfType("Kuku");
-            return vnfInfo;
+            return convertVnfInfo(vnfId, cbamVnfInfo);
         } catch (Exception e) {
             throw buildFatalFailure(logger, "Unable to query VNF (" + vnfId + ")", e);
         }
     }
 
+    private VnfInfo convertVnfInfo(String vnfId, com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo) {
+        VnfInfo vnfInfo = new VnfInfo();
+        vnfInfo.setVersion(cbamVnfInfo.getVnfSoftwareVersion());
+        vnfInfo.setVnfInstanceId(vnfId);
+        String onapCsarId = getVnfdIdFromModifyableAttributes(cbamVnfInfo);
+        vnfInfo.setVnfdId(onapCsarId);
+        vnfInfo.setVnfPackageId(onapCsarId);
+        vnfInfo.setVnfInstanceDescription(cbamVnfInfo.getDescription());
+        vnfInfo.setVnfInstanceName(cbamVnfInfo.getName());
+        vnfInfo.setVnfProvider(cbamVnfInfo.getVnfProvider());
+        vnfInfo.setVnfStatus("ACTIVE");
+        vnfInfo.setVnfType("Kuku");
+        return vnfInfo;
+    }
+
     private ScaleDirection convert(org.onap.vnfmdriver.model.ScaleDirection direction) {
         if (org.onap.vnfmdriver.model.ScaleDirection.IN.equals(direction)) {
             return ScaleDirection.IN;
@@ -507,7 +600,7 @@ public class LifecycleManager {
             JsonObject root = new Gson().toJsonTree(jobInfo).getAsJsonObject();
             com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst();
             String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, cbamVnfInfo.getVnfdId());
-            Set<Map.Entry<String, JsonElement>> acceptableOperationParameters = getAcceptableOperationParameters(vnfdContent, "Basic", SCALE_OPERATION_NAME);
+            Set<Map.Entry<String, JsonElement>> acceptableOperationParameters = getAcceptableOperationParameters(vnfdContent, SCALE_OPERATION_NAME);
             buildAdditionalParameters(request, root, acceptableOperationParameters);
             cbamRequest.setAdditionalParams(root);
             grantManager.requestGrantForScale(vnfmId, vnfId, getVimIdFromInstantiationRequest(vnfmId, vnf), getVnfdIdFromModifyableAttributes(vnf), request, jobInfo.getJobId());
@@ -566,6 +659,16 @@ public class LifecycleManager {
         });
     }
 
+    public JobInfo customOperation(String vnfmId, String vnfId, String operationId, Object additionalParams, HttpServletResponse httpResponse) {
+        logOperationInput(vnfId, "custom", additionalParams);
+        return scheduleExecution(vnfId, httpResponse, "custom", job -> {
+            CustomOperationRequest cbamRequest = new CustomOperationRequest();
+            cbamRequest.setAdditionalParams(additionalParams);
+            OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdCustomCustomOperationNamePost(vnfId, operationId, cbamRequest, NOKIA_LCM_API_VERSION).blockingFirst();
+            waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
+        });
+    }
+
     private JobInfo scheduleExecution(String vnfId, HttpServletResponse httpResponse, String operation, AsynchronousExecution asynchronExecution) {
         JobInfo jobInfo = new JobInfo();
         jobInfo.setJobId(jobManager.spawnJob(vnfId, httpResponse));
@@ -609,11 +712,16 @@ public class LifecycleManager {
 
     public static class VnfCreationResult {
         private final com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo;
+
         private final String vnfdId;
 
-        VnfCreationResult(com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo, String vnfdId) {
+        public VnfCreationResult(com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo, String vnfdId) {
             this.vnfInfo = vnfInfo;
             this.vnfdId = vnfdId;
         }
+
+        public com.nokia.cbam.lcm.v32.model.VnfInfo getVnfInfo() {
+            return vnfInfo;
+        }
     }
 }