From 2c1179b657efe2a291012d2b8f2eee2179402d27 Mon Sep 17 00:00:00 2001 From: Denes Nemeth Date: Tue, 3 Apr 2018 17:32:13 +0200 Subject: Fixes in LCM Change-Id: I9dfdacf32970c86b595939f6cd92b6eb276ebf90 Issue-ID: VFC-728 Signed-off-by: Denes Nemeth --- nokiav2/.gitignore | 1 + .../src/main/resources/application.properties | 18 + nokiav2/docs/development.rst | 28 + nokiav2/docs/integration.rst | 81 +-- nokiav2/docs/so.rst | 16 + nokiav2/docs/vnfintegration.rst | 5 +- .../nokia/onap/direct/AAIRestApiProvider.java | 3 - .../onap/direct/notification/VnfcManager.java | 10 + .../svnfm/nokia/onap/so/SoLifecycleManager.java | 327 ++++++++++ .../vnfm/svnfm/nokia/onap/so/package-info.java | 20 + .../driver/vnfm/svnfm/nokia/restapi/LcmApi.java | 8 +- .../driver/vnfm/svnfm/nokia/restapi/SoApi.java | 175 +++++ .../vnfm/svnfm/nokia/util/SystemFunctions.java | 2 +- .../svnfm/nokia/vnfm/AdditionalParameters.java | 19 +- .../vnfm/svnfm/nokia/vnfm/LifecycleManager.java | 181 ++++-- .../driver/src/main/resources/self.swagger.json | 707 ++++++++++++++++++++- .../nokia/onap/direct/TestAAIRestApiProvider.java | 1 - .../onap/direct/notification/TestVnfcManager.java | 10 +- .../nokia/onap/so/TestSoLifecycleManager.java | 514 +++++++++++++++ .../restapi/TestSwaggerDefinitionConsistency.java | 24 +- .../svnfm/nokia/vnfm/TestLifecycleManager.java | 79 ++- .../test/resources/application-direct.properties | 18 +- .../src/test/resources/application.properties | 23 +- nokiav2/generatedapis/pom.xml | 20 + .../generatedapis/src/main/resources/so.vnfm.json | 674 ++++++++++++++++++++ .../src/main/resources/vfc.vnfdriver.swagger.json | 4 + 26 files changed, 2787 insertions(+), 181 deletions(-) create mode 100644 nokiav2/docs/development.rst create mode 100644 nokiav2/docs/so.rst create mode 100644 nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoLifecycleManager.java create mode 100644 nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/package-info.java create mode 100644 nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoApi.java create mode 100644 nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/TestSoLifecycleManager.java create mode 100644 nokiav2/generatedapis/src/main/resources/so.vnfm.json (limited to 'nokiav2') diff --git a/nokiav2/.gitignore b/nokiav2/.gitignore index 88783a3b..8d01eac6 100644 --- a/nokiav2/.gitignore +++ b/nokiav2/.gitignore @@ -5,3 +5,4 @@ bin tmp logs debug-logs +NOTES.internal.txt diff --git a/nokiav2/deployment/src/main/resources/application.properties b/nokiav2/deployment/src/main/resources/application.properties index c467e765..d52ed498 100644 --- a/nokiav2/deployment/src/main/resources/application.properties +++ b/nokiav2/deployment/src/main/resources/application.properties @@ -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 index 00000000..f0bcc714 --- /dev/null +++ b/nokiav2/docs/development.rst @@ -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 + diff --git a/nokiav2/docs/integration.rst b/nokiav2/docs/integration.rst index 2c02b759..303a2016 100644 --- a/nokiav2/docs/integration.rst +++ b/nokiav2/docs/integration.rst @@ -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:///auth/admin with admin username and password from previous step and change password (save the changed password) + - Log into keycloak https:///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 - 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 | ++===================+=================================+ +| | portal.api.simpledemo.onap.org | ++-------------------+---------------------------------+ +| | policy.api.simpledemo.onap.org | ++-------------------+---------------------------------+ +| | sdc.api.simpledemo.onap.org | ++-------------------+---------------------------------+ +| | vid.api.simpledemo.onap.org | ++-------------------+---------------------------------+ +| | aai.api.simpledemo.onap.org | ++-------------------+---------------------------------+ +| | msb.api.simpledemo.onap.org | ++-------------------+---------------------------------+ +| | 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///tenants/tenant/ + 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 - - Download the cbam driver into ONAP multi service node - - Load the image into docker and note the image identifier - -.. 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= 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 index 00000000..1f18d94a --- /dev/null +++ b/nokiav2/docs/so.rst @@ -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 _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 diff --git a/nokiav2/docs/vnfintegration.rst b/nokiav2/docs/vnfintegration.rst index 62674e53..a846b265 100644 --- a/nokiav2/docs/vnfintegration.rst +++ b/nokiav2/docs/vnfintegration.rst @@ -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) diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/AAIRestApiProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/AAIRestApiProvider.java index 14bdea11..08bf2c41 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/AAIRestApiProvider.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/AAIRestApiProvider.java @@ -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; diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/VnfcManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/VnfcManager.java index bc31f4fe..db65d2f1 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/VnfcManager.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/VnfcManager.java @@ -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 index 00000000..c6e07e83 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/SoLifecycleManager.java @@ -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 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 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 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 index 00000000..0e29b927 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/package-info.java @@ -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; diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcmApi.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcmApi.java index f7c9ed10..92148029 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcmApi.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcmApi.java @@ -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 index 00000000..b2c833bb --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SoApi.java @@ -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); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/SystemFunctions.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/SystemFunctions.java index b67c7863..22d4c20d 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/SystemFunctions.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/SystemFunctions.java @@ -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. - *

