Fixes in LCM 29/40729/2
authorDenes Nemeth <denes.nemeth@nokia.com>
Tue, 3 Apr 2018 15:32:13 +0000 (17:32 +0200)
committerDenes Nemeth <denes.nemeth@nokia.com>
Wed, 4 Apr 2018 12:08:23 +0000 (14:08 +0200)
Change-Id: I9dfdacf32970c86b595939f6cd92b6eb276ebf90
Issue-ID: VFC-728
Signed-off-by: Denes Nemeth <denes.nemeth@nokia.com>
26 files changed:
nokiav2/.gitignore
nokiav2/deployment/src/main/resources/application.properties
nokiav2/docs/development.rst [new file with mode: 0644]
nokiav2/docs/integration.rst
nokiav2/docs/so.rst [new file with mode: 0644]
nokiav2/docs/vnfintegration.rst
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/AAIRestApiProvider.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/VnfcManager.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoLifecycleManager.java [new file with mode: 0644]
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/package-info.java [new file with mode: 0644]
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcmApi.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoApi.java [new file with mode: 0644]
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/SystemFunctions.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java
nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java
nokiav2/driver/src/main/resources/self.swagger.json
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/TestAAIRestApiProvider.java
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/TestVnfcManager.java
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/TestSoLifecycleManager.java [new file with mode: 0644]
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerDefinitionConsistency.java
nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestLifecycleManager.java
nokiav2/driver/src/test/resources/application-direct.properties
nokiav2/driver/src/test/resources/application.properties
nokiav2/generatedapis/pom.xml
nokiav2/generatedapis/src/main/resources/so.vnfm.json [new file with mode: 0644]
nokiav2/generatedapis/src/main/resources/vfc.vnfdriver.swagger.json

index 88783a3..8d01eac 100644 (file)
@@ -5,3 +5,4 @@ bin
 tmp
 logs
 debug-logs
+NOTES.internal.txt
index c467e76..d52ed49 100644 (file)
@@ -60,6 +60,24 @@ skipCertificateVerification=true
 # in PEM format encoded in BASE64 to a single line
 trustedCertificates=
 
+###############################################################################
+# Configuration parameters for direct integration
+###############################################################################
+# skip hostname verification during SSL on CBAM LCN, LCM and authorization interface
+skipHostnameVerificationForAai=true
+# skip certificate verification during SSL on CBAM LCN, LCM and authorization interface
+skipCertificateVerificationForAai=true
+# the collection of trusted certificates for SSL on CBAM LCN, LCM and authorization interface
+# in PEM format encoded in BASE64 to a single line
+trustedCertificatesForAai=
+#The username to access AAI
+aaiUsername=AAI
+#The password to access AAI
+aaiPassword=AAI
+#The username to access SDC
+sdcUsername=SDC
+#The password to access SDC
+sdcPassword=SDC
 ###############################################################################
 # End of mandatory properties for driver                                      #
 ###############################################################################
diff --git a/nokiav2/docs/development.rst b/nokiav2/docs/development.rst
new file mode 100644 (file)
index 0000000..f0bcc71
--- /dev/null
@@ -0,0 +1,28 @@
+Developing the Nokia v2 SVNFM adapter
+=====================================
+
+
+Quality gate
+------------
+
+99.9 % unit test converage
+near 0 sonar issues (with the exceptions of FIXME issues)
+
+Usfull links
+------------
+
+Jenkins build bot: https://jenkins.onap.org/view/vfc/job/vfc-nfvo-driver-svnfm-nokiav2-master-drv-vnfm-nokiav2-verify-java/
+Jenkins sonar analyitcs: https://jenkins.onap.org/view/vfc/job/vfc-nfvo-driver-vnfm-svnfm-nokiav2-sonar/
+Jenkins CLM: https://jenkins.onap.org/view/vfc/job/vfc-nfvo-driver-svnfm-nokiav2-maven-clm-master/
+Jenkins daily release https://jenkins.onap.org/view/vfc/job/vfc-nfvo-driver-svnfm-nokiav2-master-drv-vnfm-nokiav2-release-version-java-daily/
+Sonar: https://sonar.onap.org/dashboard?id=org.onap.vfc.nfvo.driver.vnfm.svnfm.nokiav2%3Avfc-nfvo-driver-vnfm-svnfm-nokiav2
+Nexus IQ reports: https://nexus-iq.wl.linuxfoundation.org/assets/index.html#/management/view/application/vfc-nfvo-driver-svnfm-nokiav2
+
+Backlog
+-------
+
+- add driver to OOM based deployments
+- Solve remaining severe & moderate license issues
+- Support for operation traces in logging https://wiki.onap.org/pages/viewpage.action?pageId=20087036
+- Add CSIT using SVNFM simulator
+
index 2c02b75..303a201 100644 (file)
@@ -1,24 +1,26 @@
 Integrate ONAP with Nokia VNFM
 ==============================
 
-Prepare CBAM
-------------
+The following section describes how the Nokia VNFM can be integrated into ONAP. The integration is the easiest if the
+VNFM is installed before ONAP.
 
-* Start CBAM in ONAP network
-
- - via image: (read the CBAM installation guide)
+Prepare the VNFM
+----------------
+* Start VNFM: The VNFM must be able to communicate with the ONAP VF-C interface, the cloud and the VNF, so the VNFM must
+ have the correct network setup. The VNFM will use LCNs to notify VF-C of the executed changes, so the LCN zone of the
+ VNFM must be configured so that the VNFM is able to reach the VF-C LCN interface.
 
 * Register driver in CBAM
 
- - Log into CBAM via SSH and get keycloak admin password
+ - Log into CBAM via SSH and determine the keycloak admin password
 
   - ectl get /cbam/cluster/components/keycloak/admin_credentials/password
 
- - Log into keycloak https://<cbamIp>/auth/admin with admin username and password from previous step and change password (save the changed password)
+ - Log into keycloak https://<cbamIp>/auth/admin with admin username and password from previous step and change password (note the changed password)
  - Add a new client
 
   - set client id to onapClient
-  - change credential type to confidental
+  - change credential type to confidential
   - enable Standard Flow Enabled, Direct Access Grants Enabled, Service Accounts Enabled
   - add * for redirect URL
   - save
@@ -32,13 +34,13 @@ Prepare CBAM
   - reset password
   - assign the "user" role to the created user
 
- - Log into CBAM GUI usin the created user
+ - Log into CBAM GUI using the created user
 
   - change and note the password <onapPassword>
 
  - Add SSL certificates for all VIM connection or disable certificate verification
 
-  - For insecure
+  - For insecure (all certificates are automatically trusted)
 
    - sudo su -
    - ectl set /cbam/cluster/components/tlm/insecure_vim_connection true
@@ -48,27 +50,26 @@ Prepare CBAM
 
   - For secure: (read CBAM documentation)
 
-Prepare /ets/hosts file on your machine (optional easier to copy paste URLs)
+Prepare /ets/hosts file on your laptop (optional easier to copy paste URLs)
 ----------------------------------------------------------------------------
 
-+--------------+---------------------------------+
-| IP address   | DNS entry                       |
-+==============+=================================+
-| 1.2.3.4      | portal.api.simpledemo.onap.org  |
-+--------------+---------------------------------+
-| 1.2.3.4      | policy.api.simpledemo.onap.org  |
-+--------------+---------------------------------+
-| 1.2.3.4      | sdc.api.simpledemo.onap.org     |
-+--------------+---------------------------------+
-| 1.2.3.4      | vid.api.simpledemo.onap.org     |
-+--------------+---------------------------------+
-| 1.2.3.4      | aai.api.simpledemo.onap.org     |
-+--------------+---------------------------------+
-| 1.2.3.4      | msb.api.simpledemo.onap.org     |
-+--------------+---------------------------------+
-| 1.2.3.4      | robot.api.simpledemo.onap.org   |
-+--------------+---------------------------------+
-
++-------------------+---------------------------------+
+| IP address        | DNS entry                       |
++===================+=================================+
+| <fill IP address> | portal.api.simpledemo.onap.org  |
++-------------------+---------------------------------+
+| <fill IP address> | policy.api.simpledemo.onap.org  |
++-------------------+---------------------------------+
+| <fill IP address> | sdc.api.simpledemo.onap.org     |
++-------------------+---------------------------------+
+| <fill IP address> | vid.api.simpledemo.onap.org     |
++-------------------+---------------------------------+
+| <fill IP address> | aai.api.simpledemo.onap.org     |
++-------------------+---------------------------------+
+| <fill IP address> | msb.api.simpledemo.onap.org     |
++-------------------+---------------------------------+
+| <fill IP address> | robot.api.simpledemo.onap.org   |
++-------------------+---------------------------------+
 
 Add the VNFM driver to ONAP
 ---------------------------
@@ -85,7 +86,7 @@ Add the VNFM driver to ONAP
 - Create tenant (may already exist) (repeat for all tenants planed to be used within the cloud)
 
  + tool: Postman
- + change tenant id, region id owner id
+ + change tenantId, cloudRegion and cloudOwner
  + method: PUT
  + url: https://aai.api.simpledemo.onap.org:8443/aai/v11/cloud-infrastructure/cloud-regions/cloud-region/<cloudOwner>/<cloudRegion>/tenants/tenant/<tenantId>
  + Headers
@@ -99,7 +100,7 @@ Add the VNFM driver to ONAP
 
   - change tenant id, region id owner id and tenant name
 
-- Register the VNFM as external system (repeat for all cloud planed to be used)
+- Register the VNFM as external system (repeat for all clouds planed to be used)
 
  - Visit MSB http://msb.api.simpledemo.onap.org:9518/api/aai-esr-server/v1/vims
 
@@ -135,14 +136,12 @@ Add the VNFM driver to ONAP
   - visit http://msb.api.simpledemo.onap.org:9518/api/aai-esr-server/v1/vnfms and search for the previously registered VNFM
   - note the id field <vnfmId>
 
- - Download the cbam driver into ONAP multi service node
- - Load the image into docker and note the image identifier <imageId>
-
-.. code-block:: console
-
-   docker load -i /tmp/nokia.img
+Configure the SVNFM driver (generic)
+------------------------------------
 
-Start the driver (fill in values)
+ - Download the CBAM SVNFM driver
+   - docker pull https://nexus.onap.org/content/sites/raw/onap/vfc/nfvo/svnfm/nokiav2:1.1.0-STAGING-latest
+ - Start the driver (fill in values)
 
 .. code-block:: console
 
@@ -154,3 +153,9 @@ Start the driver (fill in values)
    export CBAM_USERNAME=<onapUsername>
    docker run --name vfc_nokia -p 8089:8089 -e "MSB_IP=$MULTI_NODE_IP" -e "CONFIGURE=kuku" -e "EXTERNAL_IP=$MULTI_NODE_IP" -e "CBAM_CATALOG_URL=https://$CBAM_IP:443/api/catalog/adapter/" -e "CBAM_LCN_URL=https://$CBAM_IP:443/vnfm/lcn/v3/" -e "CBAM_KEYCLOAK_URL=https://$CBAM_IP:443/auth/" -e "CBAM_USERNAME=$CBAM_USERNAME" -e "CBAM_PASSWORD=$CBAM_PASSWORD" -e "VNFM_ID=$VNFM_ID" -d --stop-timeout 300 $IMAGE_ID
 
+Configure the SVNFM driver (ONAP demo environment)
+--------------------------------------------------
+ - Configure the already running instance
+ - docker exec -it `docker ps | grep nokiav2 | awk '{print $1}'` /bin/bash
+ - Edit /service/application.properties
+ - Fill values for cbamCatalogUrl, cbamLcnUrl, cbamKeyCloakBaseUrl, cbamUsername, cbamPassword, vnfmId
diff --git a/nokiav2/docs/so.rst b/nokiav2/docs/so.rst
new file mode 100644 (file)
index 0000000..1f18d94
--- /dev/null
@@ -0,0 +1,16 @@
+Integration directly through SO
+===============================
+
+
+Requirements on the VNF package
+-------------------------------
+
+- the VNFD must have a instantiation level named default
+- each VDU must have a corresponding software image named <vduname>_image
+- the VNF integrator must use the availability zones to specify the location of the VNFCs. One availability zone
+will be defined for each VDU
+
+Limitations of the current release
+----------------------------------
+
+- at least one server instance mapping for each VDU must be supplied in the VNF activation request
\ No newline at end of file
index 62674e5..a846b26 100644 (file)
@@ -6,13 +6,14 @@ Automatic
 
 - Visit http://msb.api.simpledemo.onap.org/api/NokiaSVNFM/v1/convert
 - Select the CBAM package to be converted into an ONAP package
-- Click on upload button and the ONAP package will be donwloaded 
+- Click on upload button and the ONAP package will be downloaded
 
 
 Manual
 ------
 
-- the VNF must declare the externalVnfmId and onapCsarId as modifyable attribute in CBAM package (value will be filled out by CBAM)
+- the VNF must declare the externalVnfmId and onapCsarId as modifyable attribute in CBAM package. Each should have
+a default value. (The concrete value will be filled out by CBAM)
 - each operation must declare a jobId additional parameter in CBAM package (value will be filled out by CBAM)
 - the heal operation must declare the jobId, vmName and action parameters in CBAM package (values will be filled out by CBAM)
 - each operation (including built-in) must include the following section as the last pre_action (all JS are provided by CBAM)