+ * *

See the description of the class Date for * a discussion of slight discrepancies that may arise between * Unable to load /unittests/missing * "computer time" and coordinated universal time (UTC). diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java index f585a6a2..1ec129ea 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParameters.java @@ -24,7 +24,6 @@ import java.util.*; */ public class AdditionalParameters { private VimInfoTypeEnum vimType; - private String domain; private String instantiationLevel; private List computeResourceFlavours = new ArrayList<>(); private List 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 + diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java index 94ab240a..5cd11058 100644 --- a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java @@ -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 *

    @@ -123,7 +126,7 @@ public class LifecycleManager { * The rollback of the failed operation is not implemented *
      *
    • delete the VNF if error occurs before instantiation
    • - *
    • terminate & delete VNF if error occurs after instantiation
    • + *
    • terminateVnf & delete VNF if error occurs after instantiation
    • *
    * * @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 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 *
      *
    • delete the VNF if error occurs before instantiation
    • - *
    • terminate & delete VNf if error occurs after instantiation
    • + *
    • terminateVnf & delete VNf if error occurs after instantiation
    • *
    * * @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 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 + *
      + *
    • fails if the VNF does not exist
    • + *
    • terminates if instantiated
    • + *
    • deletes the VNF
    • + *
    + * + * @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; + } } } diff --git a/nokiav2/driver/src/main/resources/self.swagger.json b/nokiav2/driver/src/main/resources/self.swagger.json index f8d24a0b..64041502 100644 --- a/nokiav2/driver/src/main/resources/self.swagger.json +++ b/nokiav2/driver/src/main/resources/self.swagger.json @@ -18,9 +18,293 @@ }, "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": { @@ -294,35 +578,35 @@ ], "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": { @@ -693,7 +977,7 @@ } } }, - "/lcn":{ + "/lcn": { "get": { "tags": [ "SBI" @@ -752,13 +1036,13 @@ "tags": [ "Utilities" ], - "consumes":[ + "consumes": [ "multipart/form-data" ], - "produces":[ + "produces": [ "application/octet-stream" ], - "parameters" : [ + "parameters": [ { "description": "The CBAM VNF package", "in": "formData", @@ -771,7 +1055,7 @@ "responses": { "200": { "description": "The converted package", - "schema":{ + "schema": { "type": "file" } } @@ -781,7 +1065,7 @@ "tags": [ "Utilities" ], - "produces":[ + "produces": [ "text/html" ], "summary": "UI to convert the Nokia CBAM package to ONAP package", @@ -792,7 +1076,362 @@ } } } - + }, + "/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" + } + } + } + } } } } diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/TestAAIRestApiProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/TestAAIRestApiProvider.java index a97b74d5..bd5e42f1 100644 --- a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/TestAAIRestApiProvider.java +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/TestAAIRestApiProvider.java @@ -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 implements Answer { private T result = null; diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/TestVnfcManager.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/TestVnfcManager.java index ece65ee6..4c382113 100644 --- a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/TestVnfcManager.java +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/direct/notification/TestVnfcManager.java @@ -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 index 00000000..ebc2159d --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/so/TestSoLifecycleManager.java @@ -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> extLinks = ArgumentCaptor.forClass(List.class); + ArgumentCaptor 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> extLinks = ArgumentCaptor.forClass(List.class); + ArgumentCaptor 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> extLinks = ArgumentCaptor.forClass(List.class); + ArgumentCaptor 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> extLinks = ArgumentCaptor.forClass(List.class); + ArgumentCaptor 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> extLinks = ArgumentCaptor.forClass(List.class); + ArgumentCaptor 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> extLinks = ArgumentCaptor.forClass(List.class); + ArgumentCaptor 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 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 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 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 diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerDefinitionConsistency.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerDefinitionConsistency.java index f88305a0..d39a1445 100644 --- a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerDefinitionConsistency.java +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerDefinitionConsistency.java @@ -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> CLASSES = Sets.newHashSet(LcmApi.class, LcnApi.class, SwaggerApi.class, ConverterApi.class); + public static final HashSet> 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 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); } } diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestLifecycleManager.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestLifecycleManager.java index 16d1f021..7078e02d 100644 --- a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestLifecycleManager.java +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestLifecycleManager.java @@ -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 operationExecutions = new ArrayList<>(); @@ -100,6 +102,8 @@ public class TestLifecycleManager extends TestBase { private Set finished = new HashSet<>(); private ArgumentCaptor actualScaleRequest = ArgumentCaptor.forClass(ScaleVnfRequest.class); private ArgumentCaptor actualHealRequest = ArgumentCaptor.forClass(HealVnfRequest.class); + private ArgumentCaptor customOperationRequestArgumentCaptor = ArgumentCaptor.forClass(CustomOperationRequest.class); + private ArgumentCaptor 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>() { + @Override + public Observable 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 actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer>() { + @Override + public Observable 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 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); diff --git a/nokiav2/driver/src/test/resources/application-direct.properties b/nokiav2/driver/src/test/resources/application-direct.properties index f933db94..27ce13e0 100644 --- a/nokiav2/driver/src/test/resources/application-direct.properties +++ b/nokiav2/driver/src/test/resources/application-direct.properties @@ -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 diff --git a/nokiav2/driver/src/test/resources/application.properties b/nokiav2/driver/src/test/resources/application.properties index f5c42fc0..8446b483 100644 --- a/nokiav2/driver/src/test/resources/application.properties +++ b/nokiav2/driver/src/test/resources/application.properties @@ -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 diff --git a/nokiav2/generatedapis/pom.xml b/nokiav2/generatedapis/pom.xml index d9498a26..b34a6a88 100644 --- a/nokiav2/generatedapis/pom.xml +++ b/nokiav2/generatedapis/pom.xml @@ -92,6 +92,26 @@ Release AAI + + so + + generate + + + ${basedir}/src/main/resources/so.vnfm.json + java + retrofit2 + ${project.build.directory}/generated-sources/so + org.onap.vnfmadapter.so.api + org.onap.vnfmadapter.so.model + + true + src/gen/java/main + true + true + + + msb diff --git a/nokiav2/generatedapis/src/main/resources/so.vnfm.json b/nokiav2/generatedapis/src/main/resources/so.vnfm.json new file mode 100644 index 00000000..78b8dffd --- /dev/null +++ b/nokiav2/generatedapis/src/main/resources/so.vnfm.json @@ -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 + } + } + } + } +} diff --git a/nokiav2/generatedapis/src/main/resources/vfc.vnfdriver.swagger.json b/nokiav2/generatedapis/src/main/resources/vfc.vnfdriver.swagger.json index 0670ea98..c9c5fa6d 100644 --- a/nokiav2/generatedapis/src/main/resources/vfc.vnfdriver.swagger.json +++ b/nokiav2/generatedapis/src/main/resources/vfc.vnfdriver.swagger.json @@ -1355,6 +1355,10 @@ "type": "string", "description": "vendor name" }, + "domain": { + "type": "string", + "description": "domain" + }, "version": { "type": "string", "description": "vim version" -- cgit 1.2.3-korg