index 14bdea1..08bf2c4 100644 (file)
@@ -23,10 +23,8 @@ import org.onap.aai.api.CloudInfrastructureApi;
 import org.onap.aai.api.ExternalSystemApi;
 import org.onap.aai.api.NetworkApi;
 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.MsbApiProvider;
-import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.Conditions;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Conditional;
 import org.springframework.stereotype.Component;
 
 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager.SERVICE_NAME;
@@ -36,7 +34,6 @@ import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrati
  * Handles authentication and mandatory parameters.
  */
 @Component
-@Conditional(value = Conditions.UseForDirect.class)
 public class AAIRestApiProvider {
     private final MsbApiProvider msbApiProvider;
     private final AaiSecurityProvider aaiSecurityProvider;
index bc31f4f..db65d2f 100644 (file)
@@ -27,6 +27,8 @@ import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.context.annotation.Conditional;
 import org.springframework.stereotype.Component;
 
+import static com.google.common.base.Splitter.on;
+import static com.google.common.collect.Lists.newArrayList;
 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.SEPARATOR;
 
 /**
@@ -46,6 +48,14 @@ public class VnfcManager extends AbstractManager {
         return vnfId + SEPARATOR + cbamVnfcId;
     }
 
+    /**
+     * @param onapVnfcId the identifier of the VNFC in AAI
+     * @return the identifier of the VNFC in CBAM
+     */
+    public static String buildCbamId(String onapVnfcId) {
+        return newArrayList(on(SEPARATOR).split(onapVnfcId)).get(1);
+    }
+
     @Override
     protected Logger getLogger() {
         return logger;
diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoLifecycleManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoLifecycleManager.java
new file mode 100644 (file)
index 0000000..c6e07e8
--- /dev/null
@@ -0,0 +1,327 @@
+/*
+ * Copyright 2016-2017, Nokia Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so;
+
+
+import com.nokia.cbam.lcm.v32.model.*;
+import com.nokia.cbam.lcm.v32.model.VimInfo;
+import java.util.ArrayList;
+import java.util.List;
+import javax.servlet.http.HttpServletResponse;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VimInfoProvider;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.AdditionalParameters;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.JobManager;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager;
+import org.onap.vnfmadapter.so.model.*;
+import org.onap.vnfmdriver.model.ExtVirtualLinkInfo;
+import org.onap.vnfmdriver.model.*;
+import org.onap.vnfmdriver.model.VnfInfo;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Component;
+
+import static java.util.Optional.of;
+
+import static com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum.*;
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.direct.notification.VnfcManager.buildCbamId;
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION;
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager.getVnfdIdFromModifyableAttributes;
+import static org.onap.vnfmadapter.so.model.SoJobStatus.*;
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.springframework.util.StringUtils.isEmpty;
+
+/**
+ * Responsible for providing access to AAI APIs.
+ * Handles authentication and mandatory parameters.
+ */
+
+@Component
+public class SoLifecycleManager {
+    private static Logger logger = getLogger(SoLifecycleManager.class);
+    private final LifecycleManager lifecycleManager;
+    private final VimInfoProvider vimInfoProvider;
+    private final CbamRestApiProvider cbamRestApiProvider;
+    private final JobManager jobManager;
+
+    @Autowired
+    SoLifecycleManager(LifecycleManager lifecycleManager, VimInfoProvider vimInfoProvider, CbamRestApiProvider cbamRestApiProvider, JobManager jobManager) {
+        this.lifecycleManager = lifecycleManager;
+        this.vimInfoProvider = vimInfoProvider;
+        this.cbamRestApiProvider = cbamRestApiProvider;
+        this.jobManager = jobManager;
+    }
+
+    /**
+     * Creates the VNF in SO terminology
+     *
+     * @param vnfmId  the identifier of the VNFM
+     * @param request the VNF creation request
+     * @return the VNF creation response
+     */
+    public SoVnfCreationResponse create(String vnfmId, SoVnfCreationRequest request) {
+        SoVnfCreationResponse response = new SoVnfCreationResponse();
+        LifecycleManager.VnfCreationResult result = lifecycleManager.create(vnfmId, request.getCsarId(), request.getName(), request.getDescription());
+        response.setVnfId(result.getVnfInfo().getId());
+        return response;
+    }
+
+    /**
+     * Activate the VNF in SO terminology
+     *
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param soRequest    the VNF activation request
+     * @param httpResponse the HTTP response
+     * @return the job handler of the VNF activation
+     */
+    public SoJobHandler activate(String vnfmId, String vnfId, SoVnfActivationRequest soRequest, HttpServletResponse httpResponse) {
+        AdditionalParameters additionalParameters = new AdditionalParameters();
+        additionalParameters.setAdditionalParams(buildAdditionalParameters(soRequest.getAdditionalParams()));
+        String vimId = soRequest.getVimId();
+        org.onap.vnfmdriver.model.VimInfo vimInfo = vimInfoProvider.getVimInfo(vimId);
+        additionalParameters.setVimType(vimTypeHeuristic(vimInfo.getUrl()));
+        processVdus(soRequest, additionalParameters, vimId);
+        if (isEmpty(additionalParameters.getInstantiationLevel())) {
+            additionalParameters.setInstantiationLevel("default");
+        }
+        processNetworks(soRequest, additionalParameters, vimId);
+        processZones(soRequest, additionalParameters, vimId);
+        com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst();
+        String onapVnfdId = getVnfdIdFromModifyableAttributes(cbamVnfInfo);
+        VnfInfo vnfInfo = lifecycleManager.queryVnf(vnfmId, vnfId);
+        List<ExtVirtualLinkInfo> externalVirtualLinks = new ArrayList<>();
+        VnfInstantiateResponse instantiate = lifecycleManager.instantiate(vnfmId, externalVirtualLinks, httpResponse, soRequest.getAdditionalParams(), additionalParameters, vnfId, onapVnfdId, vnfInfo.getVnfdId());
+        return buildJobHandler(instantiate.getJobId());
+    }
+
+    /**
+     * Scale the VNF
+     *
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param soRequest    the VNF scale request
+     * @param httpResponse the HTTP response
+     * @return the job handler of the VNF activation
+     */
+    public SoJobHandler scale(String vnfmId, String vnfId, SoVnfScaleRequest soRequest, HttpServletResponse httpResponse) {
+        org.onap.vnfmdriver.model.VnfScaleRequest driverRequest = new org.onap.vnfmdriver.model.VnfScaleRequest();
+        driverRequest.setAdditionalParam(buildAdditionalParameters(soRequest.getAdditionalParams()));
+        driverRequest.setAspectId(soRequest.getAspectId());
+        driverRequest.setNumberOfSteps(soRequest.getSteps().toString());
+        driverRequest.setType(soRequest.getDirection() == SoScaleDirection.IN ? org.onap.vnfmdriver.model.ScaleDirection.IN : org.onap.vnfmdriver.model.ScaleDirection.OUT);
+        return buildJobHandler(lifecycleManager.scaleVnf(vnfmId, vnfId, driverRequest, httpResponse).getJobId());
+    }
+
+    /**
+     * Heal the VNF
+     *
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param request      the VNF heal request
+     * @param httpResponse the HTTP response
+     * @return the job handler of the VNF activation
+     */
+    public SoJobHandler heal(String vnfmId, String vnfId, SoVnfHealRequest request, HttpServletResponse httpResponse) {
+        org.onap.vnfmdriver.model.VnfHealRequest vnfHealRequest = new org.onap.vnfmdriver.model.VnfHealRequest();
+        VnfHealRequestAffectedvm affectedVm = new VnfHealRequestAffectedvm();
+        affectedVm.setVimid("notUsedByDriver");
+        affectedVm.setVduid("notUsedByDriver");
+        affectedVm.setVmname("unknown");
+        vnfHealRequest.setAffectedvm(affectedVm);
+        vnfHealRequest.setAction("heal");
+        return buildJobHandler(lifecycleManager.healVnf(vnfmId, vnfId, vnfHealRequest, of(buildCbamId(request.getVnfcId())), httpResponse).getJobId());
+    }
+
+    /**
+     * Deactivate the VNF
+     *
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param soRequest    the VNF deactivation request
+     * @param httpResponse the HTTP response
+     * @return the job handler of the VNF activation
+     */
+    public SoJobHandler deactivate(String vnfmId, String vnfId, SoVnfTerminationRequest soRequest, HttpServletResponse httpResponse) {
+        VnfTerminateRequest driverRequest = new VnfTerminateRequest();
+        driverRequest.setTerminationType(soRequest.getMode() == SoTerminationMode.FORCEFUL ? VnfTerminationType.FORCEFUL : VnfTerminationType.GRACEFUL);
+        driverRequest.setGracefulTerminationTimeout(soRequest.getGracefulTerminationTimeoutInMs().toString());
+        return buildJobHandler(lifecycleManager.terminateAndDelete(vnfmId, vnfId, driverRequest, httpResponse).getJobId());
+    }
+
+    /**
+     * Delete the VNF
+     *
+     * @param vnfmId the identifier of the VNFM
+     * @param vnfId  the identifier of the VNF
+     * @return the job handler of the VNF activation
+     */
+    public void delete(String vnfmId, String vnfId) {
+        lifecycleManager.deleteVnf(vnfmId, vnfId);
+    }
+
+    /**
+     * Execute a custom operation on a VNF
+     *
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param request      the VNF custom
+     * @param httpResponse the HTTP response
+     * @return the job handler of the VNF activation
+     */
+    public SoJobHandler customOperation(String vnfmId, String vnfId, SoVnfCustomOperation request, HttpServletResponse httpResponse) {
+        String operationId = request.getOperationId();
+        CustomOperationRequest cbamRequest = new CustomOperationRequest();
+        cbamRequest.setAdditionalParams(buildAdditionalParameters(request.getAdditionalParams()));
+        return buildJobHandler(lifecycleManager.customOperation(vnfmId, vnfId, operationId, request.getAdditionalParams(), httpResponse).getJobId());
+    }
+
+    /**
+     * @param jobId  the identifier of the job
+     * @param vnfmId the identifier of the VNFM
+     * @return the details of the job
+     */
+    public SoJobDetail getJobDetails(String vnfmId, String jobId) {
+        SoJobDetail jobDetail = new SoJobDetail();
+        jobDetail.setJobId(jobId);
+        JobStatus currentStatus = jobManager.getJob(vnfmId, jobId).getResponseDescriptor().getStatus();
+        if (JobStatus.STARTED.equals(currentStatus)) {
+            jobDetail.setStatus(STARTED);
+        } else if (JobStatus.PROCESSING.equals(currentStatus)) {
+            jobDetail.setStatus(STARTED);
+        } else if (JobStatus.FINISHED.equals(currentStatus)) {
+            jobDetail.setStatus(FINISHED);
+        } else if (JobStatus.TIMEOUT.equals(currentStatus)) {
+            jobDetail.setStatus(FAILED);
+        } else {//ERROR
+            jobDetail.setStatus(FAILED);
+        }
+        return jobDetail;
+    }
+
+    private VimInfo.VimInfoTypeEnum vimTypeHeuristic(String url) {
+        if (url.contains("/v3")) {
+            return OPENSTACK_V3_INFO;
+        } else if (url.contains("/v2")) {
+            return OPENSTACK_V2_INFO;
+        } else {
+            return VMWARE_VCLOUD_INFO;
+        }
+    }
+
+    private Object buildAdditionalParameters(Object additionalParams) {
+        return additionalParams;
+    }
+
+    private SoJobHandler buildJobHandler(String jobId) {
+        SoJobHandler jobHandler = new SoJobHandler();
+        jobHandler.setJobId(jobId);
+        return jobHandler;
+    }
+
+    private void processVdus(SoVnfActivationRequest request, AdditionalParameters additionalParameters, String vimId) {
+        if (request.getVduMappings() != null) {
+            for (SoVduMapping vduMapping : request.getVduMappings()) {
+                VimComputeResourceFlavour flavour = new VimComputeResourceFlavour();
+                flavour.setVimId(vimId);
+                flavour.setVnfdVirtualComputeDescId(vduMapping.getVduId());
+                flavour.setResourceId(vduMapping.getFlavourId());
+                additionalParameters.getComputeResourceFlavours().add(flavour);
+                VimSoftwareImage image = new VimSoftwareImage();
+                image.setVimId(vimId);
+                image.setResourceId(vduMapping.getImageId());
+                image.setVnfdSoftwareImageId(vduMapping.getVduId() + CbamUtils.SEPARATOR + "image");
+                additionalParameters.getSoftwareImages().add(image);
+            }
+        }
+    }
+
+    private void processNetworks(SoVnfActivationRequest request, AdditionalParameters additionalParameters, String vimId) {
+        if (request.getNetworkMappings() != null) {
+            for (SoNetworkMapping networkMapping : request.getNetworkMappings()) {
+                ExtVirtualLinkData extVirtualLinkData = createExtVirtualLinkData(additionalParameters, networkMapping.getVldId());
+                extVirtualLinkData.setVimId(vimId);
+                extVirtualLinkData.setResourceId(networkMapping.getNetworkProviderId());
+                if (networkMapping.getAssignedAddresses() != null) {
+                    for (SoAssignedAddresses assignedAddresses : networkMapping.getAssignedAddresses()) {
+                        VnfExtCpData extCpData = createExtVirtualLinkData(extVirtualLinkData.getExtCps(), assignedAddresses.getCpdId());
+                        addMissing(extCpData, assignedAddresses.getIpAddress());
+                    }
+                }
+            }
+        }
+    }
+
+    private void processZones(SoVnfActivationRequest request, AdditionalParameters additionalParameters, String vimId) {
+        if (request.getServerMappings() != null) {
+            for (SoServerMapping serverMapping : request.getServerMappings()) {
+                ZoneInfo zone = locateOrCreateZone(additionalParameters.getZones(), serverMapping.getVduId());
+                zone.setResourceId(serverMapping.getAvailabilityZoneId());
+                zone.setVimId(vimId);
+            }
+        }
+    }
+
+    private ZoneInfo locateOrCreateZone(List<ZoneInfo> zones, String vduId) {
+        if (zones != null) {
+            for (ZoneInfo zone : zones) {
+                if (zone.getId().equals(vduId)) {
+                    return zone;
+                }
+            }
+        }
+        ZoneInfo zoneInfo = new ZoneInfo();
+        zoneInfo.setId(vduId);
+        zones.add(zoneInfo);
+        return zoneInfo;
+    }
+
+    private void addMissing(VnfExtCpData extCpData, String ipAddress) {
+        if (extCpData.getAddresses() == null) {
+            extCpData.setAddresses(new ArrayList<>());
+        }
+        for (NetworkAddress networkAddress : extCpData.getAddresses()) {
+            if (ipAddress.equals(networkAddress.getIp())) {
+                return;
+            }
+        }
+        NetworkAddress address = new NetworkAddress();
+        address.setIp(ipAddress);
+        extCpData.getAddresses().add(address);
+    }
+
+    private VnfExtCpData createExtVirtualLinkData(List<VnfExtCpData> extCps, String cpdId) {
+        if (extCps != null) {
+            for (VnfExtCpData extCp : extCps) {
+                if (extCp.getCpdId().equals(cpdId)) {
+                    return extCp;
+                }
+            }
+        }
+        VnfExtCpData extCp = new VnfExtCpData();
+        extCp.setCpdId(cpdId);
+        extCps.add(extCp);
+        return extCp;
+    }
+
+    private ExtVirtualLinkData createExtVirtualLinkData(AdditionalParameters additionalParameters, String virtualLinkId) {
+        ExtVirtualLinkData nonExistingVl = new ExtVirtualLinkData();
+        nonExistingVl.setExtVirtualLinkId(virtualLinkId);
+        additionalParameters.getExtVirtualLinks().add(nonExistingVl);
+        return nonExistingVl;
+    }
+}
\ No newline at end of file
diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/package-info.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/package-info.java
new file mode 100644 (file)
index 0000000..0e29b92
--- /dev/null
@@ -0,0 +1,20 @@
+/*
+ * Copyright 2016-2017, Nokia Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * Handles information exchange with SO
+ */
+package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so;
index f7c9ed1..9214802 100644 (file)
@@ -73,9 +73,9 @@ public class LcmApi {
     /**
      * Terminate the VNF (defined further in the VF-C driver integration documentation)
      *
-     * @param request       the instantiation request
+     * @param request       the termination request
      * @param vnfmId        the identifier of the VNFM
-     * @param vnfInstanceId the identifer of the VNF
+     * @param vnfInstanceId the identifier of the VNF
      * @param httpResponse  the HTTP response
      * @return the job representing the VNF termination operation
      */
@@ -90,7 +90,7 @@ public class LcmApi {
      * Query the VNF (defined further in the VF-C driver integration documentation)
      *
      * @param vnfmId        the identifier of the VNFM
-     * @param vnfInstanceId the identifer of the VNF
+     * @param vnfInstanceId the identifier of the VNF
      * @param httpResponse  the HTTP response
      * @return the VNF info
      */
@@ -104,7 +104,7 @@ public class LcmApi {
     /**
      * Query the job (defined further in the VF-C driver integration documentation)
      *
-     * @param jobId        the identifer of the job
+     * @param jobId        the identifier of the job
      * @param vnfmId       the identifier of the VNFM
      * @param httpResponse the HTTP response
      * @return the instantiated VNF info
diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoApi.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoApi.java
new file mode 100644 (file)
index 0000000..b2c833b
--- /dev/null
@@ -0,0 +1,175 @@
+/*
+ * Copyright 2016-2017, Nokia Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.restapi;
+
+import javax.servlet.http.HttpServletResponse;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so.SoLifecycleManager;
+import org.onap.vnfmadapter.so.model.*;
+import org.slf4j.Logger;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Controller;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.ResponseBody;
+
+import static javax.servlet.http.HttpServletResponse.SC_CREATED;
+
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.DriverProperties.BASE_URL;
+import static org.slf4j.LoggerFactory.getLogger;
+import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE;
+import static org.springframework.web.bind.annotation.RequestMethod.*;
+
+/**
+ * Responsible for providing the Nokia sVNFM REST APIs
+ */
+@Controller
+@RequestMapping(value = BASE_URL + "/so")
+public class SoApi {
+    private static Logger logger = getLogger(SoApi.class);
+
+    private final SoLifecycleManager soLifecycleManager;
+
+    //private final LifecycleManager d;
+    @Autowired
+    SoApi(SoLifecycleManager lifecycleManager) {
+        this.soLifecycleManager = lifecycleManager;
+    }
+
+    /**
+     * Create the VNF
+     *
+     * @param request      the creation request
+     * @param vnfmId       the identifier of the VNFM
+     * @param httpResponse the HTTP response
+     * @return the descriptor of the created VNF
+     */
+    @RequestMapping(value = "/{vnfmId}/vnfs", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public SoVnfCreationResponse createVnf(@RequestBody SoVnfCreationRequest request, @PathVariable("vnfmId") String vnfmId, HttpServletResponse httpResponse) {
+        logger.info("REST: Create the VNF");
+        SoVnfCreationResponse response = soLifecycleManager.create(vnfmId, request);
+        httpResponse.setStatus(SC_CREATED);
+        return response;
+    }
+
+    /**
+     * Activate the VNF
+     *
+     * @param request      the activation request
+     * @param vnfmId       the identifier of the VNFM
+     * @param httpResponse the HTTP response
+     * @return the descriptor of the created VNF
+     */
+    @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public SoJobHandler activateVnf(@RequestBody SoVnfActivationRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) {
+        logger.info("REST: Create the VNF");
+        return soLifecycleManager.activate(vnfmId, vnfId, request, httpResponse);
+    }
+
+    /**
+     * Execute custom operation on the VNF
+     *
+     * @param request      the custom operation request
+     * @param vnfmId       the identifier of the VNFM
+     * @param httpResponse the HTTP response
+     * @return the descriptor of the created VNF
+     */
+    @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}/customOperation", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public SoJobHandler executeCustomOperation(@RequestBody SoVnfCustomOperation request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) {
+        logger.info("REST: Create the VNF");
+        return soLifecycleManager.customOperation(vnfmId, vnfId, request, httpResponse);
+    }
+
+    /**
+     * Terminate the VNF
+     *
+     * @param request      the termination request
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param httpResponse the HTTP response
+     * @return the job representing the VNF termination operation
+     */
+    @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}/terminate", method = POST, produces = APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public SoJobHandler deactivateVnf(@RequestBody SoVnfTerminationRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) {
+        logger.info("REST: Deactivate VNF");
+        return soLifecycleManager.deactivate(vnfmId, vnfId, request, httpResponse);
+    }
+
+    /**
+     * Delete the VNF
+     *
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param httpResponse the HTTP response
+     */
+    @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}", method = DELETE)
+    public void deleteVnf(@PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) {
+        logger.info("REST: Delete VNF");
+        soLifecycleManager.delete(vnfmId, vnfId);
+        httpResponse.setStatus(HttpServletResponse.SC_NO_CONTENT);
+    }
+
+    /**
+     * Query the job
+     *
+     * @param jobId        the identifier of the job
+     * @param vnfmId       the identifier of the VNFM
+     * @param httpResponse the HTTP response
+     * @return the instantiated VNF info
+     */
+    @RequestMapping(value = "/{vnfmId}/jobs/{jobId}", method = GET, produces = APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public SoJobDetail getJob(@PathVariable("vnfmId") String vnfmId, @PathVariable("jobId") String jobId, HttpServletResponse httpResponse) {
+        logger.debug("REST: Query the job");
+        return soLifecycleManager.getJobDetails(vnfmId, jobId);
+    }
+
+    /**
+     * Scale the VNF (defined further in the VF-C driver integration documentation)
+     *
+     * @param request      the scaling request
+     * @param vnfmId       the identifier of the VNFM
+     * @param vnfId        the identifier of the VNF
+     * @param httpResponse the HTTP response
+     * @return the job representing the scaling operation
+     */
+    @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}/scale", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public SoJobHandler scaleVnf(@RequestBody SoVnfScaleRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfId, HttpServletResponse httpResponse) {
+        logger.info("REST: Scale the VNF");
+        return soLifecycleManager.scale(vnfmId, vnfId, request, httpResponse);
+    }
+
+    /**
+     * Heal the VNF (defined further in the VF-C driver integration documentation)
+     *
+     * @param request       the healing request
+     * @param vnfmId        the identifier of the VNFM
+     * @param vnfInstanceId the identifier of the VNF
+     * @param httpResponse  the HTTP response
+     * @return the job representing the healing operation
+     */
+    @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}/heal", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE)
+    @ResponseBody
+    public SoJobHandler healVnf(@RequestBody SoVnfHealRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfInstanceId, HttpServletResponse httpResponse) {
+        logger.info("REST: Heal the VNF");
+        return soLifecycleManager.heal(vnfmId, vnfInstanceId, request, httpResponse);
+    }
+}
index b67c786..22d4c20 100644 (file)
@@ -67,7 +67,7 @@ public class SystemFunctions {
      * operating system and may be larger.  For example, many
      * operating systems measure time in units of tens of
      * milliseconds.
-     * <p>
+     *
      * <p> See the description of the class <code>Date</code> for
      * a discussion of slight discrepancies that may arise between
      * Unable to load /unittests/missing     * "computer time" and coordinated universal time (UTC).
index f585a6a..1ec129e 100644 (file)
@@ -24,7 +24,6 @@ import java.util.*;
  */
 public class AdditionalParameters {
     private VimInfoTypeEnum vimType;
-    private String domain;
     private String instantiationLevel;
     private List<VimComputeResourceFlavour> computeResourceFlavours = new ArrayList<>();
     private List<ZoneInfo> zones = new ArrayList<>();
@@ -66,20 +65,6 @@ public class AdditionalParameters {
         this.vimType = vimType;
     }
 
-    /**
-     * @return the domain of the OpenStack (required for v3 API)
-     */
-    public String getDomain() {
-        return domain;
-    }
-
-    /**
-     * @param domain the domain of the OpenStack (required for v3 API)
-     */
-    public void setDomain(String domain) {
-        this.domain = domain;
-    }
-
     /**
      * @return the flavours to be used for the VNF
      */
@@ -180,7 +165,6 @@ public class AdditionalParameters {
         if (o == null || getClass() != o.getClass()) return false;
         AdditionalParameters that = (AdditionalParameters) o;
         return vimType == that.vimType &&
-                Objects.equals(domain, that.domain) &&
                 Objects.equals(instantiationLevel, that.instantiationLevel) &&
                 Objects.equals(computeResourceFlavours, that.computeResourceFlavours) &&
                 Objects.equals(zones, that.zones) &&
@@ -194,14 +178,13 @@ public class AdditionalParameters {
     @Override
     public int hashCode() {
 
-        return Objects.hash(vimType, domain, instantiationLevel, computeResourceFlavours, zones, softwareImages, extManagedVirtualLinks, externalConnectionPointAddresses, extVirtualLinks, additionalParams);
+        return Objects.hash(vimType, instantiationLevel, computeResourceFlavours, zones, softwareImages, extManagedVirtualLinks, externalConnectionPointAddresses, extVirtualLinks, additionalParams);
     }
 
     @Override
     public String toString() {
         return "AdditionalParameters{" +
                 "vimType=" + vimType +
-                ", domain='" + domain + '\'' +
                 ", instantiationLevel='" + instantiationLevel + '\'' +
                 ", computeResourceFlavours=" + computeResourceFlavours +
                 ", zones=" + zones +
index 94ab240..5cd1105 100644 (file)
@@ -30,7 +30,6 @@ 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;
@@ -113,6 +112,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 +126,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 +160,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 +199,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 +211,19 @@ 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());
+    @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);
+        GrantVNFResponseVim vim = grantManager.requestGrantForInstantiate(vnfmId, vnfId, vimId, onapVnfdId, additionalParameters.getInstantiationLevel(), vnfdContent, jobInfo.getJobId());
         if (vim.getVimId() == null) {
             throw buildFatalFailure(logger, "VF-C did not send VIM identifier in grant response");
         }
         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());
@@ -328,7 +335,7 @@ public class LifecycleManager {
         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,44 +407,71 @@ 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 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);
+            }
         }
     }
 
-    private void deleteVnf(String vnfmId, String vnfId) {
+    /**
+     * 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();
         logger.info("The VNF with {} identifier has been deleted", vnfId);
@@ -450,10 +484,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 +492,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;
@@ -566,6 +600,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 +653,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;
+        }
     }
 }
index f8d24a0..6404150 100644 (file)
     },
     "description": "ONAP Nokia CBAM Driver API.",
     "title": "ONAP Nokia CBAM Driver API",
-    "version": "1.0.0"
+    "version": "1.1.0"
   },
   "definitions": {
+    "SoJobHandler": {
+      "type": "object",
+      "properties": {
+        "jobId": {
+          "required": true,
+          "description": "The identifier of the job",
+          "type": "string"
+        }
+      }
+    },
+    "SoJobStatus": {
+      "description": "The status of the job",
+      "type": "string",
+      "enum": [
+        "started",
+        "finished",
+        "failed"
+      ]
+    },
+    "SoJobDetail": {
+      "allOf": [
+        {
+          "$ref": "#/definitions/SoJobHandler"
+        },
+        {
+          "type": "object",
+          "properties": {
+            "status": {
+              "required": true,
+              "description": "The status of the job",
+              "$ref": "#/definitions/SoJobStatus"
+            },
+            "description": {
+              "required": true,
+              "description": "The description of the current state of the job",
+              "type": "string"
+            }
+          }
+        }
+      ]
+    },
+    "SoVnfCreationRequest": {
+      "type": "object",
+      "properties": {
+        "name": {
+          "required": true,
+          "description": "The name of the VNF",
+          "type": "string"
+        },
+        "csarId": {
+          "required": true,
+          "description": "The identifier of the VNF package in SDC",
+          "type": "string"
+        },
+        "description": {
+          "required": false,
+          "description": "The description of the VNF",
+          "type": "string"
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoVnfCreationResponse": {
+      "type": "object",
+      "properties": {
+        "vnfId": {
+          "required": true,
+          "description": "The identifier of the created VNF",
+          "type": "string"
+        }
+      }
+    },
+    "SoVduMapping": {
+      "type": "object",
+      "properties": {
+        "vduId": {
+          "required": true,
+          "description": "The identifier of the VDU within the VNF package",
+          "type": "string"
+        },
+        "imageId": {
+          "required": true,
+          "description": "The provider id of the image to be used for the VDU",
+          "type": "string"
+        },
+        "flavourId": {
+          "required": true,
+          "description": "The provider id of the flavour to be used for the VDU",
+          "type": "string"
+        }
+      }
+    },
+    "SoServerMapping": {
+      "type": "object",
+      "description": "Maps a server instance to a VDU and availability zone",
+      "properties": {
+        "vduId": {
+          "required": true,
+          "description": "The identifier of the VDU",
+          "type": "string"
+        },
+        "availabilityZoneId": {
+          "required": false,
+          "description": "The provider id of the availability zone to be used for the server instance",
+          "type": "string"
+        }
+      }
+    },
+    "SoAssignedAddresses": {
+      "type": "object",
+      "properties": {
+        "cpdId": {
+          "required": true,
+          "description": "The identifier of the connection point descriptor",
+          "type": "string"
+        },
+        "ipAddress": {
+          "required": true,
+          "description": "The IP address to be used",
+          "type": "string"
+        }
+      }
+    },
+    "SoNetworkMapping": {
+      "type": "object",
+      "properties": {
+        "vldId": {
+          "required": true,
+          "description": "The identifier of the network in the VNF package",
+          "type": "string"
+        },
+        "networkProviderId": {
+          "required": true,
+          "description": "The provider id of the network be used for the given purpose",
+          "type": "string"
+        },
+        "assignedAddresses": {
+          "required": true,
+          "description": "The assigned network addresses",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/SoAssignedAddresses"
+          }
+        }
+      }
+    },
+    "SoVnfActivationRequest": {
+      "type": "object",
+      "properties": {
+        "vimId": {
+          "required": true,
+          "type": "string",
+          "description": "The identifier of the VIM on which the VNF is to be instantiated"
+        },
+        "serverMappings": {
+          "required": true,
+          "description": "The server mappings",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/SoServerMapping"
+          }
+        },
+        "vduMappings": {
+          "required": true,
+          "description": "The VDU mappings",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/SoVduMapping"
+          }
+        },
+        "networkMappings": {
+          "required": true,
+          "description": "The network mappings",
+          "type": "array",
+          "items": {
+            "$ref": "#/definitions/SoNetworkMapping"
+          }
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoScaleDirection": {
+      "description": "The direction of the scale",
+      "type": "string",
+      "enum": [
+        "in",
+        "out"
+      ]
+    },
+    "SoVnfScaleRequest": {
+      "type": "object",
+      "properties": {
+        "aspectId": {
+          "type": "string",
+          "description": "The identifier of the scaling aspect in the VNF package"
+        },
+        "steps": {
+          "type": "integer",
+          "description": "The expected absolute scale level"
+        },
+        "direction": {
+          "required": true,
+          "description": "The direction of the scale",
+          "$ref": "#/definitions/SoScaleDirection"
+        },
+        "serverMappings": {
+          "required": true,
+          "description": "The server mappings",
+          "items": {
+            "$ref": "#/definitions/SoServerMapping"
+          }
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoVnfCustomOperation": {
+      "type": "object",
+      "properties": {
+        "operationId": {
+          "required": true,
+          "type": "string",
+          "description": "The identifier of the custom operation"
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoVnfHealRequest": {
+      "type": "object",
+      "properties": {
+        "vnfcId": {
+          "type": "string",
+          "description": "The identifier of the VNFC to be healed"
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoTerminationMode": {
+      "description": "The way in which the VNF is terminated",
+      "type": "string",
+      "enum": [
+        "forceful",
+        "graceful"
+      ]
+    },
+    "SoVnfTerminationRequest": {
+      "type": "object",
+      "properties": {
+        "mode": {
+          "required": true,
+          "description": "The VNF termination mode",
+          "$ref": "#/definitions/SoTerminationMode"
+        },
+        "gracefulTerminationTimeoutInMs": {
+          "required": false,
+          "type": "integer",
+          "description": "The timeout for graceful termination. After the timeout has expired forceful termination is attempted."
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
     "JobDetailInfo": {
       "properties": {
         "jobId": {
       ],
       "type": "string"
     },
-    "extVirtualLinkInfo":{
-        "type": "object",
-        "properties": {
-          "resourceSubnetId": {
-            "type": "string",
-            "description": "The provider id of the subnet"
-          },
-          "vlInstanceId": {
-            "type": "string",
-            "description" : "The identifier of the virtual link"
-          },
-          "resourceId": {
-            "type": "string",
-            "description": "The provider id of the network"
-          },
-          "cpdId": {
-            "type": "string",
-            "description": "The identifier of the connection point descriptor"
-          },
-          "vim": {
-            "type": "object",
-            "properties": {
-               "vimid": {
-                  "type": "string",
-                  "description": "The identifier of the VIM"
-               }
+    "extVirtualLinkInfo": {
+      "type": "object",
+      "properties": {
+        "resourceSubnetId": {
+          "type": "string",
+          "description": "The provider id of the subnet"
+        },
+        "vlInstanceId": {
+          "type": "string",
+          "description": "The identifier of the virtual link"
+        },
+        "resourceId": {
+          "type": "string",
+          "description": "The provider id of the network"
+        },
+        "cpdId": {
+          "type": "string",
+          "description": "The identifier of the connection point descriptor"
+        },
+        "vim": {
+          "type": "object",
+          "properties": {
+            "vimid": {
+              "type": "string",
+              "description": "The identifier of the VIM"
             }
           }
         }
+      }
     },
     "jobResponseInfo": {
       "properties": {
         }
       }
     },
-    "/lcn":{
+    "/lcn": {
       "get": {
         "tags": [
           "SBI"
         "tags": [
           "Utilities"
         ],
-        "consumes":[
+        "consumes": [
           "multipart/form-data"
         ],
-        "produces":[
+        "produces": [
           "application/octet-stream"
         ],
-        "parameters" : [
+        "parameters": [
           {
             "description": "The CBAM VNF package",
             "in": "formData",
         "responses": {
           "200": {
             "description": "The converted package",
-            "schema":{
+            "schema": {
               "type": "file"
             }
           }
         "tags": [
           "Utilities"
         ],
-        "produces":[
+        "produces": [
           "text/html"
         ],
         "summary": "UI to convert the Nokia CBAM package to ONAP package",
           }
         }
       }
-
+    },
+    "/so/{vnfmId}/vnfs": {
+      "post": {
+        "tags": [
+          "SO VNFM Adaptor"
+        ],
+        "summary": "VNF create",
+        "description": "VNF create",
+        "operationId": "vnf_create",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF creation request parameter",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfCreationRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoVnfCreationResponse"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}": {
+      "post": {
+        "tags": [
+          "SO VNFM Adaptor"
+        ],
+        "summary": "VNF activation",
+        "description": "VNF activation",
+        "operationId": "vnf_activate",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "instantiate request param",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfActivationRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      },
+      "delete": {
+        "tags": [
+          "SO VNFM driver"
+        ],
+        "summary": "Deletes VNF",
+        "description": "Deletes the VNF. If the VNF was instantiated VNF termination must be called before VNF deletion",
+        "operationId": "delete_vnf",
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          }
+        ],
+        "responses": {
+          "204": {
+            "description": "The VNF was deleted successfully"
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}/scale": {
+      "post": {
+        "tags": [
+          "SO VNFM Adaptor"
+        ],
+        "summary": "VNF scale",
+        "description": "VNF scale request",
+        "operationId": "vnf_scale",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF scale request parameters",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfScaleRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}/customOperation": {
+      "post": {
+        "tags": [
+          "SO VNFM Adaptor"
+        ],
+        "summary": "VNF scale",
+        "description": "VNF scale request",
+        "operationId": "vnf_scale",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF scale request parameters",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfCustomOperation"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}/heal": {
+      "post": {
+        "tags": [
+          "SO VNFM driver"
+        ],
+        "summary": "VNF heal",
+        "description": "VNF heal",
+        "operationId": "vnf_heal",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF heal request parameters",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfHealRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}/terminate": {
+      "post": {
+        "tags": [
+          "SO VNFM driver"
+        ],
+        "summary": "VNF terminate",
+        "description": "VNF terminate",
+        "operationId": "vnf_terminate",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF termination request parameters",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfTerminationRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/jobs/{jobId}": {
+      "get": {
+        "tags": [
+          "SO VNFM driver"
+        ],
+        "summary": "Query job status",
+        "description": "Query the job status",
+        "operationId": "get_jobstatus",
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the job",
+            "name": "jobId",
+            "in": "path"
+          }
+        ],
+        "responses": {
+          "202": {
+            "description": "The details of a job",
+            "schema": {
+              "$ref": "#/definitions/SoJobDetail"
+            }
+          },
+          "404": {
+            "description": "The job is unknown to the VNFM. The VNFM does not keep finished jobs for forever.",
+            "schema": {
+              "$ref": "#/definitions/SoJobDetail"
+            }
+          }
+        }
+      }
     }
   }
 }
index a97b74d..bd5e42f 100644 (file)
@@ -36,7 +36,6 @@ import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase;
 
 import static junit.framework.TestCase.assertEquals;
 import static org.mockito.Mockito.*;
-import static org.springframework.test.util.ReflectionTestUtils.setField;
 
 class ResultCaptor<T> implements Answer {
     private T result = null;
index ece65ee..4c38211 100644 (file)
@@ -55,7 +55,6 @@ public class TestVnfcManager extends TestBase {
         when(aaiRestApiProvider.getNetworkApi()).thenReturn(networkApi);
     }
 
-
     /**
      * test create
      */
@@ -138,6 +137,15 @@ public class TestVnfcManager extends TestBase {
         VOID_OBSERVABLE.assertCalled();
     }
 
+    /**
+     * test VNFC id conversion
+     */
+    @Test
+    public void testCbamId() {
+        assertEquals("b", VnfcManager.buildCbamId("a_b"));
+    }
+
+
     /**
      * test inheritence
      */
diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/TestSoLifecycleManager.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/TestSoLifecycleManager.java
new file mode 100644 (file)
index 0000000..ebc2159
--- /dev/null
@@ -0,0 +1,514 @@
+/*
+ * Copyright 2016-2017, Nokia Corporation
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.so;
+
+import com.google.gson.JsonObject;
+import com.nokia.cbam.lcm.v32.model.ExtVirtualLinkData;
+import com.nokia.cbam.lcm.v32.model.VimSoftwareImage;
+import com.nokia.cbam.lcm.v32.model.VnfInfo;
+import com.nokia.cbam.lcm.v32.model.VnfProperty;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Test;
+import org.mockito.ArgumentCaptor;
+import org.mockito.Mock;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VimInfoProvider;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.AdditionalParameters;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.JobManager;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager;
+import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase;
+import org.onap.vnfmadapter.so.model.*;
+import org.onap.vnfmdriver.model.*;
+
+import static com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum.*;
+import static junit.framework.TestCase.assertEquals;
+import static org.mockito.ArgumentMatchers.eq;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION;
+import static org.springframework.test.util.ReflectionTestUtils.setField;
+
+public class TestSoLifecycleManager extends TestBase {
+
+    private static final String VNFD_ID = "cbamVnfdId";
+    @Mock
+    private LifecycleManager lifecycleManager;
+    @Mock
+    private VimInfoProvider vimInfoProvider;
+    @Mock
+    private JobManager jobManager;
+    private SoLifecycleManager soLifecycleManager;
+
+    @Before
+    public void init() {
+        setField(SoLifecycleManager.class, "logger", logger);
+        soLifecycleManager = new SoLifecycleManager(lifecycleManager, vimInfoProvider, cbamRestApiProvider, jobManager);
+    }
+
+    /**
+     * test VNF creation
+     */
+    @Test
+    public void testVnfCreation() throws Exception {
+        SoVnfCreationRequest onapRequest = new SoVnfCreationRequest();
+        Object additionalParams = new JsonObject();
+        onapRequest.setAdditionalParams(additionalParams);
+        onapRequest.setCsarId("csarId");
+        onapRequest.setDescription("description");
+        onapRequest.setName("name");
+        VnfInfo vnfInfo = new VnfInfo();
+        vnfInfo.setId(VNF_ID);
+        LifecycleManager.VnfCreationResult genericResponse = new LifecycleManager.VnfCreationResult(vnfInfo, VNFD_ID);
+        when(lifecycleManager.create(VNFM_ID, "csarId", "name", "description")).thenReturn(genericResponse);
+        //when
+        SoVnfCreationResponse response = soLifecycleManager.create(VNFM_ID, onapRequest);
+        //verify
+        assertEquals(VNF_ID, response.getVnfId());
+    }
+
+    /**
+     * test VNF activation without parameters
+     */
+    @Test
+    public void testVnfActivation() throws Exception {
+        SoVnfActivationRequest soRequest = new SoVnfActivationRequest();
+        soRequest.setVimId(VIM_ID);
+
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        org.onap.vnfmdriver.model.VnfInfo vnfInfo = new org.onap.vnfmdriver.model.VnfInfo();
+        vnfInfo.setVnfdId(VNFD_ID);
+        when(lifecycleManager.queryVnf(VNFM_ID, VNF_ID)).thenReturn(vnfInfo);
+        ArgumentCaptor<List<ExtVirtualLinkInfo>> extLinks = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<AdditionalParameters> additionalParameters = ArgumentCaptor.forClass(AdditionalParameters.class);
+        VnfInstantiateResponse instantiationResponse = new VnfInstantiateResponse();
+        instantiationResponse.setJobId(JOB_ID);
+        when(lifecycleManager.instantiate(eq(VNFM_ID), extLinks.capture(), eq(httpResponse), eq(additionalParams), additionalParameters.capture(), eq(VNF_ID), eq("csarId"), eq(VNFD_ID))).thenReturn(instantiationResponse);
+        org.onap.vnfmdriver.model.VimInfo esrInfo = new org.onap.vnfmdriver.model.VimInfo();
+        esrInfo.setUrl("http://localhost:123/v3");
+        esrInfo.setDomain("domain");
+        when(vimInfoProvider.getVimInfo(VIM_ID)).thenReturn(esrInfo);
+        VnfInfo cbamVnfInfo = new VnfInfo();
+        cbamVnfInfo.setExtensions(new ArrayList<>());
+        VnfProperty onapVnfdId = new VnfProperty();
+        cbamVnfInfo.getExtensions().add(onapVnfdId);
+        onapVnfdId.setName(LifecycleManager.ONAP_CSAR_ID);
+        onapVnfdId.setValue("csarId");
+        when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(cbamVnfInfo));
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.activate(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        AdditionalParameters actualAdditionalParameters = additionalParameters.getValue();
+        assertEquals(0, actualAdditionalParameters.getComputeResourceFlavours().size());
+        assertEquals(additionalParams, actualAdditionalParameters.getAdditionalParams());
+        assertEquals(0, actualAdditionalParameters.getExternalConnectionPointAddresses().size());
+        assertEquals(0, actualAdditionalParameters.getExtManagedVirtualLinks().size());
+        assertEquals(0, actualAdditionalParameters.getExtVirtualLinks().size());
+        assertEquals("default", actualAdditionalParameters.getInstantiationLevel());
+        assertEquals(0, actualAdditionalParameters.getSoftwareImages().size());
+        assertEquals(OPENSTACK_V3_INFO, actualAdditionalParameters.getVimType());
+        assertEquals(0, actualAdditionalParameters.getZones().size());
+        assertEquals(0, extLinks.getValue().size());
+    }
+
+
+    /**
+     * test VNF activation without parameters for V2 based API
+     */
+    @Test
+    public void testVnfActivationForV2() throws Exception {
+        SoVnfActivationRequest soRequest = new SoVnfActivationRequest();
+        soRequest.setVimId(VIM_ID);
+
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        org.onap.vnfmdriver.model.VnfInfo vnfInfo = new org.onap.vnfmdriver.model.VnfInfo();
+        vnfInfo.setVnfdId(VNFD_ID);
+        when(lifecycleManager.queryVnf(VNFM_ID, VNF_ID)).thenReturn(vnfInfo);
+        ArgumentCaptor<List<ExtVirtualLinkInfo>> extLinks = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<AdditionalParameters> additionalParameters = ArgumentCaptor.forClass(AdditionalParameters.class);
+        VnfInstantiateResponse instantiationResponse = new VnfInstantiateResponse();
+        instantiationResponse.setJobId(JOB_ID);
+        when(lifecycleManager.instantiate(eq(VNFM_ID), extLinks.capture(), eq(httpResponse), eq(additionalParams), additionalParameters.capture(), eq(VNF_ID), eq("csarId"), eq(VNFD_ID))).thenReturn(instantiationResponse);
+        org.onap.vnfmdriver.model.VimInfo esrInfo = new org.onap.vnfmdriver.model.VimInfo();
+        esrInfo.setUrl("http://localhost:123/v2");
+        when(vimInfoProvider.getVimInfo(VIM_ID)).thenReturn(esrInfo);
+        VnfInfo cbamVnfInfo = new VnfInfo();
+        cbamVnfInfo.setExtensions(new ArrayList<>());
+        VnfProperty onapVnfdId = new VnfProperty();
+        cbamVnfInfo.getExtensions().add(onapVnfdId);
+        onapVnfdId.setName(LifecycleManager.ONAP_CSAR_ID);
+        onapVnfdId.setValue("csarId");
+        when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(cbamVnfInfo));
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.activate(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        AdditionalParameters actualAdditionalParameters = additionalParameters.getValue();
+        assertEquals(OPENSTACK_V2_INFO, actualAdditionalParameters.getVimType());
+    }
+
+    /**
+     * test VNF activation without parameters for vCloud based API
+     */
+    @Test
+    public void testVnfActivationForVcloud() throws Exception {
+        SoVnfActivationRequest soRequest = new SoVnfActivationRequest();
+        soRequest.setVimId(VIM_ID);
+
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        org.onap.vnfmdriver.model.VnfInfo vnfInfo = new org.onap.vnfmdriver.model.VnfInfo();
+        vnfInfo.setVnfdId(VNFD_ID);
+        when(lifecycleManager.queryVnf(VNFM_ID, VNF_ID)).thenReturn(vnfInfo);
+        ArgumentCaptor<List<ExtVirtualLinkInfo>> extLinks = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<AdditionalParameters> additionalParameters = ArgumentCaptor.forClass(AdditionalParameters.class);
+        VnfInstantiateResponse instantiationResponse = new VnfInstantiateResponse();
+        instantiationResponse.setJobId(JOB_ID);
+        when(lifecycleManager.instantiate(eq(VNFM_ID), extLinks.capture(), eq(httpResponse), eq(additionalParams), additionalParameters.capture(), eq(VNF_ID), eq("csarId"), eq(VNFD_ID))).thenReturn(instantiationResponse);
+        org.onap.vnfmdriver.model.VimInfo esrInfo = new org.onap.vnfmdriver.model.VimInfo();
+        esrInfo.setUrl("http://localhost:123/");
+        esrInfo.setDomain("domain");
+        when(vimInfoProvider.getVimInfo(VIM_ID)).thenReturn(esrInfo);
+        VnfInfo cbamVnfInfo = new VnfInfo();
+        cbamVnfInfo.setExtensions(new ArrayList<>());
+        VnfProperty onapVnfdId = new VnfProperty();
+        cbamVnfInfo.getExtensions().add(onapVnfdId);
+        onapVnfdId.setName(LifecycleManager.ONAP_CSAR_ID);
+        onapVnfdId.setValue("csarId");
+        when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(cbamVnfInfo));
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.activate(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        AdditionalParameters actualAdditionalParameters = additionalParameters.getValue();
+        assertEquals(VMWARE_VCLOUD_INFO, actualAdditionalParameters.getVimType());
+    }
+
+    /**
+     * test VNF activation with VDU mappings
+     */
+    @Test
+    public void testVnfActivationWithVdu() throws Exception {
+        SoVnfActivationRequest soRequest = new SoVnfActivationRequest();
+        soRequest.setVimId(VIM_ID);
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        org.onap.vnfmdriver.model.VnfInfo vnfInfo = new org.onap.vnfmdriver.model.VnfInfo();
+        vnfInfo.setVnfdId(VNFD_ID);
+        when(lifecycleManager.queryVnf(VNFM_ID, VNF_ID)).thenReturn(vnfInfo);
+        ArgumentCaptor<List<ExtVirtualLinkInfo>> extLinks = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<AdditionalParameters> additionalParameters = ArgumentCaptor.forClass(AdditionalParameters.class);
+        VnfInstantiateResponse instantiationResponse = new VnfInstantiateResponse();
+        instantiationResponse.setJobId(JOB_ID);
+        when(lifecycleManager.instantiate(eq(VNFM_ID), extLinks.capture(), eq(httpResponse), eq(additionalParams), additionalParameters.capture(), eq(VNF_ID), eq("csarId"), eq(VNFD_ID))).thenReturn(instantiationResponse);
+        org.onap.vnfmdriver.model.VimInfo esrInfo = new org.onap.vnfmdriver.model.VimInfo();
+        esrInfo.setUrl("http://localhost:123/v3");
+        esrInfo.setDomain("domain");
+        when(vimInfoProvider.getVimInfo(VIM_ID)).thenReturn(esrInfo);
+        VnfInfo cbamVnfInfo = new VnfInfo();
+        cbamVnfInfo.setExtensions(new ArrayList<>());
+        VnfProperty onapVnfdId = new VnfProperty();
+        cbamVnfInfo.getExtensions().add(onapVnfdId);
+        onapVnfdId.setName(LifecycleManager.ONAP_CSAR_ID);
+        onapVnfdId.setValue("csarId");
+        when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(cbamVnfInfo));
+        soRequest.setVduMappings(new ArrayList<>());
+        SoVduMapping vduMapping = new SoVduMapping();
+        soRequest.getVduMappings().add(vduMapping);
+        vduMapping.setFlavourId("flavorId");
+        vduMapping.setImageId("imageId");
+        vduMapping.setVduId("vduId");
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.activate(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        AdditionalParameters actualAdditionalParameters = additionalParameters.getValue();
+        assertEquals(1, actualAdditionalParameters.getComputeResourceFlavours().size());
+        assertEquals(1, actualAdditionalParameters.getSoftwareImages().size());
+        VimSoftwareImage image = actualAdditionalParameters.getSoftwareImages().get(0);
+        assertEquals(VIM_ID, image.getVimId());
+        assertEquals("vduId_image", image.getVnfdSoftwareImageId());
+        assertEquals("imageId", image.getResourceId());
+        assertEquals(VIM_ID, actualAdditionalParameters.getComputeResourceFlavours().get(0).getVimId());
+        assertEquals("flavorId", actualAdditionalParameters.getComputeResourceFlavours().get(0).getResourceId());
+        assertEquals("vduId", actualAdditionalParameters.getComputeResourceFlavours().get(0).getVnfdVirtualComputeDescId());
+        assertEquals(OPENSTACK_V3_INFO, actualAdditionalParameters.getVimType());
+    }
+
+    /**
+     * test VNF activation with network mappings
+     */
+    @Test
+    public void testVnfActivationWithNetworkMapping() throws Exception {
+        SoVnfActivationRequest soRequest = new SoVnfActivationRequest();
+        soRequest.setVimId(VIM_ID);
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        org.onap.vnfmdriver.model.VnfInfo vnfInfo = new org.onap.vnfmdriver.model.VnfInfo();
+        vnfInfo.setVnfdId(VNFD_ID);
+        when(lifecycleManager.queryVnf(VNFM_ID, VNF_ID)).thenReturn(vnfInfo);
+        ArgumentCaptor<List<ExtVirtualLinkInfo>> extLinks = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<AdditionalParameters> additionalParameters = ArgumentCaptor.forClass(AdditionalParameters.class);
+        VnfInstantiateResponse instantiationResponse = new VnfInstantiateResponse();
+        instantiationResponse.setJobId(JOB_ID);
+        when(lifecycleManager.instantiate(eq(VNFM_ID), extLinks.capture(), eq(httpResponse), eq(additionalParams), additionalParameters.capture(), eq(VNF_ID), eq("csarId"), eq(VNFD_ID))).thenReturn(instantiationResponse);
+        org.onap.vnfmdriver.model.VimInfo esrInfo = new org.onap.vnfmdriver.model.VimInfo();
+        esrInfo.setUrl("http://localhost:123/v3");
+        esrInfo.setDomain("domain");
+        when(vimInfoProvider.getVimInfo(VIM_ID)).thenReturn(esrInfo);
+        VnfInfo cbamVnfInfo = new VnfInfo();
+        cbamVnfInfo.setExtensions(new ArrayList<>());
+        VnfProperty onapVnfdId = new VnfProperty();
+        cbamVnfInfo.getExtensions().add(onapVnfdId);
+        onapVnfdId.setName(LifecycleManager.ONAP_CSAR_ID);
+        onapVnfdId.setValue("csarId");
+        when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(cbamVnfInfo));
+        soRequest.setNetworkMappings(new ArrayList<>());
+        SoNetworkMapping networkMapping = new SoNetworkMapping();
+        networkMapping.setVldId("myVldId");
+        networkMapping.setNetworkProviderId("providerId");
+        networkMapping.setAssignedAddresses(new ArrayList<>());
+        SoAssignedAddresses e1 = new SoAssignedAddresses();
+        e1.setIpAddress("1.2.3.4");
+        e1.setCpdId("cpdId");
+        SoAssignedAddresses e2 = new SoAssignedAddresses();
+        e2.setIpAddress("1.2.3.5");
+        e2.setCpdId("cpdId2");
+        SoAssignedAddresses e3 = new SoAssignedAddresses();
+        e3.setIpAddress("1.2.3.6");
+        e3.setCpdId("cpdId2");
+        SoAssignedAddresses e4 = new SoAssignedAddresses();
+        e4.setIpAddress("1.2.3.6");
+        e4.setCpdId("cpdId2");
+        networkMapping.getAssignedAddresses().add(e1);
+        networkMapping.getAssignedAddresses().add(e2);
+        networkMapping.getAssignedAddresses().add(e3);
+        networkMapping.getAssignedAddresses().add(e4);
+        SoNetworkMapping networkMapping2 = new SoNetworkMapping();
+        soRequest.getNetworkMappings().add(networkMapping);
+        soRequest.getNetworkMappings().add(networkMapping2);
+        networkMapping2.setVldId("myVldId2");
+        networkMapping2.setNetworkProviderId("providerId2");
+
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.activate(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        AdditionalParameters actualAdditionalParameters = additionalParameters.getValue();
+        assertEquals(2, actualAdditionalParameters.getExtVirtualLinks().size());
+        ExtVirtualLinkData actualVl = actualAdditionalParameters.getExtVirtualLinks().get(0);
+        assertEquals(VIM_ID, actualVl.getVimId());
+        assertEquals("providerId", actualVl.getResourceId());
+        assertEquals("myVldId", actualVl.getExtVirtualLinkId());
+        assertEquals(2, actualVl.getExtCps().size());
+        assertEquals("cpdId", actualVl.getExtCps().get(0).getCpdId());
+        assertEquals("1.2.3.4", actualVl.getExtCps().get(0).getAddresses().get(0).getIp());
+        assertEquals("cpdId2", actualVl.getExtCps().get(1).getCpdId());
+        assertEquals("1.2.3.5", actualVl.getExtCps().get(1).getAddresses().get(0).getIp());
+        assertEquals("1.2.3.6", actualVl.getExtCps().get(1).getAddresses().get(1).getIp());
+    }
+
+    /**
+     * test VNF activation with server mappings
+     */
+    @Test
+    public void testVnfActivationWithServerMappings() throws Exception {
+        SoVnfActivationRequest soRequest = new SoVnfActivationRequest();
+        soRequest.setVimId(VIM_ID);
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        org.onap.vnfmdriver.model.VnfInfo vnfInfo = new org.onap.vnfmdriver.model.VnfInfo();
+        vnfInfo.setVnfdId(VNFD_ID);
+        when(lifecycleManager.queryVnf(VNFM_ID, VNF_ID)).thenReturn(vnfInfo);
+        ArgumentCaptor<List<ExtVirtualLinkInfo>> extLinks = ArgumentCaptor.forClass(List.class);
+        ArgumentCaptor<AdditionalParameters> additionalParameters = ArgumentCaptor.forClass(AdditionalParameters.class);
+        VnfInstantiateResponse instantiationResponse = new VnfInstantiateResponse();
+        instantiationResponse.setJobId(JOB_ID);
+        when(lifecycleManager.instantiate(eq(VNFM_ID), extLinks.capture(), eq(httpResponse), eq(additionalParams), additionalParameters.capture(), eq(VNF_ID), eq("csarId"), eq(VNFD_ID))).thenReturn(instantiationResponse);
+        org.onap.vnfmdriver.model.VimInfo esrInfo = new org.onap.vnfmdriver.model.VimInfo();
+        esrInfo.setUrl("http://localhost:123/v3");
+        esrInfo.setDomain("domain");
+        when(vimInfoProvider.getVimInfo(VIM_ID)).thenReturn(esrInfo);
+        VnfInfo cbamVnfInfo = new VnfInfo();
+        cbamVnfInfo.setExtensions(new ArrayList<>());
+        VnfProperty onapVnfdId = new VnfProperty();
+        cbamVnfInfo.getExtensions().add(onapVnfdId);
+        onapVnfdId.setName(LifecycleManager.ONAP_CSAR_ID);
+        onapVnfdId.setValue("csarId");
+        when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(cbamVnfInfo));
+        soRequest.setServerMappings(new ArrayList<>());
+        SoServerMapping s1 = new SoServerMapping();
+        soRequest.getServerMappings().add(s1);
+        s1.setVduId("vduId1");
+        s1.setAvailabilityZoneId("azId1");
+        SoServerMapping s2 = new SoServerMapping();
+        soRequest.getServerMappings().add(s2);
+        s2.setVduId("vduId1");
+        s2.setAvailabilityZoneId("azId1");
+        SoServerMapping s3 = new SoServerMapping();
+        soRequest.getServerMappings().add(s3);
+        s3.setVduId("vduId2");
+        s3.setAvailabilityZoneId("azId1");
+
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.activate(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        AdditionalParameters actualAdditionalParameters = additionalParameters.getValue();
+        assertEquals(2, actualAdditionalParameters.getZones().size());
+        assertEquals(VIM_ID, actualAdditionalParameters.getZones().get(0).getVimId());
+        assertEquals("azId1", actualAdditionalParameters.getZones().get(0).getResourceId());
+        assertEquals("vduId1", actualAdditionalParameters.getZones().get(0).getId());
+        assertEquals(VIM_ID, actualAdditionalParameters.getZones().get(1).getVimId());
+        assertEquals("azId1", actualAdditionalParameters.getZones().get(1).getResourceId());
+        assertEquals("vduId2", actualAdditionalParameters.getZones().get(1).getId());
+    }
+
+    /**
+     * test VNF scale
+     */
+    @Test
+    public void testScaling() throws Exception {
+        SoVnfScaleRequest soRequest = new SoVnfScaleRequest();
+        ArgumentCaptor<org.onap.vnfmdriver.model.VnfScaleRequest> driverRequest = ArgumentCaptor.forClass(org.onap.vnfmdriver.model.VnfScaleRequest.class);
+        JobInfo jobInfo = new JobInfo();
+        jobInfo.setJobId(JOB_ID);
+
+        soRequest.setAspectId("aspectId");
+        soRequest.setDirection(SoScaleDirection.IN);
+        soRequest.setSteps(2);
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        when(lifecycleManager.scaleVnf(eq(VNFM_ID), eq(VNF_ID), driverRequest.capture(), eq(httpResponse))).thenReturn(jobInfo);
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.scale(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        assertEquals(2, Integer.parseInt(driverRequest.getValue().getNumberOfSteps()));
+        assertEquals("aspectId", driverRequest.getValue().getAspectId());
+        assertEquals(org.onap.vnfmdriver.model.ScaleDirection.IN, driverRequest.getValue().getType());
+        assertEquals(additionalParams, driverRequest.getValue().getAdditionalParam());
+    }
+
+    /**
+     * test VNF heal
+     */
+    @Test
+    public void testHeal() throws Exception {
+        SoVnfHealRequest soRequest = new SoVnfHealRequest();
+        ArgumentCaptor<org.onap.vnfmdriver.model.VnfHealRequest> driverRequest = ArgumentCaptor.forClass(org.onap.vnfmdriver.model.VnfHealRequest.class);
+        JobInfo jobInfo = new JobInfo();
+        jobInfo.setJobId(JOB_ID);
+
+        soRequest.setVnfcId(VNF_ID + "_vnfcId");
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        when(lifecycleManager.healVnf(eq(VNFM_ID), eq(VNF_ID), driverRequest.capture(), eq(Optional.of("vnfcId")), eq(httpResponse))).thenReturn(jobInfo);
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.heal(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        assertEquals("notUsedByDriver", driverRequest.getValue().getAffectedvm().getVduid());
+        assertEquals("notUsedByDriver", driverRequest.getValue().getAffectedvm().getVimid());
+        assertEquals("unknown", driverRequest.getValue().getAffectedvm().getVmname());
+        assertEquals("heal", driverRequest.getValue().getAction());
+    }
+
+    /**
+     * test VNF deactivation
+     */
+    @Test
+    public void testDeactivation() throws Exception {
+        SoVnfTerminationRequest soRequest = new SoVnfTerminationRequest();
+        ArgumentCaptor<org.onap.vnfmdriver.model.VnfTerminateRequest> driverRequest = ArgumentCaptor.forClass(org.onap.vnfmdriver.model.VnfTerminateRequest.class);
+        JobInfo jobInfo = new JobInfo();
+        jobInfo.setJobId(JOB_ID);
+        soRequest.setGracefulTerminationTimeoutInMs(1234);
+        soRequest.setMode(SoTerminationMode.GRACEFUL);
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        when(lifecycleManager.terminateAndDelete(eq(VNFM_ID), eq(VNF_ID), driverRequest.capture(), eq(httpResponse))).thenReturn(jobInfo);
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.deactivate(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+        assertEquals(VnfTerminationType.GRACEFUL, driverRequest.getValue().getTerminationType());
+        assertEquals("1234", driverRequest.getValue().getGracefulTerminationTimeout());
+    }
+
+    /**
+     * test VNF deletion
+     */
+    @Test
+    public void testDelete() throws Exception {
+        //when
+        soLifecycleManager.delete(VNFM_ID, VNF_ID);
+        //verify
+        verify(lifecycleManager).deleteVnf(VNFM_ID, VNF_ID);
+    }
+
+    /**
+     * test VNF custom operation
+     */
+    @Test
+    public void testCustomOperation() throws Exception {
+        SoVnfCustomOperation soRequest = new SoVnfCustomOperation();
+        JobInfo jobInfo = new JobInfo();
+        jobInfo.setJobId(JOB_ID);
+        soRequest.setOperationId("operationId");
+        JsonObject additionalParams = new JsonObject();
+        soRequest.setAdditionalParams(additionalParams);
+        when(lifecycleManager.customOperation(VNFM_ID, VNF_ID, "operationId", additionalParams, httpResponse)).thenReturn(jobInfo);
+        //when
+        SoJobHandler jobHandler = soLifecycleManager.customOperation(VNFM_ID, VNF_ID, soRequest, httpResponse);
+        //verify
+        assertEquals(JOB_ID, jobHandler.getJobId());
+    }
+
+
+    /**
+     * test VNF custom operation
+     */
+    @Test
+    public void testJobDetails() throws Exception {
+        JobDetailInfo currentJobDetails = new JobDetailInfo();
+        currentJobDetails.setJobId(JOB_ID);
+        when(jobManager.getJob(VNFM_ID, JOB_ID)).thenReturn(currentJobDetails);
+        currentJobDetails.setResponseDescriptor(new JobDetailInfoResponseDescriptor());
+
+        assertJob(currentJobDetails, SoJobStatus.FINISHED, JobStatus.FINISHED);
+        assertJob(currentJobDetails, SoJobStatus.FAILED, JobStatus.ERROR);
+        assertJob(currentJobDetails, SoJobStatus.FAILED, JobStatus.TIMEOUT);
+        assertJob(currentJobDetails, SoJobStatus.STARTED, JobStatus.STARTED);
+        assertJob(currentJobDetails, SoJobStatus.STARTED, JobStatus.PROCESSING);
+
+    }
+
+    private void assertJob(JobDetailInfo currentJobDetails, SoJobStatus expectedState, JobStatus started) {
+        currentJobDetails.getResponseDescriptor().setStatus(started);
+        //when
+        SoJobDetail jobDetail = soLifecycleManager.getJobDetails(VNFM_ID, JOB_ID);
+        //verify
+        assertEquals(JOB_ID, jobDetail.getJobId());
+        assertEquals(expectedState, jobDetail.getStatus());
+    }
+
+
+}
\ No newline at end of file
index f88305a..d39a144 100644 (file)
@@ -37,7 +37,7 @@ import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil.loadFile;
 
 public class TestSwaggerDefinitionConsistency extends TestBase {
 
-    public static final HashSet<Class<?>> CLASSES = Sets.newHashSet(LcmApi.class, LcnApi.class, SwaggerApi.class, ConverterApi.class);
+    public static final HashSet<Class<?>> CLASSES = Sets.newHashSet(LcmApi.class, LcnApi.class, SwaggerApi.class, ConverterApi.class, SoApi.class);
 
     @Test
     public void test() throws Exception {
@@ -69,15 +69,31 @@ public class TestSwaggerDefinitionConsistency extends TestBase {
     }
 
     private void locate(String path) {
+        Set<String> paths = new HashSet<>();
         for (Class<?> clazz : CLASSES) {
             RequestMapping basePath = clazz.getAnnotation(RequestMapping.class);
             for (Method method : clazz.getMethods()) {
                 RequestMapping methodMapping = method.getAnnotation(RequestMapping.class);
-                if (methodMapping != null && path.equals(basePath.value()[0] + methodMapping.value()[0])) {
-                    return;
+                if (methodMapping != null) {
+                    paths.add(basePath.value()[0] + methodMapping.value()[0]);
+                    if (path.equals(basePath.value()[0] + methodMapping.value()[0])) {
+                        return;
+                    }
+                }
+            }
+        }
+        for (Class<?> clazz : CLASSES) {
+            RequestMapping basePath = clazz.getAnnotation(RequestMapping.class);
+            for (Method method : clazz.getMethods()) {
+                RequestMapping methodMapping = method.getAnnotation(RequestMapping.class);
+                if (methodMapping != null) {
+                    paths.add(basePath.value()[0] + methodMapping.value()[0]);
+                    if (path.equals(basePath.value()[0] + methodMapping.value()[0])) {
+                        return;
+                    }
                 }
             }
         }
-        throw new NoSuchElementException(path);
+        throw new NoSuchElementException(path + " in " + paths);
     }
 }
index 16d1f02..7078e02 100644 (file)
@@ -90,6 +90,8 @@ public class TestLifecycleManager extends TestBase {
     private OperationExecution modifyPropertyoperationExecution = new OperationExecution();
     private OperationExecution scaleOperationExecution = new OperationExecution();
     private OperationExecution healOperationExecution = new OperationExecution();
+    private OperationExecution customOperationExecution = new OperationExecution();
+
 
     private VnfInfo vnfInfo = new VnfInfo();
     private List<OperationExecution> operationExecutions = new ArrayList<>();
@@ -100,6 +102,8 @@ public class TestLifecycleManager extends TestBase {
     private Set<Boolean> finished = new HashSet<>();
     private ArgumentCaptor<ScaleVnfRequest> actualScaleRequest = ArgumentCaptor.forClass(ScaleVnfRequest.class);
     private ArgumentCaptor<HealVnfRequest> actualHealRequest = ArgumentCaptor.forClass(HealVnfRequest.class);
+    private ArgumentCaptor<CustomOperationRequest> customOperationRequestArgumentCaptor = ArgumentCaptor.forClass(CustomOperationRequest.class);
+    private ArgumentCaptor<String> operationIdCaptor = ArgumentCaptor.forClass(String.class);
 
     private LifecycleManager lifecycleManager;
 
@@ -135,9 +139,12 @@ public class TestLifecycleManager extends TestBase {
         operationExecutions.add(instantiationOperationExecution);
         instantiationOperationExecution.setStatus(OperationStatus.FINISHED);
         modifyPropertyoperationExecution.setStatus(OperationStatus.FINISHED);
+        customOperationExecution.setStatus(OperationStatus.FINISHED);
         modifyPropertyoperationExecution.setId(UUID.randomUUID().toString());
         scaleOperationExecution.setId(UUID.randomUUID().toString());
         healOperationExecution.setId(UUID.randomUUID().toString());
+        customOperationExecution.setId(UUID.randomUUID().toString());
+
         when(vnfApi.vnfsVnfInstanceIdPatch(eq(VNF_ID), actualVnfModifyRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(buildObservable(modifyPropertyoperationExecution));
         doAnswer(new Answer() {
             @Override
@@ -160,6 +167,13 @@ public class TestLifecycleManager extends TestBase {
                 return buildObservable(healOperationExecution);
             }
         });
+        when(vnfApi.vnfsVnfInstanceIdCustomCustomOperationNamePost(eq(VNF_ID), operationIdCaptor.capture(), customOperationRequestArgumentCaptor.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<Observable<OperationExecution>>() {
+            @Override
+            public Observable<OperationExecution> answer(InvocationOnMock invocation) throws Throwable {
+                operationExecutions.add(customOperationExecution);
+                return buildObservable(customOperationExecution);
+            }
+        });
     }
 
     /**
@@ -725,7 +739,7 @@ public class TestLifecycleManager extends TestBase {
      * - the VNF is not deleted before the notifications are processed
      */
     @Test
-    public void testTermination() throws Exception {
+    public void testTerminationAndDeletion() throws Exception {
         //given
         VnfTerminateRequest terminationRequest = new VnfTerminateRequest();
         when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(vnfInfo));
@@ -765,6 +779,49 @@ public class TestLifecycleManager extends TestBase {
         verify(logger).info(eq("Starting {} operation on VNF with {} identifier with {} parameter"), eq("termination"), eq(VNF_ID), anyString());
     }
 
+    /**
+     * test termination basic success scenario
+     * - the VNF is not deleted before the notifications are processed
+     */
+    @Test
+    public void testTermination() throws Exception {
+        //given
+        VnfTerminateRequest terminationRequest = new VnfTerminateRequest();
+        when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(vnfInfo));
+        vnfInfo.setInstantiationState(InstantiationState.INSTANTIATED);
+        vnfInfo.setOperationExecutions(operationExecutions);
+        VnfProperty vnfdId = new VnfProperty();
+        vnfdId.setName(LifecycleManager.ONAP_CSAR_ID);
+        vnfdId.setValue(ONAP_CSAR_ID);
+        vnfInfo.getExtensions().add(vnfdId);
+        ArgumentCaptor<TerminateVnfRequest> actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class);
+        when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<Observable<OperationExecution>>() {
+            @Override
+            public Observable<OperationExecution> answer(InvocationOnMock invocation) throws Throwable {
+                OperationExecution terminationOperation = new OperationExecution();
+                terminationOperation.setId("terminationId");
+                operationExecutions.add(terminationOperation);
+                terminationOperation.setStatus(OperationStatus.FINISHED);
+                return buildObservable(terminationOperation);
+            }
+        });
+        JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } ");
+        when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(buildObservable(instantiationParameters));
+        //when
+        JobInfo jobInfo = lifecycleManager.terminate(VNFM_ID, VNF_ID, terminationRequest, restResponse);
+        //verify
+        waitForJobToFinishInJobManager(finished);
+        assertEquals(1, actualTerminationRequest.getAllValues().size());
+        assertEquals(TerminationType.FORCEFUL, actualTerminationRequest.getValue().getTerminationType());
+        assertEquals(JOB_ID, new Gson().toJsonTree(actualTerminationRequest.getValue().getAdditionalParams()).getAsJsonObject().get("jobId").getAsString());
+        InOrder notificationIsProcessedBeforeDeletingTheVnf = Mockito.inOrder(vfcGrantManager, notificationManager, vnfApi);
+        notificationIsProcessedBeforeDeletingTheVnf.verify(vfcGrantManager).requestGrantForTerminate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, vnfInfo, JOB_ID);
+        notificationIsProcessedBeforeDeletingTheVnf.verify(notificationManager).waitForTerminationToBeProcessed("terminationId");
+        verify(vnfApi, never()).vnfsVnfInstanceIdDelete(VNF_ID, NOKIA_LCM_API_VERSION);
+        verify(jobManager).spawnJob(VNF_ID, restResponse);
+        verify(logger).info(eq("Starting {} operation on VNF with {} identifier with {} parameter"), eq("termination"), eq(VNF_ID), anyString());
+    }
+
     /**
      * test termination of a non instantiated VNF
      * - the VNF is not terminated (only deleted)
@@ -796,7 +853,7 @@ public class TestLifecycleManager extends TestBase {
         }
         verify(vfcGrantManager, never()).requestGrantForTerminate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, vnfInfo, JOB_ID);
         verify(notificationManager, never()).waitForTerminationToBeProcessed("terminationId");
-        verify(logger).debug("The VNF {} with identifier is not instantiated no termination required", VNF_ID);
+        verify(logger).warn("The VNF with {} identifier is not instantiated no termination is required", VNF_ID);
         verify(logger).info("Deleting VNF with {} identifier", VNF_ID);
         verify(logger).info("The VNF with {} identifier has been deleted", VNF_ID);
         VOID_OBSERVABLE.assertCalled();
@@ -1394,6 +1451,22 @@ public class TestLifecycleManager extends TestBase {
         verify(logger).error("Unable to heal VNF with myVnfId identifier", expectedException);
     }
 
+
+    /**
+     * test custom operation basic scenario
+     */
+    @Test
+    public void testCustomOperation() throws Exception {
+        String operationId = "operationIdCaptor";
+        Object additionalParams = new JsonObject();
+        //when
+        JobInfo job = lifecycleManager.customOperation(VNFM_ID, VNF_ID, operationId, additionalParams, restResponse);
+        //verify
+        waitForJobToFinishInJobManager(finished);
+        assertEquals(operationId, operationIdCaptor.getValue());
+        assertEquals(additionalParams, customOperationRequestArgumentCaptor.getValue().getAdditionalParams());
+    }
+
     private void waitForJobToFinishInJobManager(Set<Boolean> finished) throws InterruptedException {
         while (finished.size() == 0) {
             systemFunctions().sleep(100);
@@ -1413,7 +1486,7 @@ public class TestLifecycleManager extends TestBase {
                 break;
             case OPENSTACK_V3_INFO:
                 additionalParam.setVimType(VimInfo.VimInfoTypeEnum.OPENSTACK_V3_INFO);
-                additionalParam.setDomain("myDomain");
+                vimInfo.setDomain("myDomain");
                 break;
             case VMWARE_VCLOUD_INFO:
                 additionalParam.setVimType(VimInfo.VimInfoTypeEnum.VMWARE_VCLOUD_INFO);
index f933db9..27ce13e 100644 (file)
@@ -50,17 +50,30 @@ cbamUsername=onap
 cbamPassword=Admin@123
 # the identifier of the VNFM in A&AI core system registry
 vnfmId=7c267318-2a6a-4d47-b039-a7cce5fea38b
+
+###############################################################################
+# Configuration parameters for direct integration
+###############################################################################
+# skip hostname verification during SSL on CBAM LCN, LCM and authorization interface
+skipHostnameVerificationForAai=true
+# skip certificate verification during SSL on CBAM LCN, LCM and authorization interface
+skipCertificateVerificationForAai=true
+# the collection of trusted certificates for SSL on CBAM LCN, LCM and authorization interface
+# in PEM format encoded in BASE64 to a single line
+trustedCertificatesForAai=
+#The username to access AAI
 aaiUsername=AAI
+#The password to access AAI
 aaiPassword=AAI
+#The username to access SDC
 sdcUsername=SDC
+#The password to access SDC
 sdcPassword=SDC
-
 ###############################################################################
 # End of mandatory properties for driver                                      #
 ###############################################################################
 ipMap=10.0.14.1->msb.api.simpledemo.onap.org,172.17.0.15->msb.api.simpledemo.onap.org,10.0.1.1->aai.api.simpledemo.onap.org
 vnfmInfoCacheEvictionInMs=600000
-
 ## for logging begin ##
 com.fasterxml.jackson.core=jackson-databind
 #logging.file=${catalina.base}/logs/vfcadaptor.log
@@ -68,6 +81,5 @@ logging.level.org.springframework=INFO
 logging.level.org.hibernate=OFF
 logging.level.org.springframework.web=DEBUG
 ## for logging end ##
-
 spring.http.multipart.max-file-size=50000KB
 spring.http.multipart.max-request-size=50000KB
index f5c42fc..8446b48 100644 (file)
@@ -50,14 +50,31 @@ cbamUsername=onap
 cbamPassword=myPassword
 # the identifier of the VNFM in A&AI core system registry
 vnfmId=53fbba58-464e-4cc4-8d33-aaaf072f0a27
+
 ###############################################################################
-# End of mandatory properties for driver                                      #
+# Configuration parameters for direct integration
 ###############################################################################
+# skip hostname verification during SSL on CBAM LCN, LCM and authorization interface
+skipHostnameVerificationForAai=true
+# skip certificate verification during SSL on CBAM LCN, LCM and authorization interface
+skipCertificateVerificationForAai=true
+# the collection of trusted certificates for SSL on CBAM LCN, LCM and authorization interface
+# in PEM format encoded in BASE64 to a single line
+trustedCertificatesForAai=
+#The username to access AAI
+aaiUsername=AAI
+#The password to access AAI
+aaiPassword=AAI
+#The username to access SDC
+sdcUsername=SDC
+#The password to access SDC
+sdcPassword=SDC
 
-
+###############################################################################
+# End of mandatory properties for driver                                      #
+###############################################################################
 spring.autoconfigure.exclude=org.springframework.boot.autoconfigure.security.oauth2.OAuth2AutoConfiguration,org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration
 vnfmInfoCacheEvictionInMs=600000
-
 ## for logging begin ##
 com.fasterxml.jackson.core=jackson-databind
 #logging.file=${catalina.base}/logs/vfcadaptor.log
index d9498a2..b34a6a8 100644 (file)
@@ -92,6 +92,26 @@ Release AAI
               </configOptions>
             </configuration>
           </execution>
+          <execution>
+            <id>so</id>
+            <goals>
+              <goal>generate</goal>
+            </goals>
+            <configuration>
+              <inputSpec>${basedir}/src/main/resources/so.vnfm.json</inputSpec>
+              <language>java</language>
+              <library>retrofit2</library>
+              <output>${project.build.directory}/generated-sources/so</output>
+              <apiPackage>org.onap.vnfmadapter.so.api</apiPackage>
+              <modelPackage>org.onap.vnfmadapter.so.model</modelPackage>
+              <configOptions>
+                <jackson>true</jackson>
+                <sourceFolder>src/gen/java/main</sourceFolder>
+                <withXml>true</withXml>
+                <useRxJava2>true</useRxJava2>
+              </configOptions>
+            </configuration>
+          </execution>
           <execution>
             <id>msb</id>
             <goals>
diff --git a/nokiav2/generatedapis/src/main/resources/so.vnfm.json b/nokiav2/generatedapis/src/main/resources/so.vnfm.json
new file mode 100644 (file)
index 0000000..78b8dff
--- /dev/null
@@ -0,0 +1,674 @@
+{
+  "swagger": "2.0",
+  "info": {
+    "version": "1.0.0",
+    "title": "ONAP SO VNFM Adapter API",
+    "description": "Describes the API between SO and the adapter for VNFM",
+    "contact": {
+      "name": "ONAP SO VNFM",
+      "email": "onap-discuss@lists.onap.org",
+      "url": "https://gerrit.onap.org/r/#/admin/projects/vfc/nfvo/lcm"
+    }
+  },
+  "basePath": "/api/v1",
+  "schemes": [
+    "http",
+    "https"
+  ],
+  "consumes": [
+    "application/json"
+  ],
+  "produces": [
+    "application/json"
+  ],
+  "paths": {
+    "/so/{vnfmId}/vnfs": {
+      "post": {
+        "tags": [
+          "SO VNFM Adaptor"
+        ],
+        "summary": "VNF create",
+        "description": "VNF create",
+        "operationId": "vnf_create",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF creation request parameter",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfCreationRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoVnfCreationResponse"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}": {
+      "post": {
+        "tags": [
+          "SO VNFM Adaptor"
+        ],
+        "summary": "VNF activation",
+        "description": "VNF activation",
+        "operationId": "vnf_activate",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "instantiate request param",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfActivationRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      },
+      "delete": {
+        "tags": [
+          "SO VNFM driver"
+        ],
+        "summary": "Deletes VNF",
+        "description": "Deletes the VNF. If the VNF was instantiated VNF termination must be called before VNF deletion",
+        "operationId": "delete_vnf",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          }
+        ],
+        "responses": {
+          "204": {
+            "description": "The VNF was deleted successfully"
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}/scale": {
+      "post": {
+        "tags": [
+          "SO VNFM Adaptor"
+        ],
+        "summary": "VNF scale",
+        "description": "VNF scale request",
+        "operationId": "vnf_scale",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF scale request parameters",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfScaleRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}/customOperation": {
+      "post": {
+        "tags": [
+          "SO VNFM Adaptor"
+        ],
+        "summary": "VNF scale",
+        "description": "VNF scale request",
+        "operationId": "vnf_scale",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF scale request parameters",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfCustomOperation"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}/heal": {
+      "post": {
+        "tags": [
+          "SO VNFM driver"
+        ],
+        "summary": "VNF heal",
+        "description": "VNF heal",
+        "operationId": "vnf_heal",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF heal request parameters",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfHealRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/vnfs/{vnfId}/terminate": {
+      "post": {
+        "tags": [
+          "SO VNFM driver"
+        ],
+        "summary": "VNF terminate",
+        "description": "VNF terminate",
+        "operationId": "vnf_terminate",
+        "consumes": [
+          "application/json"
+        ],
+        "produces": [
+          "application/json"
+        ],
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNF in A&AI",
+            "name": "vnfId",
+            "in": "path"
+          },
+          {
+            "in": "body",
+            "name": "body",
+            "description": "VNF termination request parameters",
+            "required": true,
+            "schema": {
+              "$ref": "#/definitions/SoVnfTerminationRequest"
+            }
+          }
+        ],
+        "responses": {
+          "201": {
+            "description": "",
+            "schema": {
+              "$ref": "#/definitions/SoJobHandler"
+            }
+          }
+        }
+      }
+    },
+    "/so/{vnfmId}/jobs/{jobId}": {
+      "get": {
+        "tags": [
+          "SO VNFM driver"
+        ],
+        "summary": "Query job status",
+        "description": "Query the job status",
+        "operationId": "get_jobstatus",
+        "parameters": [
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the VNFM in A&AI",
+            "name": "vnfmId",
+            "in": "path"
+          },
+          {
+            "required": true,
+            "type": "string",
+            "description": "The identifier of the job",
+            "name": "jobId",
+            "in": "path"
+          }
+        ],
+        "responses": {
+          "202": {
+            "description": "The details of a job",
+            "schema": {
+              "$ref": "#/definitions/SoJobDetail"
+            }
+          },
+          "404": {
+            "description": "The job is unknown to the VNFM. The VNFM does not keep finished jobs for forever.",
+            "schema": {
+              "$ref": "#/definitions/SoJobDetail"
+            }
+          }
+        }
+      }
+    }
+  },
+  "definitions": {
+    "SoJobHandler": {
+      "type": "object",
+      "properties": {
+        "jobId": {
+          "required": true,
+          "description": "The identifier of the job",
+          "type": "string"
+        }
+      }
+    },
+    "SoJobStatus": {
+      "description": "The status of the job",
+      "type": "string",
+      "enum": [
+        "started",
+        "finished",
+        "failed"
+      ]
+    },
+    "SoJobDetail": {
+      "allOf": [
+        {
+          "$ref": "#/definitions/SoJobHandler"
+        },
+        {
+          "type": "object",
+          "properties": {
+            "status": {
+              "required": true,
+              "description": "The status of the job",
+               "$ref": "#/definitions/SoJobStatus"
+            },
+            "description": {
+              "required": true,
+              "description": "The description of the current state of the job",
+              "type": "string"
+            }
+          }
+        }
+      ]
+    },
+    "SoVnfCreationRequest": {
+      "type": "object",
+      "properties": {
+        "name": {
+          "required": true,
+          "description": "The name of the VNF",
+          "type": "string"
+        },
+        "csarId": {
+          "required": true,
+          "description": "The identifier of the VNF package in SDC",
+          "type": "string"
+        },
+        "description": {
+          "required": false,
+          "description": "The description of the VNF",
+          "type": "string"
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoVnfCreationResponse": {
+      "type": "object",
+      "properties": {
+        "vnfId": {
+          "required": true,
+          "description": "The identifier of the created VNF",
+          "type": "string"
+        }
+      }
+    },
+    "SoVduMapping": {
+      "type": "object",
+      "properties": {
+        "vduId": {
+          "required": true,
+          "description": "The identifier of the VDU within the VNF package",
+          "type": "string"
+        },
+        "imageId": {
+          "required": true,
+          "description": "The provider id of the image to be used for the VDU",
+          "type": "string"
+        },
+        "flavourId": {
+          "required": true,
+          "description": "The provider id of the flavour to be used for the VDU",
+          "type": "string"
+        }
+      }
+    },
+    "SoServerMapping": {
+      "type": "object",
+      "description": "Maps a server instance to a VDU and availability zone",
+      "properties": {
+        "vduId": {
+          "required": true,
+          "description": "The identifier of the VDU",
+          "type": "string"
+        },
+        "availabilityZoneId": {
+          "required": false,
+          "description": "The provider id of the availability zone to be used for the server instance",
+          "type": "string"
+        }
+      }
+    },
+    "SoAssignedAddresses": {
+      "type": "object",
+      "properties": {
+        "cpdId" : {
+          "required": true,
+          "description": "The identifier of the connection point descriptor",
+          "type" : "string"
+        },
+        "ipAddress": {
+          "required": true,
+          "description": "The IP address to be used",
+          "type": "string"
+        }
+      }
+    },
+    "SoNetworkMapping": {
+      "type": "object",
+      "properties": {
+        "vldId": {
+          "required": true,
+          "description": "The identifier of the network in the VNF package",
+          "type": "string"
+        },
+        "networkProviderId": {
+          "required": true,
+          "description": "The provider id of the network be used for the given purpose",
+          "type": "string"
+        },
+        "assignedAddresses": {
+          "required": true,
+          "description": "The assigned network addresses",
+          "type" : "array",
+          "items": {
+            "$ref": "#/definitions/SoAssignedAddresses"
+          }
+        }
+      }
+    },
+    "SoVnfActivationRequest": {
+      "type": "object",
+      "properties": {
+        "vimId" : {
+          "required" : true,
+           "type" : "string",
+          "description" : "The identifier of the VIM on which the VNF is to be instantiated"
+        },
+        "serverMappings": {
+          "required": true,
+          "description": "The server mappings",
+          "type" : "array",
+          "items": {
+            "$ref": "#/definitions/SoServerMapping"
+          }
+        },
+        "vduMappings": {
+          "required": true,
+          "description": "The VDU mappings",
+          "type" : "array",
+          "items": {
+            "$ref": "#/definitions/SoVduMapping"
+          }
+        },
+        "networkMappings": {
+          "required": true,
+          "description": "The network mappings",
+          "type" : "array",
+          "items": {
+            "$ref": "#/definitions/SoNetworkMapping"
+          }
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoScaleDirection": {
+      "description": "The direction of the scale",
+      "type": "string",
+      "enum": [
+        "in",
+        "out"
+      ]
+    },
+    "SoVnfScaleRequest": {
+      "type": "object",
+      "properties": {
+        "aspectId": {
+          "type": "string",
+          "description": "The identifier of the scaling aspect in the VNF package"
+        },
+        "steps": {
+          "type": "integer",
+          "description": "The expected absolute scale level"
+        },
+        "direction": {
+          "required": true,
+          "description": "The direction of the scale",
+          "$ref": "#/definitions/SoScaleDirection"
+        },
+        "serverMappings": {
+          "required": true,
+          "description": "The server mappings",
+          "items": {
+            "$ref": "#/definitions/SoServerMapping"
+          }
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoVnfCustomOperation": {
+      "type": "object",
+      "properties": {
+        "operationId": {
+          "required" : true,
+          "type": "string",
+          "description": "The identifier of the custom operation"
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoVnfHealRequest": {
+      "type": "object",
+      "properties": {
+        "vnfcId": {
+          "type": "string",
+          "description": "The identifier of the VNFC to be healed"
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    },
+    "SoTerminationMode": {
+      "description": "The way in which the VNF is terminated",
+      "type": "string",
+      "enum": [
+        "forceful",
+        "graceful"
+      ]
+    },
+    "SoVnfTerminationRequest": {
+      "type": "object",
+      "properties": {
+        "mode" : {
+          "required" : true,
+          "description" : "The VNF termination mode",
+          "$ref": "#/definitions/SoTerminationMode"
+        },
+        "gracefulTerminationTimeoutInMs": {
+          "required" : false,
+          "type": "integer",
+          "description": "The timeout for graceful termination. After the timeout has expired forceful termination is attempted."
+        },
+        "additionalParams": {
+          "description": "Additional VNFM specific parameters",
+          "type": "object",
+          "additionalProperties": true
+        }
+      }
+    }
+  }
+}
index 0670ea9..c9c5fa6 100644 (file)
           "type": "string",
           "description": "vendor name"
         },
+        "domain": {
+          "type": "string",
+          "description": "domain"
+        },
         "version": {
           "type": "string",
           "description": "vim version"