diff options
author | Denes Nemeth <denes.nemeth@nokia.com> | 2018-02-12 20:55:54 +0100 |
---|---|---|
committer | Denes Nemeth <denes.nemeth@nokia.com> | 2018-02-23 11:44:45 +0100 |
commit | b17042b955489d8a023d09abad5436ff9b900dc3 (patch) | |
tree | 1e4392ac04a2fb1ed8d17075d504cf6594acaf16 /nokiav2/driver | |
parent | d4982f7b1777e9cdae9a4cc7d0d104263889ac69 (diff) |
Updating Nokia driver
Change-Id: I950afe6acbdb359cd67a448024f006a45e8fc293
Signed-off-by: Denes Nemeth <denes.nemeth@nokia.com>
Issue-ID: VFC-728
Diffstat (limited to 'nokiav2/driver')
122 files changed, 15053 insertions, 0 deletions
diff --git a/nokiav2/driver/pom.xml b/nokiav2/driver/pom.xml new file mode 100644 index 00000000..e770f3e4 --- /dev/null +++ b/nokiav2/driver/pom.xml @@ -0,0 +1,121 @@ +<?xml version="1.0"?> +<!-- + 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. + --> +<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> + <modelVersion>4.0.0</modelVersion> + <artifactId>driver</artifactId> + <version>1.1.0-SNAPSHOT</version> + <packaging>jar</packaging> + <name>vfc/nfvo/driver/vnfm/svnfm/nokiav2/driver</name> + <description>svnfm vnfm driver</description> + <parent> + <groupId>org.onap.vfc.nfvo.driver.vnfm.svnfm.nokiav2</groupId> + <artifactId>vfc-nfvo-driver-vnfm-svnfm-nokiav2</artifactId> + <version>1.1.0-SNAPSHOT</version> + </parent> + <properties> + <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> + <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> + <java.version>1.8</java.version> + </properties> + <dependencies> + <dependency> + <groupId>org.onap.vfc.nfvo.driver.vnfm.svnfm.nokiav2</groupId> + <artifactId>vfc-nfvo-driver-vnfm-svnfm-nokiav2-clients</artifactId> + <version>1.1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-web</artifactId> + <version>1.5.10.RELEASE</version> + <scope>provided</scope> + </dependency> + <dependency> + <groupId>org.springframework.boot</groupId> + <artifactId>spring-boot-starter-test</artifactId> + <version>1.5.10.RELEASE</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>com.google.guava</groupId> + <artifactId>guava</artifactId> + <version>20.0</version> + <!-- parsing VNFDs --> + </dependency> + <dependency> + <groupId>org.yaml</groupId> + <artifactId>snakeyaml</artifactId> + <version>1.19</version> + </dependency> + <dependency> + <!-- this does not have a compile time dependency, but is required to be able to deserialize the date to joda time --> + <groupId>com.fasterxml.jackson.dataformat</groupId> + <artifactId>jackson-dataformat-yaml</artifactId> + <!-- this version must be in sync with the dependency comming from spring boot --> + <version>2.8.10</version> + </dependency> + <!-- access MSB during registration --> + <dependency> + <groupId>org.onap.msb.java-sdk</groupId> + <artifactId>msb-java-sdk</artifactId> + <version>1.1.0-SNAPSHOT</version> + </dependency> + <dependency> + <groupId>pl.pojo</groupId> + <artifactId>pojo-tester</artifactId> + <version>0.7.6</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.eclipse.jetty</groupId> + <artifactId>jetty-server</artifactId> + <version>9.4.8.v20171121</version> + <scope>test</scope> + </dependency> + <dependency> + <groupId>org.jetbrains</groupId> + <artifactId>annotations</artifactId> + <version>RELEASE</version> + </dependency> + <dependency> + <groupId>org.onap.aai.aai-common</groupId> + <artifactId>aai-schema</artifactId> + <version>1.2.0</version> + </dependency> + <dependency> + <groupId>org.onap.aai</groupId> + <artifactId>rest-client</artifactId> + <version>1.2.0</version> + </dependency> + </dependencies> + <build> + <plugins> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-compiler-plugin</artifactId> + <version>3.5</version> + <configuration> + <source>1.8</source> + <target>1.8</target> + </configuration> + </plugin> + <plugin> + <groupId>org.apache.maven.plugins</groupId> + <artifactId>maven-surefire-plugin</artifactId> + </plugin> + </plugins> + </build> +</project> diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/NokiaSvnfmApplication.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/NokiaSvnfmApplication.java new file mode 100644 index 00000000..e75159f6 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/NokiaSvnfmApplication.java @@ -0,0 +1,98 @@ +/* + * 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; + +import org.apache.log4j.Logger; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.JobManager; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.SpringApplication; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.ApplicationListener; +import org.springframework.context.annotation.Profile; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.stereotype.Component; + +/** + * Represents the spring boot application + */ +@SpringBootApplication +public class NokiaSvnfmApplication { + private static Logger logger = Logger.getLogger(NokiaSvnfmApplication.class); + + /** + * Entry point for the Spring boot application + * + * @param args arguments for the application (not used) + */ + public static void main(String[] args) { + SpringApplication.run(NokiaSvnfmApplication.class, args); + } + + /** + * Responsible for starting the self registration process after the servlet has been started + * and is ready to answer REST request + * - has been disabled in the test because the application that provides the ONAP simulator + * has already not yet been started (can not answer REST requests) + */ + @Component + @Profile("!test") + public static class SelfRegistrationTrigger implements ApplicationListener<ApplicationReadyEvent> { + @Autowired + private SelfRegistrationManager selfRegistrationManager; + + @Override + public void onApplicationEvent(ApplicationReadyEvent contextRefreshedEvent) { + logger.info("Self registration started"); + try { + selfRegistrationManager.register(); + logger.info("Self registration finished"); + } catch (RuntimeException e) { + logger.error("Self registration failed", e); + throw e; + } + } + } + + /** + * Responsible for starting the un-registration process after the service has been ramped down + * - has been disabled in test because the same application that provides the ONAP simulator + * has already been ramped down (can not answer REST requests) + */ + @Component + @Profile("!test") + public static class SelfDeRegistrationTrigger implements ApplicationListener<ContextClosedEvent> { + @Autowired + private SelfRegistrationManager selfRegistrationManager; + @Autowired + private JobManager jobManager; + + @Override + public void onApplicationEvent(ContextClosedEvent contextClosedEvent) { + logger.info("Self de-registration started"); + try { + jobManager.prepareForShutdown(); + selfRegistrationManager.deRegister(); + } catch (RuntimeException e) { + logger.error("Self de-registration failed", e); + throw e; + } + logger.info("Self de-registration finished"); + } + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/IGrantManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/IGrantManager.java new file mode 100644 index 00000000..d851215d --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/IGrantManager.java @@ -0,0 +1,81 @@ +/* + * 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.api; + +import com.nokia.cbam.lcm.v32.model.VnfInfo; +import org.onap.vnfmdriver.model.GrantVNFResponseVim; +import org.onap.vnfmdriver.model.VnfHealRequest; +import org.onap.vnfmdriver.model.VnfScaleRequest; + +/** + * Responsible for requesting grants during various LCM operations + */ +public interface IGrantManager { + + /** + * Request grant for healing + * - the affected virtual machine is added twice to the grant request (add & remove) to + * signal that it is temporary removed + * - the grant response is only used make a binary decision + * + * @param vnfmId the identifier of the VNFM + * @param vnfId the identifier of the VNF + * @param vimId the identifier of the VIM + * @param request the heal request + * @param jobId the identifier of the job that triggered the grant + */ + void requestGrantForHeal(String vnfmId, String vnfId, String vimId, String onapCsarId, VnfHealRequest request, String jobId); + + /** + * Request grant for scaling + * - the affected virtual machines are calculated from the Heat mapping section of the corresponding aspect + * - the grant response is only used make a binary decision + * + * @param vnfmId the identifier of the VNFM + * @param vnfId the identifier of the VNF + * @param vimId the identifier of the VIM + * @param onapCsarId the CSAR ID of the ONAP + * @param request the scaling request + * @param jobId the identifier of the job that triggered the grant + */ + void requestGrantForScale(String vnfmId, String vnfId, String vimId, String onapCsarId, VnfScaleRequest request, String jobId); + + /** + * Request grant for termination + * - the resources removed is the previously deployed resources based on VNF query + * - the grant response is only used make a binary decision + * + * @param vnfmId the identifier of the VNFM + * @param vnfId the identifier of the VNF + * @param vimId the identifier of the VIM + */ + void requestGrantForTerminate(String vnfmId, String vnfId, String vimId, String onapVnfdId, VnfInfo vnf, String jobId); + + /** + * Request grant for instantiation + * - the added resources are calculated from the VNFD by counting the VDUs in the selected the instantiation level + * - the only parameter used from the grant response in the VIM to which the VNF is to be deployed to + * + * @param vnfmId the identifier of the VNFM + * @param vnfId the identifier of the VNF + * @param vimId the identifier of the VIM + * @param onapVnfdId the identifier of the VNF package in ONAP + * @param instantiationLevelId the instantiation level + * @param cbamVnfdContent the content of the CBAM VNFD + * @return the grant response + */ + GrantVNFResponseVim requestGrantForInstantiate(String vnfmId, String vnfId, String vimId, String onapVnfdId, String instantiationLevelId, String cbamVnfdContent, String jobId); +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/INotificationSender.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/INotificationSender.java new file mode 100644 index 00000000..92099cc3 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/INotificationSender.java @@ -0,0 +1,36 @@ +/* + * 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.api; + +import com.nokia.cbam.lcm.v32.model.OperationExecution; +import com.nokia.cbam.lcm.v32.model.VnfLifecycleChangeNotification; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.ReportedAffectedConnectionPoints; + +/** + * Responsible for processing the preprocessed notification from CBAM and making the changes + * based on the notification in various ONAP sub systems. + */ +public interface INotificationSender { + /** + * Execute changes in the ONAP subsystem based on the received notification + * + * @param receivedNotification the notification from CBAM + * @param operationExecution the executed operation that triggered the LCN + * @param affectedConnectionPoints the affected connection points during the operation + * @param vimId the identifier of the VIM in ONAP + */ + void processNotification(VnfLifecycleChangeNotification receivedNotification, OperationExecution operationExecution, ReportedAffectedConnectionPoints affectedConnectionPoints, String vimId); +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/IPackageProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/IPackageProvider.java new file mode 100644 index 00000000..a652354d --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/IPackageProvider.java @@ -0,0 +1,40 @@ +/* + * 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.api; + +/** + * Provides a VNF package from ONAP repositories + */ +public interface IPackageProvider { + /** + * The location of the CBAM package within the ONAP package + */ + String CBAM_PACKAGE_NAME_IN_ZIP = "Artifacts/Deployment/OTHER/cbam.package.zip"; + + /** + * Download the package from ONAP + * + * @param csarId the CSAR identifier of the package in ONAP + * @return the binary content of the package + */ + byte[] getPackage(String csarId); + + /** + * @param csarId the CSAR identifier of the package in ONAP + * @return the identifier of the package in CBAM + */ + String getCbamVnfdId(String csarId); +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/VimInfoProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/VimInfoProvider.java new file mode 100644 index 00000000..111f44b3 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/VimInfoProvider.java @@ -0,0 +1,30 @@ +/* + * 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.api; + +import org.onap.vnfmdriver.model.VimInfo; + +/** + * Responsible for providing information from the VIM to be used for the VNF + */ +public interface VimInfoProvider { + + /** + * @param vimId the identifier of the VIM + * @return the description of the VIM + */ + VimInfo getVimInfo(String vimId); +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/VnfmInfoProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/VnfmInfoProvider.java new file mode 100644 index 00000000..cfcb1d41 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/VnfmInfoProvider.java @@ -0,0 +1,40 @@ +/* + * 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.api; + +import org.onap.vnfmdriver.model.VnfmInfo; + +/** + * Responsible for providing information from the VNFM itself + */ +public interface VnfmInfoProvider { + + /** + * The name of the VNFM info cache eviction in the properties file + */ + String VNFM_INFO_CACHE_EVICTION_IN_MS = "vnfmInfoCacheEvictionInMs"; + + /** + * The default VNFM info cache eviction in milliseconds + */ + int DEFAULT_CACHE_EVICTION_TIMEOUT_IN_MS = 10 * 60 * 1000; + + /** + * @param vnfmId the identifier of the VNFM + * @return the description of the VNFM + */ + VnfmInfo getVnfmInfo(String vnfmId); +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/package-info.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/package-info.java new file mode 100644 index 00000000..4463b26a --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/api/package-info.java @@ -0,0 +1,21 @@ +/* + * 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. + */ + +/** + * The collection of interfaces to connect to core systems. The + * driver is able to interface with VF-C xor with SDC, A&AI directly. + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api; diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/GenericExternalSystemInfoProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/GenericExternalSystemInfoProvider.java new file mode 100644 index 00000000..3e1e05a5 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/GenericExternalSystemInfoProvider.java @@ -0,0 +1,83 @@ +/* + * 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.core; + +import com.google.common.cache.CacheLoader; +import com.google.common.cache.LoadingCache; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VimInfoProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VnfmInfoProvider; +import org.onap.vnfmdriver.model.VnfmInfo; +import org.slf4j.Logger; +import org.springframework.beans.factory.InitializingBean; +import org.springframework.core.env.Environment; + +import java.util.concurrent.TimeUnit; + +import static com.google.common.cache.CacheBuilder.newBuilder; +import static java.lang.Long.valueOf; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Responsible for providing access to core systems + */ +abstract public class GenericExternalSystemInfoProvider extends IpMappingProvider implements VnfmInfoProvider, VimInfoProvider, InitializingBean { + private static Logger logger = getLogger(GenericExternalSystemInfoProvider.class); + private final Environment environment; + private LoadingCache<String, VnfmInfo> vnfmInfoCache; + + public GenericExternalSystemInfoProvider(Environment environment) { + super(environment); + this.environment = environment; + } + + /** + * After the Bean has been initialized the IP mapping and the VMFM cache is initialized + * It is done in this phase because the logic requires the the @Value anoted fields to + * be specified + */ + @Override + public void afterPropertiesSet() throws Exception { + super.afterPropertiesSet(); + vnfmInfoCache = newBuilder().expireAfterWrite(environment.getProperty(VNFM_INFO_CACHE_EVICTION_IN_MS, Long.class, valueOf(DEFAULT_CACHE_EVICTION_TIMEOUT_IN_MS)), TimeUnit.MILLISECONDS).concurrencyLevel(1).build(new CacheLoader<String, VnfmInfo>() { + @Override + public VnfmInfo load(String vnfmId) throws Exception { + logger.info("Quering VNFM info from source with " + vnfmId + " identifier"); + return queryVnfmInfoFromSource(vnfmId); + } + }); + } + + /* + * @param vnfmId the identifier of the VNFM + * @return the cached VNFM + */ + public VnfmInfo getVnfmInfo(String vnfmId) { + try { + return vnfmInfoCache.get(vnfmId); + } catch (Exception e) { + throw fatalFailure(logger, "Unable to query VNFM info for " + vnfmId, e); + } + } + + /** + * Load the information related to the VNFM from the remote source + * + * @param vnfmId the identifier of the VNFM + * @return the description of the VNFM + */ + public abstract VnfmInfo queryVnfmInfoFromSource(String vnfmId); +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/IpMappingProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/IpMappingProvider.java new file mode 100644 index 00000000..a2472283 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/IpMappingProvider.java @@ -0,0 +1,69 @@ +/* + * 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.core; + +import org.springframework.beans.factory.InitializingBean; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashMap; +import java.util.Map; +import java.util.function.Consumer; + +import static com.google.common.base.Splitter.on; +import static com.google.common.collect.Lists.newArrayList; + +/** + * Responsible for remapping IP/DNS names in URLs based on property file + */ +@Component +public class IpMappingProvider implements InitializingBean { + public static final String IP_MAP = "ipMap"; + private final Environment environment; + private final Map<String, String> ipMap = new HashMap<>(); + + @Autowired + IpMappingProvider(Environment environment) { + this.environment = environment; + } + + /** + * After the Bean has been initialized the IP mapping and the VMFM cache is initialized + * It is done in this phase because it requires the environment to be initialized + */ + @Override + public void afterPropertiesSet() throws Exception { + on(",").trimResults().omitEmptyStrings().split(environment.getProperty(IP_MAP, String.class, "")).forEach(new Consumer<String>() { + @Override + public void accept(String item) { + ArrayList<String> ip = newArrayList(on("->").trimResults().split(item)); + ipMap.put(ip.get(0), ip.get(1)); + } + }); + } + + /** + * Map IP addresses based on configuration parameter ipMap + * + * @param ip the original IP address + * @return the mapped IP address + */ + public String mapPrivateIpToPublicIp(String ip) { + return ipMap.getOrDefault(ip, ip); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/MsbApiProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/MsbApiProvider.java new file mode 100644 index 00000000..b6f4644a --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/MsbApiProvider.java @@ -0,0 +1,85 @@ +/* + * 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.core; + +import org.onap.msb.sdk.discovery.common.RouteException; +import org.onap.msb.sdk.discovery.entity.MicroServiceFullInfo; +import org.onap.msb.sdk.discovery.entity.NodeInfo; +import org.onap.msb.sdk.httpclient.msb.MSBServiceClient; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import static java.lang.Integer.valueOf; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Responsible for providing REST client to access MSB API + */ +@Component +public class MsbApiProvider extends IpMappingProvider { + private static Logger logger = getLogger(MsbApiProvider.class); + @Value("${messageBusIp}") + private String messageBusIp; + @Value("${messageBusPort}") + private String messageBusPort; + + @Autowired + MsbApiProvider(Environment environment) { + super(environment); + } + + /** + * @return API to access ONAP MSB + */ + public MSBServiceClient getMsbClient() { + return new MSBServiceClient(messageBusIp, valueOf(messageBusPort)); + } + + /** + * @param name the name of the micro service + * @param version the version of the micro service + * @return the base URL of the micro service (ex. https://1.2.3.4/path ) + */ + public String getMicroServiceUrl(String name, String version) { + MicroServiceFullInfo microServiceFullInfo = getMicroServiceInfo(name, version); + String protocol = "http://"; //FIXME the enable_ssl field should be used, but it is not available in SDK + String ipAnPort = getNodeIpAnPort(microServiceFullInfo); + //the field name in A&AI is misleading the URL is relative path postfixed to http(s)://ip:port + String fullUrl = protocol + ipAnPort + microServiceFullInfo.getUrl(); + return fullUrl; + } + + private MicroServiceFullInfo getMicroServiceInfo(String name, String version) throws RuntimeException { + try { + return getMsbClient().queryMicroServiceInfo(name, version); + } catch (RouteException e) { + throw fatalFailure(logger, "Unable to get micro service URL for " + name + " with version " + version, e); + } + } + + private String getNodeIpAnPort(MicroServiceFullInfo microServiceFullInfo) { + for (NodeInfo nodeInfo : microServiceFullInfo.getNodes()) { + if (!nodeInfo.getIp().startsWith("172.")) { // FIXME how to know which of the multiple addresses to use? + return mapPrivateIpToPublicIp(nodeInfo.getIp()) + ":" + nodeInfo.getPort(); + } + } + throw fatalFailure(logger, "The " + microServiceFullInfo.getServiceName() + " service with " + microServiceFullInfo.getVersion() + " does not have any valid nodes" + microServiceFullInfo.getNodes()); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/SelfRegistrationManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/SelfRegistrationManager.java new file mode 100644 index 00000000..3b2f1d34 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/SelfRegistrationManager.java @@ -0,0 +1,194 @@ +/* + * 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.core; + +import com.nokia.cbam.lcn.v32.ApiException; +import com.nokia.cbam.lcn.v32.api.SubscriptionsApi; +import com.nokia.cbam.lcn.v32.model.*; +import org.onap.msb.sdk.discovery.common.RouteException; +import org.onap.msb.sdk.discovery.entity.MicroServiceFullInfo; +import org.onap.msb.sdk.discovery.entity.MicroServiceInfo; +import org.onap.msb.sdk.discovery.entity.Node; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.DriverProperties; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.HashSet; + +import static com.nokia.cbam.lcn.v32.model.SubscriptionAuthentication.TypeEnum.NONE; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCN_API_VERSION; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Responsible for registering the driver in the core systems. + */ +@Component +public class SelfRegistrationManager { + public static final String DRIVER_VERSION = "v1"; + public static final String SERVICE_NAME = "NokiaSVNFM"; + // 1 means internal 0 means core :) + public static final String INTERNAL_SERVICE = "1"; + public static final String SWAGGER_API_DEFINITION = "self.swagger.json"; + private static Logger logger = getLogger(SelfRegistrationManager.class); + private final DriverProperties driverProperties; + private final MsbApiProvider msbApiProvider; + private final CbamRestApiProvider cbamRestApiProvider; + + @Value("${driverMsbExternalIp}") + private String driverMsbExternalIp; + @Value("${driverVnfmExternalIp}") + private String driverVnfmExternalIp; + @Value("${server.port}") + private String driverPort; + private volatile boolean ready = false; + + @Autowired + SelfRegistrationManager(DriverProperties driverProperties, MsbApiProvider msbApiProvider, CbamRestApiProvider cbamRestApiProvider) { + this.cbamRestApiProvider = cbamRestApiProvider; + this.msbApiProvider = msbApiProvider; + this.driverProperties = driverProperties; + } + + /** + * Register the driver in micro-service bus and subscribe to LCNs from CBAM + */ + public void register() { + //the order is important (only publish it's existence after the subscription has been created) + subscribeToLcn(driverProperties.getVnfmId()); + try { + registerMicroService(); + } catch (RuntimeException e) { + deleteSubscription(driverProperties.getVnfmId()); + throw e; + } + ready = true; + } + + /** + * De-register the VNFM driver from the micro-service bus + */ + public void deRegister() { + try { + logger.info("Cancelling micro service registration"); + msbApiProvider.getMsbClient().cancelMicroServiceInfo(SERVICE_NAME, DRIVER_VERSION); + } catch (RouteException e) { + //ONAP throws 500 internal server error, but deletes the micro service + try { + MicroServiceFullInfo microServiceFullInfo = msbApiProvider.getMsbClient().queryMicroServiceInfo(SERVICE_NAME, DRIVER_VERSION); + logger.error("Unable to deRegister Nokia VNFM driver", e); + //the micro service still exists + throw new RuntimeException(e); + } catch (RouteException e1) { + // the micro service was deleted (even though 500 HTTP code was reported) + } + } + deleteSubscription(driverProperties.getVnfmId()); + } + + /** + * @return the swagger API definition + */ + public byte[] getSwaggerApiDefinition() { + return SystemFunctions.systemFunctions().loadFile(SWAGGER_API_DEFINITION); + } + + private String getDriverVnfmUrl() { + return "http://" + driverVnfmExternalIp + ":" + driverPort + DriverProperties.BASE_URL; + } + + private void deleteSubscription(String vnfmId) { + logger.info("Deleting CBAM LCN subscription"); + SubscriptionsApi lcnApi = cbamRestApiProvider.getCbamLcnApi(vnfmId); + try { + String callbackUrl = getDriverVnfmUrl() + DriverProperties.LCN_PATH; + for (Subscription subscription : lcnApi.subscriptionsGet(NOKIA_LCN_API_VERSION)) { + if (subscription.getCallbackUrl().equals(callbackUrl)) { + lcnApi.subscriptionsSubscriptionIdDelete(subscription.getId(), NOKIA_LCN_API_VERSION); + } + } + } catch (ApiException e) { + logger.error("Unable to delete CBAM LCN subscription"); + throw new RuntimeException(e); + } + } + + private MicroServiceFullInfo registerMicroService() { + logger.info("Registering micro service"); + MicroServiceInfo microServiceInfo = new MicroServiceInfo(); + microServiceInfo.setUrl(DriverProperties.BASE_URL); + //the PATH should not be set + microServiceInfo.setProtocol("REST"); + microServiceInfo.setVisualRange(INTERNAL_SERVICE); + microServiceInfo.setServiceName(SERVICE_NAME); + microServiceInfo.setVersion(DRIVER_VERSION); + //FIXME set enable_ssl to false after the field has been added to MSB SDK + //currently defaults to false, which is good + Node node = new Node(); + microServiceInfo.setNodes(new HashSet<>()); + microServiceInfo.getNodes().add(node); + node.setIp(driverMsbExternalIp); + node.setPort(driverPort); + node.setTtl("0"); + try { + return msbApiProvider.getMsbClient().registerMicroServiceInfo(microServiceInfo); + } catch (RouteException e) { + logger.error("Unable to register Nokia VNFM driver", e); + throw new RuntimeException(e); + } + } + + private void subscribeToLcn(String vnfmId) { + String callbackUrl = getDriverVnfmUrl() + DriverProperties.LCN_PATH; + logger.info("Subscribing to CBAM LCN " + driverProperties.getCbamLcnUrl() + " with callback to " + callbackUrl); + SubscriptionsApi lcnApi = cbamRestApiProvider.getCbamLcnApi(vnfmId); + try { + for (Subscription subscription : lcnApi.subscriptionsGet(NOKIA_LCN_API_VERSION)) { + if (subscription.getCallbackUrl().equals(callbackUrl)) { + return; + } + } + CreateSubscriptionRequest request = new CreateSubscriptionRequest(); + request.setFilter(new SubscriptionFilter()); + request.getFilter().setNotificationTypes(new ArrayList<>()); + request.getFilter().getNotificationTypes().add(VnfNotificationType.VNFLIFECYCLECHANGENOTIFICATION); + request.setCallbackUrl(callbackUrl); + request.getFilter().addOperationTypesItem(OperationType.HEAL); + request.getFilter().addOperationTypesItem(OperationType.INSTANTIATE); + request.getFilter().addOperationTypesItem(OperationType.SCALE); + request.getFilter().addOperationTypesItem(OperationType.TERMINATE); + SubscriptionAuthentication subscriptionAuthentication = new SubscriptionAuthentication(); + subscriptionAuthentication.setType(NONE);//FIXME improve authentication + request.setAuthentication(subscriptionAuthentication); + lcnApi.subscriptionsPost(request, NOKIA_LCN_API_VERSION); + } catch (ApiException e) { + logger.error("Unable to subscribe to CBAM LCN", e); + throw new RuntimeException(e); + } + } + + /** + * @return is the component ready to serve requests + */ + public boolean isReady() { + return ready; + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/package-info.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/package-info.java new file mode 100644 index 00000000..67bdef8a --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/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 communication with ONAP core functions + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core; diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/package-info.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/package-info.java new file mode 100644 index 00000000..eea0066b --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/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 ONAP components + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap; diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcExternalSystemInfoProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcExternalSystemInfoProvider.java new file mode 100644 index 00000000..1959e480 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcExternalSystemInfoProvider.java @@ -0,0 +1,64 @@ +/* + * 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.vfc; + +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.GenericExternalSystemInfoProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.Conditions; +import org.onap.vnfmdriver.ApiException; +import org.onap.vnfmdriver.model.VimInfo; +import org.onap.vnfmdriver.model.VnfmInfo; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Conditional; +import org.springframework.core.env.Environment; +import org.springframework.stereotype.Component; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Responsible for providing information related to the VNFM from VF-C source + */ +@Component +@Conditional(value = Conditions.UseForVfc.class) +public class VfcExternalSystemInfoProvider extends GenericExternalSystemInfoProvider { + private static Logger logger = getLogger(VfcExternalSystemInfoProvider.class); + private final VfcRestApiProvider vfcRestApiProvider; + + @Autowired + VfcExternalSystemInfoProvider(Environment environment, VfcRestApiProvider vfcRestApiProvider) { + super(environment); + this.vfcRestApiProvider = vfcRestApiProvider; + } + + @Override + public VnfmInfo queryVnfmInfoFromSource(String vnfmId) { + try { + return vfcRestApiProvider.getNsLcmApi().queryVnfmInfo(vnfmId); + } catch (ApiException e) { + throw fatalFailure(logger, "Unable to query VNFM from VF-C with " + vnfmId + " identifier", e); + } + } + + @Override + public VimInfo getVimInfo(String vimId) { + try { + return vfcRestApiProvider.getNsLcmApi().queryVIMInfo(vimId); + } catch (org.onap.vnfmdriver.ApiException e) { + throw fatalFailure(logger, "Unable to query VIM from VF-C with " + vimId + " identifier", e); + } + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcGrantManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcGrantManager.java new file mode 100644 index 00000000..fd68aebe --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcGrantManager.java @@ -0,0 +1,220 @@ +/* + * 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.vfc; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.nokia.cbam.lcm.v32.ApiException; +import com.nokia.cbam.lcm.v32.model.VnfInfo; +import com.nokia.cbam.lcm.v32.model.VnfcResourceInfo; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IGrantManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.Conditions; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider; +import org.onap.vnfmdriver.model.*; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Conditional; +import org.springframework.stereotype.Component; +import org.yaml.snakeyaml.Yaml; + +import java.util.*; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Responsible for handling granting before the execution of a VNF operation + */ +@Component +@Conditional(value = Conditions.UseForVfc.class) +public class VfcGrantManager implements IGrantManager { + private static Logger logger = getLogger(VfcGrantManager.class); + private final CatalogManager catalogManager; + private final CbamRestApiProvider cbamRestApiProvider; + private final VfcRestApiProvider vfcRestApiProvider; + + @Autowired + VfcGrantManager(CatalogManager catalogManager, CbamRestApiProvider cbamRestApiProvider, VfcRestApiProvider vfcRestApiProvider) { + this.catalogManager = catalogManager; + this.cbamRestApiProvider = cbamRestApiProvider; + this.vfcRestApiProvider = vfcRestApiProvider; + } + + @Override + public void requestGrantForHeal(String vnfmId, String vnfId, String vimId, String onapCsarId, VnfHealRequest request, String jobId) { + GrantVNFRequest grantRequest = buildGrantRequest(vnfmId, vimId, onapCsarId, jobId, OperationType.HEAL); + ResourceChange resourceChange = new ResourceChange(); + resourceChange.setType(ChangeType.VDU); + resourceChange.setVdu(request.getAffectedvm().getVduid()); + resourceChange.setResourceDefinitionId(UUID.randomUUID().toString()); + grantRequest.getRemoveResource().add(resourceChange); + grantRequest.getAddResource().add(resourceChange); + grantRequest.setVnfInstanceId(vnfId); + requestGrant(grantRequest); + } + + @Override + public void requestGrantForScale(String vnfmId, String vnfId, String vimId, String onapCsarId, VnfScaleRequest request, String jobId) { + try { + OperationType operationType = ScaleDirection.IN.equals(request.getType()) ? OperationType.SCALEIN : OperationType.SCALEOUT; + GrantVNFRequest grantRequest = buildGrantRequest(vnfmId, vimId, onapCsarId, jobId, operationType); + com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION); + String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, vnf.getVnfdId()); + Set<ResourceChange> resourceChanges = calculateResourceChangeDuringScaling(vnfdContent, request.getAspectId(), Integer.parseInt(request.getNumberOfSteps())); + switch (request.getType()) { + case IN: + grantRequest.getRemoveResource().addAll(resourceChanges); + break; + case OUT: + grantRequest.getAddResource().addAll(resourceChanges); + break; + } + grantRequest.setVnfInstanceId(vnfId); + requestGrant(grantRequest); + } catch (ApiException e) { + logger.error("Unable to query VNF " + vnfId, e); + throw new RuntimeException("Unable to query VNF " + vnfId, e); + } + } + + @Override + public void requestGrantForTerminate(String vnfmId, String vnfId, String vimId, String onapVnfdId, VnfInfo vnf, String jobId) { + switch (vnf.getInstantiationState()) { + case NOT_INSTANTIATED: + break; + case INSTANTIATED: + GrantVNFRequest grantRequest; + try { + grantRequest = buildGrantRequest(vnfmId, vimId, onapVnfdId, jobId, OperationType.TERMINAL); + if (vnf.getInstantiatedVnfInfo().getVnfcResourceInfo() != null) { + for (VnfcResourceInfo vnfc : vnf.getInstantiatedVnfInfo().getVnfcResourceInfo()) { + ResourceChange resourceChange = new ResourceChange(); + grantRequest.getRemoveResource().add(resourceChange); + resourceChange.setVdu(vnfc.getVduId()); + resourceChange.setType(ChangeType.VDU); + resourceChange.setResourceDefinitionId(UUID.randomUUID().toString()); + } + } + grantRequest.setVnfInstanceId(vnfId); + } catch (Exception e) { + logger.error("Unable to prepare grant request for termination", e); + throw new RuntimeException("Unable to prepare grant request for termination", e); + } + requestGrant(grantRequest); + break; + } + } + + @Override + public GrantVNFResponseVim requestGrantForInstantiate(String vnfmId, String vnfId, String vimId, String onapVnfdId, String instantiationLevelId, String cbamVnfdContent, String jobId) { + GrantVNFRequest grantRequest; + try { + grantRequest = buildGrantRequest(vnfmId, vimId, onapVnfdId, jobId, OperationType.INSTANTIATE); + grantRequest.setVnfInstanceId(vnfId); + grantRequest.setAddResource(new ArrayList<>()); + grantRequest.getAddResource().addAll(calculateResourceChangeDuringInstantiate(cbamVnfdContent, instantiationLevelId)); + } catch (Exception e) { + logger.error("Unable to prepare grant request for instantiation", e); + throw new RuntimeException("Unable to prepare grant request for instantiation", e); + } + return requestGrant(grantRequest); + } + + private GrantVNFRequest buildGrantRequest(String vnfmId, String vimId, String onapCsarId, String jobId, OperationType operationType) { + //FIXME the vimId should not be required for grant request see VFC-603 issue + GrantVNFRequest grantVNFRequest = new GrantVNFRequest(); + grantVNFRequest.setAdditionalParam(new AdditionalGrantParams(vnfmId, vimId)); + grantVNFRequest.setVnfDescriptorId(onapCsarId); + grantVNFRequest.setJobId(jobId); + grantVNFRequest.setLifecycleOperation(operationType); + grantVNFRequest.setAddResource(new ArrayList<>()); + grantVNFRequest.setRemoveResource(new ArrayList<>()); + return grantVNFRequest; + } + + private GrantVNFResponseVim requestGrant(GrantVNFRequest grantRequest) { + try { + return vfcRestApiProvider.getNsLcmApi().grantvnf(grantRequest).getVim(); + } catch (org.onap.vnfmdriver.ApiException e) { + logger.error("Unable to request grant", e); + throw new RuntimeException(e); + } + } + + private Set<ResourceChange> calculateResourceChangeDuringInstantiate(String vnfdContent, String instantiationLevelId) { + JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject(); + JsonObject capabilities = CbamUtils.child(CbamUtils.child(CbamUtils.child(root, "topology_template"), "substitution_mappings"), "capabilities"); + JsonObject deploymentFlavorProperties = CbamUtils.child(CbamUtils.child(capabilities, "deployment_flavour"), "properties"); + JsonObject instantiationLevels = CbamUtils.child(deploymentFlavorProperties, "instantiation_levels"); + Set<ResourceChange> resourceChanges = new HashSet<>(); + for (Map.Entry<String, JsonElement> vdu_level : CbamUtils.child(CbamUtils.child(instantiationLevels, instantiationLevelId), ("vdu_levels")).entrySet()) { + JsonElement number_of_instances = vdu_level.getValue().getAsJsonObject().get("number_of_instances"); + for (int i = 0; i < number_of_instances.getAsLong(); i++) { + ResourceChange resourceChange = new ResourceChange(); + resourceChanges.add(resourceChange); + resourceChange.setVdu(vdu_level.getKey()); + resourceChange.setType(ChangeType.VDU); + resourceChange.setResourceDefinitionId(UUID.randomUUID().toString()); + } + } + return resourceChanges; + } + + private Set<ResourceChange> calculateResourceChangeDuringScaling(String vnfdContent, String aspectId, int steps) { + JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject(); + Set<ResourceChange> resourceChanges = new HashSet<>(); + JsonArray policies = CbamUtils.child(root, "topology_template").getAsJsonObject().get("policies").getAsJsonArray(); + for (JsonElement policy : policies) { + if (policy.getAsJsonObject().entrySet().iterator().next().getKey().equals("heat_mapping")) { + JsonObject aspects = policy.getAsJsonObject().entrySet().iterator().next().getValue().getAsJsonObject().get("properties").getAsJsonObject().get("aspects").getAsJsonObject(); + JsonObject aspect = aspects.get(aspectId).getAsJsonObject(); + if (aspect.has("vdus")) { + for (Map.Entry<String, JsonElement> vdu : aspect.get("vdus").getAsJsonObject().entrySet()) { + String vduId = vdu.getKey(); + for (int step = 0; step < steps; step++) { + for (int i = 0; i < vdu.getValue().getAsJsonArray().size(); i++) { + ResourceChange resourceChange = new ResourceChange(); + resourceChange.setVdu(vduId); + resourceChange.setType(ChangeType.VDU); + resourceChange.setResourceDefinitionId(UUID.randomUUID().toString()); + resourceChanges.add(resourceChange); + } + } + } + } + } + } + return resourceChanges; + } + + /** + * Represents the mandatory parameters that must be sent during grant request to VF-C + */ + private static class AdditionalGrantParams { + private final String vnfmId; + private final String vimId; + + AdditionalGrantParams(String vnfmId, String vimId) { + this.vnfmId = vnfmId; + this.vimId = vimId; + } + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcNotificationSender.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcNotificationSender.java new file mode 100644 index 00000000..26439b5c --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcNotificationSender.java @@ -0,0 +1,202 @@ +/* + * 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.vfc; + +import com.google.gson.Gson; +import com.nokia.cbam.lcm.v32.model.OperationExecution; +import com.nokia.cbam.lcm.v32.model.ScaleVnfRequest; +import com.nokia.cbam.lcm.v32.model.VnfLifecycleChangeNotification; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.INotificationSender; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.Conditions; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.DriverProperties; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.ReportedAffectedConnectionPoints; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.ReportedAffectedCp; +import org.onap.vnfmdriver.model.*; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Conditional; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.List; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.ILifecycleChangeNotificationManager.SEPARATOR; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.JobManager.extractOnapJobId; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Responsible for sending notifications to VF-C + */ +@Component +@Conditional(value = Conditions.UseForVfc.class) +public class VfcNotificationSender implements INotificationSender { + private static Logger logger = getLogger(VfcNotificationSender.class); + private final DriverProperties driverProperties; + private final VfcRestApiProvider vfcRestApiProvider; + + @Autowired + VfcNotificationSender(DriverProperties driverProperties, VfcRestApiProvider vfcRestApiProvider) { + this.driverProperties = driverProperties; + this.vfcRestApiProvider = vfcRestApiProvider; + } + + @Override + public void processNotification(VnfLifecycleChangeNotification recievedNotification, OperationExecution operationExecution, ReportedAffectedConnectionPoints affectedCps, String vimId) { + VNFLCMNotification notificationToSend = new VNFLCMNotification(); + notificationToSend.setJobId(extractOnapJobId(operationExecution.getOperationParams())); + notificationToSend.setOperation(getOperation(driverProperties.getVnfmId(), recievedNotification.getVnfInstanceId(), operationExecution, recievedNotification.getOperation(), recievedNotification.getAffectedVnfcs())); + notificationToSend.setVnfInstanceId(recievedNotification.getVnfInstanceId()); + switch (recievedNotification.getStatus()) { + case FINISHED: + case FAILED: + notificationToSend.setStatus(VnfLcmNotificationStatus.RESULT); + addAffectedVirtualLinks(recievedNotification, notificationToSend); + addAffectedVnfcs(vimId, recievedNotification.getVnfInstanceId(), notificationToSend, recievedNotification); + addAffectedCps(vimId, notificationToSend, affectedCps); + break; + default: + notificationToSend.setStatus(VnfLcmNotificationStatus.START); + break; + } + sendNotification(notificationToSend); + } + + private void sendNotification(VNFLCMNotification notification) { + try { + logger.info("Sending LCN: " + new Gson().toJson(notification)); + vfcRestApiProvider.getNsLcmApi().vNFLCMNotification(driverProperties.getVnfmId(), notification.getVnfInstanceId(), notification); + } catch (Exception e) { + fatalFailure(logger, "Unable to send LCN to VF-C", e); + } + } + + private AffectedCp buildAffectedCp(String vimId, String vnfId, ReportedAffectedCp affectedCp) { + AffectedCp onapAffectedCp = new AffectedCp(); + AffectedCpPortResource port = new AffectedCpPortResource(); + port.setInstId(affectedCp.getServerProviderId()); + port.setIpAddress(affectedCp.getIpAddress()); + port.setMacAddress(affectedCp.getMacAddress()); + port.setResourceid(affectedCp.getProviderId()); + port.setResourceName(affectedCp.getName()); + port.setTenant(affectedCp.getTenantId()); + port.setVimid(vimId); + onapAffectedCp.setPortResource(port); + onapAffectedCp.setCpdid(affectedCp.getCpId()); + onapAffectedCp.setCpinstanceid(vnfId + SEPARATOR + affectedCp.getCpId()); + onapAffectedCp.setVirtualLinkInstanceId(affectedCp.getNetworkProviderId()); + onapAffectedCp.setChangeType(transform(affectedCp.getChangeType())); + //owner id & type can be left empty it will default to VNF id on VF-C + return onapAffectedCp; + } + + private VnfCpNotificationType transform(com.nokia.cbam.lcm.v32.model.ChangeType changeType) { + switch (changeType) { + case ADDED: + return VnfCpNotificationType.ADDED; + case REMOVED: + return VnfCpNotificationType.REMOVED; + default: //can only be MODIFIED + return VnfCpNotificationType.CHANGED; + } + } + + private void addAffectedVnfcs(String vimId, String vnfId, VNFLCMNotification notificationToSend, VnfLifecycleChangeNotification request) { + if (request.getAffectedVnfcs() != null) { + notificationToSend.setAffectedVnfc(new ArrayList<>()); + for (com.nokia.cbam.lcm.v32.model.AffectedVnfc affectedVnfc : request.getAffectedVnfcs()) { + org.onap.vnfmdriver.model.AffectedVnfc onapVnfc = new org.onap.vnfmdriver.model.AffectedVnfc(); + onapVnfc.setChangeType(getChangeType(affectedVnfc.getChangeType())); + onapVnfc.setVduId(affectedVnfc.getVduId()); + onapVnfc.setVmid(affectedVnfc.getComputeResource().getResourceId()); + onapVnfc.setVmname(extractServerName(affectedVnfc.getComputeResource().getAdditionalData())); + onapVnfc.setVnfcInstanceId(vnfId + SEPARATOR + affectedVnfc.getId()); + onapVnfc.setVimid(vimId); + notificationToSend.getAffectedVnfc().add(onapVnfc); + } + } + } + + private void addAffectedVirtualLinks(VnfLifecycleChangeNotification request, VNFLCMNotification notification) { + if (request.getAffectedVirtualLinks() != null) { + notification.setAffectedVl(new ArrayList<>()); + for (com.nokia.cbam.lcm.v32.model.AffectedVirtualLink affectedVirtualLink : request.getAffectedVirtualLinks()) { + org.onap.vnfmdriver.model.AffectedVirtualLink onapVirtualLink = new org.onap.vnfmdriver.model.AffectedVirtualLink(); + onapVirtualLink.setVlInstanceId(request.getVnfInstanceId() + SEPARATOR + affectedVirtualLink.getId()); + onapVirtualLink.setChangeType(getChangeType(affectedVirtualLink.getChangeType())); + onapVirtualLink.setVldid(affectedVirtualLink.getVirtualLinkDescId()); + AffectedVirtualLinkNetworkResource networkResource = new AffectedVirtualLinkNetworkResource(); + onapVirtualLink.setNetworkResource(networkResource); + networkResource.setResourceId(affectedVirtualLink.getResource().getResourceId()); + networkResource.setResourceType(AffectedVirtualLinkType.NETWORK); + notification.getAffectedVl().add(onapVirtualLink); + } + } + } + + private void addAffectedCps(String vimId, VNFLCMNotification notificationToSend, ReportedAffectedConnectionPoints affectedCps) { + if (affectedCps != null) { + notificationToSend.setAffectedCp(new ArrayList<>()); + for (ReportedAffectedCp affectedCp : affectedCps.getPost()) { + if (affectedCp.getCpdId() != null) { + AffectedCp onapAffectedCp = buildAffectedCp(vimId, notificationToSend.getVnfInstanceId(), affectedCp); + onapAffectedCp.setCpdid(affectedCp.getCpdId()); + notificationToSend.getAffectedCp().add(onapAffectedCp); + } + if (affectedCp.getEcpdId() != null) { + AffectedCp onapAffectedCp = buildAffectedCp(vimId, notificationToSend.getVnfInstanceId(), affectedCp); + onapAffectedCp.setCpdid(affectedCp.getEcpdId()); + notificationToSend.getAffectedCp().add(onapAffectedCp); + } + } + } + } + + private org.onap.vnfmdriver.model.OperationType getOperation(String vnfmId, String vnfId, OperationExecution operationExecution, com.nokia.cbam.lcm.v32.model.OperationType type, List<com.nokia.cbam.lcm.v32.model.AffectedVnfc> affectedVnfcs) { + switch (type) { + case TERMINATE: + return org.onap.vnfmdriver.model.OperationType.TERMINAL; + case INSTANTIATE: + return org.onap.vnfmdriver.model.OperationType.INSTANTIATE; + case SCALE: + ScaleVnfRequest originalRequest = new Gson().fromJson(new Gson().toJson(operationExecution.getOperationParams()), ScaleVnfRequest.class); + switch (originalRequest.getType()) { + case IN: + return org.onap.vnfmdriver.model.OperationType.SCALEIN; + default: //OUT + return org.onap.vnfmdriver.model.OperationType.SCALEOUT; + } + default: + return org.onap.vnfmdriver.model.OperationType.HEAL; + } + } + + private String extractServerName(Object additionalData) { + return new Gson().toJsonTree(additionalData).getAsJsonObject().get("name").getAsString(); + } + + private org.onap.vnfmdriver.model.VnfNotificationType getChangeType(com.nokia.cbam.lcm.v32.model.ChangeType changeType) { + switch (changeType) { + case ADDED: + return org.onap.vnfmdriver.model.VnfNotificationType.ADDED; + case REMOVED: + return org.onap.vnfmdriver.model.VnfNotificationType.REMOVED; + default: //case MODIFIED: + return org.onap.vnfmdriver.model.VnfNotificationType.MODIFIED; + } + } + +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcPackageProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcPackageProvider.java new file mode 100644 index 00000000..b8de2378 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcPackageProvider.java @@ -0,0 +1,107 @@ +/* + * 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.vfc; + +import com.google.common.io.ByteStreams; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import org.apache.http.HttpEntity; +import org.apache.http.HttpHeaders; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpGet; +import org.apache.http.impl.client.CloseableHttpClient; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IPackageProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.IpMappingProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.Conditions; +import org.onap.vfccatalog.api.VnfpackageApi; +import org.onap.vfccatalog.model.VnfPkgDetailInfo; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Conditional; +import org.springframework.stereotype.Component; + +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.io.InputStream; +import java.net.URL; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions; +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.http.MediaType.APPLICATION_OCTET_STREAM_VALUE; + +/** + * Retrieves a package from VF-C + */ +@Component +@Conditional(value = Conditions.UseForVfc.class) +public class VfcPackageProvider implements IPackageProvider { + private static Logger logger = getLogger(VfcPackageProvider.class); + private final VfcRestApiProvider restApiProvider; + private final IpMappingProvider ipMappingProvider; + + @Autowired + VfcPackageProvider(VfcRestApiProvider restApiProvider, IpMappingProvider ipMappingProvider) { + this.restApiProvider = restApiProvider; + this.ipMappingProvider = ipMappingProvider; + } + + @Override + public String getCbamVnfdId(String csarId) { + try { + VnfpackageApi onapCatalogApi = restApiProvider.getOnapCatalogApi(); + VnfPkgDetailInfo vnfPackageDetails = onapCatalogApi.queryVnfPackage(csarId); + JsonElement vnfdModel = new JsonParser().parse(vnfPackageDetails.getPackageInfo().getVnfdModel()); + return vnfdModel.getAsJsonObject().get("metadata").getAsJsonObject().get("resourceVendorModelNumber").getAsString(); + } catch (Exception e) { + throw fatalFailure(logger, "Unable to query VNF package with " + csarId + " from VF-C", e); + } + } + + @Override + public byte[] getPackage(String csarId) { + String downloadUrl; + try { + VnfpackageApi onapCatalogApi = restApiProvider.getOnapCatalogApi(); + VnfPkgDetailInfo vnfPackageDetails = onapCatalogApi.queryVnfPackage(csarId); + downloadUrl = vnfPackageDetails.getPackageInfo().getDownloadUrl(); + String host = new URL(downloadUrl).getHost(); + if (!ipMappingProvider.mapPrivateIpToPublicIp(host).equals(host)) { + downloadUrl = downloadUrl.replaceFirst("://" + host, "://" + ipMappingProvider.mapPrivateIpToPublicIp(host)); + } + } catch (Exception e) { + throw fatalFailure(logger, "Unable to query VNF package with " + csarId + " from VF-C", e); + } + try { + return downloadCbamVnfPackage(downloadUrl); + } catch (Exception e) { + throw fatalFailure(logger, "Unable to download package from " + downloadUrl + " from VF-C", e); + } + } + + private byte[] downloadCbamVnfPackage(String downloadUri) throws IOException { + CloseableHttpClient client = systemFunctions().getHttpClient(); + HttpGet httpget = new HttpGet(downloadUri); + httpget.setHeader(HttpHeaders.ACCEPT, APPLICATION_OCTET_STREAM_VALUE); + CloseableHttpResponse response = client.execute(httpget); + HttpEntity entity = response.getEntity(); + InputStream is = entity.getContent(); + ByteArrayOutputStream cbamInZip = new ByteArrayOutputStream(); + byte[] bytes = ByteStreams.toByteArray(is); + client.close(); + return bytes; + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcRestApiProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcRestApiProvider.java new file mode 100644 index 00000000..fd4e6932 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/VfcRestApiProvider.java @@ -0,0 +1,74 @@ +/* + * 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.vfc; + +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.onap.vfccatalog.api.VnfpackageApi; +import org.onap.vnfmdriver.api.NslcmApi; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.context.annotation.Conditional; +import org.springframework.stereotype.Component; + +/** + * Responsible for providing access to VF-C REST APIs + */ +@Component +@Conditional(value = Conditions.UseForVfc.class) +public class VfcRestApiProvider { + static final String NSLCM_API_SERVICE_NAME = "nslcm"; + static final String NSLCM_API_VERION = "v1"; + static final String NSCATALOG_SERVICE_NAME = "catalog"; + static final String NSCATALOG_API_VERSION = "v1"; + private final MsbApiProvider msbApiProvider; + + @Autowired + VfcRestApiProvider(MsbApiProvider msbApiProvider) { + this.msbApiProvider = msbApiProvider; + } + + /** + * @return API to access VF-C for granting & LCN API + */ + public NslcmApi getNsLcmApi() { + org.onap.vnfmdriver.ApiClient apiClient = new org.onap.vnfmdriver.ApiClient(); + String correctedUrl = fixIncorrectUrl(); + apiClient.setBasePath(correctedUrl); + return new NslcmApi(apiClient); + } + + /** + * @return API to access VF-C catalog API + */ + public VnfpackageApi getOnapCatalogApi() { + org.onap.vfccatalog.ApiClient vfcApiClient = new org.onap.vfccatalog.ApiClient(); + vfcApiClient.setBasePath(msbApiProvider.getMicroServiceUrl(NSCATALOG_SERVICE_NAME, NSCATALOG_API_VERSION)); + return new VnfpackageApi(vfcApiClient); + } + + /** + * The swagger schema definition is not consistent with MSB info. The MSB reports + * the base path /restapi/nsclm/v1 (correct) and the paths defined in swagger is + * /nsclm/v1 making all API calls /restapi/nsclm/v1/nsclm/v1 (incorrect) + * + * @return + */ + private String fixIncorrectUrl() { + String urlInMsb = msbApiProvider.getMicroServiceUrl(NSLCM_API_SERVICE_NAME, NSLCM_API_VERION); + //FIXME in VF-C swagger API definitions + return urlInMsb.replaceFirst("/nslcm/v1", ""); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/CbamVnfPackageBuilder.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/CbamVnfPackageBuilder.java new file mode 100644 index 00000000..5f9f6341 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/CbamVnfPackageBuilder.java @@ -0,0 +1,72 @@ +/* + * 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.packagetransformer; + +import com.google.common.io.ByteStreams; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; +import java.util.zip.ZipOutputStream; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions; + +/** + * Builds a CBAM VNF package capable to be deployed on ONAP from a CBAM package + */ +public class CbamVnfPackageBuilder { + + /** + * @param originalCbamVnfPackage the original CBAM VNF package + * @param vnfdLocation the location of the VNFD within the CBAM VNF package + * @param modifiedCbamVnfdContent the modified CBAM VNFD content + * @return the mod + */ + public byte[] toModifiedCbamVnfPackage(byte[] originalCbamVnfPackage, String vnfdLocation, String modifiedCbamVnfdContent) throws IOException { + ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(originalCbamVnfPackage)); + ByteArrayOutputStream result = new ByteArrayOutputStream(); + ZipOutputStream out = new ZipOutputStream(result); + ZipEntry zipEntry; + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + if (zipEntry.getName().matches(vnfdLocation)) { + out.putNextEntry(new ZipEntry(vnfdLocation)); + out.write(modifiedCbamVnfdContent.getBytes()); + out.closeEntry(); + } else { + out.putNextEntry(new ZipEntry(zipEntry.getName())); + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ByteStreams.copy(zipInputStream, byteArrayOutputStream); + out.write(byteArrayOutputStream.toByteArray()); + out.closeEntry(); + } + } + out.putNextEntry(new ZipEntry("javascript/cbam.pre.collectConnectionPoints.js")); + out.write(systemFunctions().loadFile("cbam.pre.collectConnectionPoints.js")); + out.closeEntry(); + out.putNextEntry(new ZipEntry("javascript/cbam.collectConnectionPoints.js")); + out.write(systemFunctions().loadFile("cbam.collectConnectionPoints.js")); + out.closeEntry(); + out.putNextEntry(new ZipEntry("javascript/cbam.post.collectConnectionPoints.js")); + out.write(systemFunctions().loadFile("cbam.post.collectConnectionPoints.js")); + out.closeEntry(); + out.close(); + zipInputStream.close(); + return result.toByteArray(); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/CbamVnfdBuilder.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/CbamVnfdBuilder.java new file mode 100644 index 00000000..ba17bbfd --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/CbamVnfdBuilder.java @@ -0,0 +1,100 @@ +/* + * 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.packagetransformer; + +import com.fasterxml.jackson.databind.JsonNode; +import com.fasterxml.jackson.databind.ObjectMapper; +import com.fasterxml.jackson.dataformat.yaml.YAMLMapper; +import com.google.gson.*; +import org.yaml.snakeyaml.Yaml; + +import java.io.IOException; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.child; + +/** + * Modifies a CBAM VNFD to fit ONAP + */ +public class CbamVnfdBuilder { + + /** + * @param cbamVnfdContent the original CBAM VNFD + * @return the modified content CBAM VNFD + */ + public String build(String cbamVnfdContent) throws IOException { + JsonObject root = new Gson().toJsonTree(new Yaml().load(cbamVnfdContent)).getAsJsonObject(); + JsonObject substitution_mappings = child(child(root, "topology_template"), "substitution_mappings"); + JsonObject extensions = addChild(addChild(addChild(addChild(addChild(substitution_mappings, "capabilities"), "vnf"), "properties"), "modifiable_attributes"), "extensions"); + JsonObject onapCsarId = addChild(extensions, "onapCsarId"); + onapCsarId.add("default", new JsonPrimitive("kuku")); + JsonObject vimId = addChild(extensions, "vimId"); + vimId.add("default", new JsonPrimitive("kuku")); + JsonObject interfaces = child(substitution_mappings, "interfaces"); + JsonObject basic = addChild(interfaces, "Basic"); + addOperationParams(addChild(basic, "instantiate")); + addOperationParams(addChild(basic, "terminate")); + if (interfaces.has("Scalable")) { + addOperationParams(addChild(child(interfaces, "Scalable"), "scale")); + } + if (interfaces.has("Healable")) { + addOperationParams(addChild(child(interfaces, "Healable"), "heal")); + } + JsonNode jsonNodeTree = new ObjectMapper().readTree(new GsonBuilder().setPrettyPrinting().create().toJson(root)); + return new YAMLMapper().writeValueAsString(jsonNodeTree); + } + + private void addOperationParams(JsonObject operation) { + JsonObject inputs = addChild(operation, "inputs"); + JsonObject extensions = addChild(inputs, "extensions"); + JsonArray pre_actions = addChildArray(extensions, "pre_actions"); + pre_actions.add(addAction("javascript/cbam.pre.collectConnectionPoints.js")); + JsonArray post_actions = addChildArray(extensions, "post_actions"); + post_actions.add(addAction("javascript/cbam.post.collectConnectionPoints.js")); + JsonObject additional_parameters = addChild(inputs, "additional_parameters"); + additional_parameters.addProperty("jobId", "kuku"); + } + + private JsonElement addAction(String jsAction) { + JsonObject action = new JsonObject(); + action.addProperty("javascript", jsAction); + JsonArray myInclude = new JsonArray(); + myInclude.add("javascript/cbam.collectConnectionPoints.js"); + action.add("include", myInclude); + action.addProperty("output", "operation_result"); + return action; + } + + private JsonArray addChildArray(JsonObject root, String name) { + if (root.has(name)) { + return root.get(name).getAsJsonArray(); + } else { + JsonArray child = new JsonArray(); + root.add(name, child); + return child; + } + } + + private JsonObject addChild(JsonObject root, String name) { + if (root.has(name)) { + return root.get(name).getAsJsonObject(); + } else { + JsonObject child = new JsonObject(); + root.add(name, child); + return child; + } + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfPackageBuilder.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfPackageBuilder.java new file mode 100644 index 00000000..f769becb --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfPackageBuilder.java @@ -0,0 +1,85 @@ +/* + * 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.packagetransformer; + +import com.google.common.io.ByteStreams; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.InputStream; +import java.nio.charset.StandardCharsets; +import java.util.zip.ZipEntry; +import java.util.zip.ZipOutputStream; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager.getFileInZip; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager.getVnfdLocation; + +/** + * Transforms a CBAM package into an ONAP package + */ + +public class OnapVnfPackageBuilder { + + /** + * Entry point for the command line package transformer + * + * @param args not used (required due to signature) + */ + public static void main(String[] args) throws Exception { + byte[] covert = new OnapVnfPackageBuilder().covert(systemFunctions().in()); + systemFunctions().out().write(covert); + } + + /** + * @param zip the original CBAM package + * @return the converted ONAP package + */ + public byte[] covert(InputStream zip) throws Exception { + byte[] cbamVnfPackage = ByteStreams.toByteArray(zip); + String vnfdLocation = getVnfdLocation(new ByteArrayInputStream(cbamVnfPackage)); + ByteArrayOutputStream vnfdContent = getFileInZip(new ByteArrayInputStream(cbamVnfPackage), vnfdLocation); + byte[] cbamVnfdContent = vnfdContent.toByteArray(); + String onapVnfd = new OnapVnfdBuilder().toOnapVnfd(new String(cbamVnfdContent, StandardCharsets.UTF_8)); + byte[] modifiedCbamPackage = new CbamVnfPackageBuilder().toModifiedCbamVnfPackage(cbamVnfPackage, vnfdLocation, new CbamVnfdBuilder().build(new String(cbamVnfdContent))); + return buildNewOnapPackage(modifiedCbamPackage, onapVnfd); + } + + private byte[] buildNewOnapPackage(byte[] modifiedCbamPackage, String onapVnfd) throws Exception { + ByteArrayOutputStream result = new ByteArrayOutputStream(); + ZipOutputStream out = new ZipOutputStream(result); + out.putNextEntry(new ZipEntry("Artifacts/Deployment/OTHER/cbam.package.zip")); + out.write(modifiedCbamPackage); + out.closeEntry(); + out.putNextEntry(new ZipEntry("TOSCA-Metadata/TOSCA.meta")); + out.write(systemFunctions().loadFile("TOSCA.meta")); + out.closeEntry(); + out.putNextEntry(new ZipEntry("MainServiceTemplate.yaml")); + out.write(onapVnfd.getBytes()); + out.closeEntry(); + out.putNextEntry(new ZipEntry("Definitions/MainServiceTemplate.yaml")); + out.write(onapVnfd.getBytes()); + out.closeEntry(); + out.putNextEntry(new ZipEntry("MainServiceTemplate.meta")); + out.write(systemFunctions().loadFile("MainServiceTemplate.meta")); + out.closeEntry(); + out.close(); + return result.toByteArray(); + } + + +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfdBuilder.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfdBuilder.java new file mode 100644 index 00000000..d4ff6e41 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapVnfdBuilder.java @@ -0,0 +1,229 @@ +/* + * 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.packagetransformer; + +import com.google.gson.Gson; +import com.google.gson.JsonArray; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.yaml.snakeyaml.Yaml; + +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.child; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.childElement; + +/** + * Transforms a CBAM package into an ONAP package + */ +public class OnapVnfdBuilder { + + private String buildHeader(JsonObject toplogyTemplate) { + JsonObject properties = child(child(toplogyTemplate, "substitution_mappings"), "properties"); + String descriptor_version = properties.get("descriptor_version").getAsString(); + return "tosca_definitions_version: tosca_simple_yaml_1_0\n" + + "\n" + + "metadata:\n" + + " vendor: Nokia\n" + + " csarVersion: " + descriptor_version + "\n" + + " csarProvider: " + properties.get("provider").getAsString() + "\n" + + " id: Simple\n" + + " version: " + properties.get("software_version").getAsString() + "\n" + + " csarType: NFAR\n" + + " name: " + properties.get("product_name").getAsString() + "\n" + + " vnfdVersion: " + descriptor_version + "\n\n" + + "topology_template:\n" + + " node_templates:\n"; + } + + private JsonElement get(String name, Set<Map.Entry<String, JsonElement>> nodes) { + for (Map.Entry<String, JsonElement> node : nodes) { + if (name.equals(node.getKey())) { + return node.getValue(); + } + } + throw new NoSuchElementException("The VNFD does not have a node called " + name + " but required by an other node"); + } + + private String buildVdu(String name, JsonObject vdu, Set<Map.Entry<String, JsonElement>> nodes) { + String memorySize = ""; + String cpuCount = ""; + StringBuilder body = new StringBuilder(); + JsonArray vduRequirements = childElement(vdu.getAsJsonObject(), "requirements").getAsJsonArray(); + for (int i = 0; i < vduRequirements.size(); i++) { + JsonObject requirement = vduRequirements.get(i).getAsJsonObject(); + Map.Entry<String, JsonElement> next = requirement.entrySet().iterator().next(); + switch (next.getKey()) { + case "virtual_compute": + JsonObject virtualCompute = get(next.getValue().getAsString(), nodes).getAsJsonObject(); + cpuCount = childElement(child(child(virtualCompute, "properties"), "virtual_cpu"), "num_virtual_cpu").getAsString(); + memorySize = childElement(child(child(virtualCompute, "properties"), "virtual_memory"), "virtual_mem_size").getAsString(); + break; + case "virtual_storage": + String item = + " - virtual_storage:\n" + + " capability: tosca.capabilities.nfv.VirtualStorage\n" + + " node: " + next.getValue().getAsString() + "\n"; + body.append(item); + break; + } + next.getValue(); + } + String header = " " + name + ":\n" + + " type: tosca.nodes.nfv.VDU.Compute\n" + + " capabilities:\n" + + " virtual_compute:\n" + + " properties:\n" + + " virtual_memory:\n" + + " virtual_mem_size: " + memorySize + "\n" + + " virtual_cpu:\n" + + " num_virtual_cpu: " + cpuCount + "\n" + + " requirements:\n"; + return header + body.toString(); + } + + /** + * @param cbamVnfd the CBAM VNFD + * @return the converted ONAP VNFD + */ + public String toOnapVnfd(String cbamVnfd) { + JsonObject root = new Gson().toJsonTree(new Yaml().load(cbamVnfd)).getAsJsonObject(); + JsonObject topology_template = child(root, "topology_template"); + if (topology_template.has("node_templates")) { + Set<Map.Entry<String, JsonElement>> node_templates = child(topology_template, "node_templates").entrySet(); + StringBuilder body = new StringBuilder(); + for (Map.Entry<String, JsonElement> node : node_templates) { + String type = childElement(node.getValue().getAsJsonObject(), "type").getAsString(); + switch (type) { + case "tosca.nodes.nfv.VDU": + body.append(buildVdu(node.getKey(), node.getValue().getAsJsonObject(), node_templates)); + break; + case "tosca.nodes.nfv.VirtualStorage": + body.append(buildVolume(node.getKey(), node.getValue().getAsJsonObject())); + break; + case "tosca.nodes.nfv.VL": + body.append(buildVl(node.getKey())); + break; + case "tosca.nodes.nfv.ICP": + body.append(buildIcp(node.getKey(), node.getValue().getAsJsonObject())); + break; + case "tosca.nodes.nfv.ECP": + body.append(buildEcp(node.getKey(), node.getValue(), node_templates)); + break; + } + } + return buildHeader(topology_template) + body.toString(); + } + return buildHeader(topology_template); + } + + private String buildEcp(String name, JsonElement ecp, Set<Map.Entry<String, JsonElement>> nodes) { + if (ecp.getAsJsonObject().has("requirements")) { + JsonArray requirements = ecp.getAsJsonObject().get("requirements").getAsJsonArray(); + String icpName = null; + for (int i = 0; i < requirements.size(); i++) { + JsonElement requirement = requirements.get(i); + Map.Entry<String, JsonElement> next = requirement.getAsJsonObject().entrySet().iterator().next(); + switch (next.getKey()) { + case "internal_connection_point": + icpName = next.getValue().getAsString(); + + } + } + if (icpName != null) { + JsonObject icpNode = get(icpName, nodes).getAsJsonObject(); + String vdu = null; + if (icpNode.has("requirements")) { + requirements = icpNode.getAsJsonObject().get("requirements").getAsJsonArray(); + for (int i = 0; i < requirements.size(); i++) { + JsonElement requirement = requirements.get(i); + Map.Entry<String, JsonElement> next = requirement.getAsJsonObject().entrySet().iterator().next(); + switch (next.getKey()) { + case "virtual_binding": + vdu = next.getValue().getAsString(); + } + } + if (vdu != null) { + JsonObject properties = child(icpNode, "properties"); + return " " + name + ":\n" + + " type: tosca.nodes.nfv.VduCpd\n" + + " properties:\n" + + " layer_protocol: " + childElement(properties, "layer_protocol").getAsString() + "\n" + + " role: leaf\n" + + (properties.has("description") ? + " description: " + childElement(properties, "description").getAsString() + "\n" : "") + + " requirements:\n" + + " - virtual_binding: " + vdu + "\n"; + } + } + } + } + return ""; + } + + private String buildIcp(String name, JsonObject icp) { + if (icp.has("requirements")) { + JsonArray requirements = icp.get("requirements").getAsJsonArray(); + String vdu = null; + String vl = null; + for (int i = 0; i < requirements.size(); i++) { + JsonElement requirement = requirements.get(i); + Map.Entry<String, JsonElement> next = requirement.getAsJsonObject().entrySet().iterator().next(); + switch (next.getKey()) { + case "virtual_binding": + vdu = next.getValue().getAsString(); + case "virtual_link": + vl = next.getValue().getAsString(); + break; + } + } + if (vdu != null && vl != null) { + JsonObject properties = child(icp, "properties"); + return " " + name + ":\n" + + " type: tosca.nodes.nfv.VduCpd\n" + + " properties:\n" + + " layer_protocol: " + childElement(properties, "layer_protocol").getAsString() + "\n" + + " role: leaf\n" + (properties.has("description") ? + " description: " + childElement(properties, "description").getAsString() + "\n" : "") + + " requirements:\n" + + " - virtual_binding: " + vdu + "\n" + + " - virtual_link: " + vl + "\n"; + } + } + return ""; + } + + private String buildVolume(String nodeName, JsonObject volume) { + return " " + nodeName + ":\n" + + " type: tosca.nodes.nfv.VDU.VirtualStorage\n" + + " properties:\n" + + " id: " + nodeName + "\n" + + " type_of_storage: volume\n" + + " size_of_storage: " + childElement(child(volume, "properties"), "size_of_storage").getAsString() + "\n"; + } + + private String buildVl(String name) { + return " " + name + ":\n" + + " type: tosca.nodes.nfv.VnfVirtualLinkDesc\n" + + " properties:\n" + + " vl_flavours:\n" + + " flavours:\n" + + " flavourId: notUsed\n"; + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/package-info.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/package-info.java new file mode 100644 index 00000000..7a94ee79 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/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. + */ + +/** + * Converts a CBAM package into an ONAP package + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer; diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/ConverterApi.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/ConverterApi.java new file mode 100644 index 00000000..2013a7bf --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/ConverterApi.java @@ -0,0 +1,81 @@ +/* + * 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 org.apache.http.entity.ContentType; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.OnapVnfPackageBuilder; +import org.slf4j.Logger; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.servlet.http.Part; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions; +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.TEXT_HTML_VALUE; +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +/** + * Responsible for providing the converter utilities for CBAM package format + */ +@Controller +@RequestMapping(value = BASE_URL) +public class ConverterApi { + private static Logger logger = getLogger(ConverterApi.class); + private OnapVnfPackageBuilder vnfPackageConverter = new OnapVnfPackageBuilder(); + + /** + * Return the converted ONAP package + * + * @param httpResponse the HTTP response + * @return the converted ONAP package + */ + @RequestMapping(value = "/convert", method = POST) + @ResponseBody + public void convert(HttpServletResponse httpResponse, HttpServletRequest request) throws Exception { + logger.info("REST: convert package"); + Part part = request.getParts().iterator().next(); + byte[] bytes = vnfPackageConverter.covert(part.getInputStream()); + httpResponse.addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_OCTET_STREAM.getMimeType()); + httpResponse.setStatus(HttpStatus.OK.value()); + httpResponse.addHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(bytes.length)); + httpResponse.addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + "core.csar" + "\""); + httpResponse.getOutputStream().write(bytes); + httpResponse.getOutputStream().flush(); + } + + /** + * Return the HTTP page to upload the package + * Can be removed after the generated swagger API in ONAP is fixed. + * + * @param httpResponse the HTTP response + */ + @RequestMapping(value = "/convert", method = GET, produces = TEXT_HTML_VALUE) + @ResponseBody + public void getUploadPageForConvertingVnfd(HttpServletResponse httpResponse) throws Exception { + logger.info("REST: get converter main page"); + byte[] bytes = systemFunctions().loadFile("upload.html"); + httpResponse.addHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(bytes.length)); + httpResponse.getOutputStream().write(bytes); + } +} 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 new file mode 100644 index 00000000..fa7cec4c --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcmApi.java @@ -0,0 +1,149 @@ +/* + * 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 org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.JobManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager; +import org.onap.vnfmdriver.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 javax.servlet.http.HttpServletResponse; + +import static org.apache.http.HttpStatus.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.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +/** + * Responsible for providing the Nokia sVNFM REST APIs + */ +@Controller +@RequestMapping(value = BASE_URL) +public class LcmApi { + private static Logger logger = getLogger(LcmApi.class); + + private final LifecycleManager lifecycleManager; + private final JobManager jobManager; + + @Autowired + LcmApi(LifecycleManager lifecycleManager, JobManager jobManager) { + this.lifecycleManager = lifecycleManager; + this.jobManager = jobManager; + } + + /** + * Instantiate the VNF (defined further in the VF-C driver integration documentation) + * + * @param request the instantiation request + * @param vnfmId the identifier of the VNFM + * @param httpResponse the HTTP response + * @return the instantiated VNF info + */ + @RequestMapping(value = "/{vnfmId}/vnfs", method = POST, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public VnfInstantiateResponse instantiateVnf(@RequestBody VnfInstantiateRequest request, @PathVariable("vnfmId") String vnfmId, HttpServletResponse httpResponse) { + logger.info("REST: Instantiate VNF"); + VnfInstantiateResponse response = lifecycleManager.instantiate(vnfmId, request, httpResponse); + httpResponse.setStatus(SC_CREATED); + return response; + } + + /** + * Terminate the VNF (defined further in the VF-C driver integration documentation) + * + * @param request the instantiation request + * @param vnfmId the identifier of the VNFM + * @param vnfInstanceId the identifer 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 JobInfo terminateVnf(@RequestBody VnfTerminateRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfInstanceId, HttpServletResponse httpResponse) { + logger.info("REST: Terminate VNF"); + return lifecycleManager.terminateVnf(vnfmId, vnfInstanceId, request, httpResponse); + } + + /** + * 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 httpResponse the HTTP response + * @return the VNF info + */ + @RequestMapping(value = "/{vnfmId}/vnfs/{vnfId}", method = GET, produces = APPLICATION_JSON_VALUE, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + public VnfInfo queryVnf(@PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfInstanceId, HttpServletResponse httpResponse) { + logger.info("REST: Query VNF"); + return lifecycleManager.queryVnf(vnfmId, vnfInstanceId); + } + + /** + * Query the job (defined further in the VF-C driver integration documentation) + * + * @param jobId the identifer 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 JobDetailInfo getJob(@PathVariable("vnfmId") String vnfmId, @PathVariable("jobId") String jobId, HttpServletResponse httpResponse) { + logger.debug("REST: Query job"); + return jobManager.getJob(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 vnfInstanceId 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 JobInfo scaleVnf(@RequestBody VnfScaleRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfInstanceId, HttpServletResponse httpResponse) { + logger.info("REST: Scale VNF"); + return lifecycleManager.scaleVnf(vnfmId, vnfInstanceId, 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 JobInfo healVnf(@RequestBody VnfHealRequest request, @PathVariable("vnfmId") String vnfmId, @PathVariable("vnfId") String vnfInstanceId, HttpServletResponse httpResponse) { + logger.info("REST: Heal VNF"); + return lifecycleManager.healVnf(vnfmId, vnfInstanceId, request, httpResponse); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcnApi.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcnApi.java new file mode 100644 index 00000000..883c2709 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/LcnApi.java @@ -0,0 +1,75 @@ +/* + * 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 com.nokia.cbam.lcm.v32.model.VnfLifecycleChangeNotification; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.LifecycleChangeNotificationManager; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; +import org.springframework.web.bind.annotation.ResponseStatus; + +import javax.servlet.http.HttpServletResponse; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.DriverProperties.BASE_URL; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.DriverProperties.LCN_PATH; +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.http.HttpStatus.NO_CONTENT; +import static org.springframework.http.MediaType.APPLICATION_JSON_VALUE; +import static org.springframework.web.bind.annotation.RequestMethod.GET; +import static org.springframework.web.bind.annotation.RequestMethod.POST; + +/** + * Responsible for providing the Nokia CBAM REST API for recieving LCNs from CBAM + */ +@Controller +@RequestMapping(value = BASE_URL) +public class LcnApi { + private static Logger logger = getLogger(LcnApi.class); + private final LifecycleChangeNotificationManager lcnManager; + + @Autowired + LcnApi(LifecycleChangeNotificationManager lcnManager) { + this.lcnManager = lcnManager; + } + + /** + * Provides a probe for CBAM VNFM to test LCN registration + * + * @param httpResponse the HTTP response + */ + @RequestMapping(value = LCN_PATH, method = GET) + public void testLcnConnectivity(HttpServletResponse httpResponse) { + //used to test connectivity from CBAM to driver + } + + /** + * Handle the LCN sent by CBAM + * + * @param lcn the LCN notification + * @param httpResponse the HTTP response + */ + @RequestMapping(value = LCN_PATH, method = POST, consumes = APPLICATION_JSON_VALUE) + @ResponseBody + @ResponseStatus(code = NO_CONTENT) + public void handleLcn(@RequestBody VnfLifecycleChangeNotification lcn, HttpServletResponse httpResponse) { + logger.info("REST: handle LCN"); + lcnManager.handleLcn(lcn); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SwaggerApi.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SwaggerApi.java new file mode 100644 index 00000000..6d4d19e6 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/SwaggerApi.java @@ -0,0 +1,62 @@ +/* + * 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 org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; +import org.springframework.stereotype.Controller; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.ResponseBody; + +import javax.servlet.http.HttpServletResponse; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.DriverProperties.BASE_URL; +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.web.bind.annotation.RequestMethod.GET; + +/** + * Responsible for providing the Nokia S-VNFM REST APIs for accessing the swagger definitions + */ +@Controller +@RequestMapping(value = BASE_URL) +public class SwaggerApi { + private static Logger logger = getLogger(SwaggerApi.class); + private final SelfRegistrationManager selfRegistrationManager; + + @Autowired + SwaggerApi(SelfRegistrationManager selfRegistrationManager) { + this.selfRegistrationManager = selfRegistrationManager; + } + + /** + * Return the swagger definition + * + * @param httpResponse the HTTP response + * @return the job representing the healing operation + */ + @RequestMapping(value = "/swagger.json", method = GET) + @ResponseBody + public void getSwaggerApiDefinition(HttpServletResponse httpResponse) throws Exception { + logger.info("REST: get swagger definition"); + httpResponse.addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + byte[] bytes = selfRegistrationManager.getSwaggerApiDefinition(); + httpResponse.addHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(bytes.length)); + httpResponse.getOutputStream().write(bytes); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/package-info.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/package-info.java new file mode 100644 index 00000000..4436d722 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/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. + */ + +/** + * The provided REST interfaces. + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.restapi; diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/Conditions.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/Conditions.java new file mode 100644 index 00000000..0554cbea --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/Conditions.java @@ -0,0 +1,65 @@ +/* + * 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.spring; + +import com.google.common.collect.Sets; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; + +import java.util.HashSet; +import java.util.Set; + +import static com.google.common.collect.Sets.newHashSet; + +/** + * Collects the possibilities of sources + */ +public class Conditions { + + private static final String USE_DIRECT_INTEGRATION = "direct"; + + private static Set<Condition> getAllSources() { + return newHashSet(new UseForVfc(), new UseForDirect()); + } + + /** + * Represents the condition for using VF-C + */ + public static class UseForVfc implements Condition { + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { + boolean anyOtherSourceAvailable = false; + for (Condition condition : Conditions.getAllSources()) { + if (!(condition instanceof UseForVfc) && condition.matches(conditionContext, annotatedTypeMetadata)) { + anyOtherSourceAvailable = true; + } + } + return !anyOtherSourceAvailable; + } + } + + /** + * Represents the condition for using ONAP components directly + */ + public static class UseForDirect implements Condition { + @Override + public boolean matches(ConditionContext conditionContext, AnnotatedTypeMetadata annotatedTypeMetadata) { + HashSet<String> activeProfiles = Sets.newHashSet(conditionContext.getEnvironment().getActiveProfiles()); + return activeProfiles.contains(USE_DIRECT_INTEGRATION); + } + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/RealConfig.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/RealConfig.java new file mode 100644 index 00000000..26a3156f --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/RealConfig.java @@ -0,0 +1,49 @@ +/* + * 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.spring; + +import com.nokia.cbam.lcm.v32.ApiClient; +import org.springframework.boot.autoconfigure.web.HttpMessageConverters; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; +import org.springframework.http.converter.HttpMessageConverter; +import org.springframework.http.converter.json.GsonHttpMessageConverter; + +import java.util.ArrayList; +import java.util.Collection; + +/** + * Responsible for configuring the raw REST input conversion + */ +@Configuration +public class RealConfig { + + /** + * Responsible for registering the RAW to POJO message converters. + * This is required since the generated POJOs are annotated with google GSON + * compatible annotations Jackson can not deserialize the stream. + * + * @return the message converter + */ + @Bean + public HttpMessageConverters customConverters() { + Collection<HttpMessageConverter<?>> messageConverters = new ArrayList<>(); + GsonHttpMessageConverter gsonHttpMessageConverter = new GsonHttpMessageConverter(); + gsonHttpMessageConverter.setGson(new ApiClient().getJSON().getGson()); + messageConverters.add(gsonHttpMessageConverter); + return new HttpMessageConverters(true, messageConverters); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/ServletInitializer.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/ServletInitializer.java new file mode 100644 index 00000000..fe1bb183 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/ServletInitializer.java @@ -0,0 +1,33 @@ +/* + * 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.spring; + +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.NokiaSvnfmApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.boot.web.support.SpringBootServletInitializer; + +/** + * Responsible for initializing the Spring application + */ +public class ServletInitializer extends SpringBootServletInitializer { + + @Override + protected SpringApplicationBuilder configure(SpringApplicationBuilder application) { + return application.sources(NokiaSvnfmApplication.class); + } + +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/package-info.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/package-info.java new file mode 100644 index 00000000..93f991fa --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/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. + */ + +/** + * Bootstraps the Spring environments + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring; diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/CbamUtils.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/CbamUtils.java new file mode 100644 index 00000000..7377abfc --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/CbamUtils.java @@ -0,0 +1,75 @@ +/* + * 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.util; + +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import org.slf4j.Logger; + +public class CbamUtils { + + private CbamUtils() { + //use static way + } + + /** + * @param parent the parent JSON object + * @param name the name of the child + * @return the child JSON object of parent with given name + */ + public static JsonObject child(JsonObject parent, String name) { + return childElement(parent, name).getAsJsonObject(); + } + + /** + * @param parent the parent JSON object + * @param name the name of the child + * @return the child JSON object of parent with given name + */ + public static JsonElement childElement(JsonObject parent, String name) { + JsonElement child = parent.get(name); + if (child == null) { + throw new RuntimeException("Missing child " + name); + } + return child; + } + + /** + * Logs and throws a runtime exception + * + * @param logger the logger + * @param msg the error message + * @param e the exception to be wrapped + * @return never reached (runtime exception is thrown) + */ + public static RuntimeException fatalFailure(Logger logger, String msg, Exception e) { + logger.error(msg, e); + throw new RuntimeException(msg, e); + } + + /** + * Logs and throws a runtime exception + * + * @param logger the logger + * @param msg the error message + * @return never reached (runtime exception is thrown) + */ + public static RuntimeException fatalFailure(Logger logger, String msg) { + logger.error(msg); + throw new RuntimeException(msg); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/StoreLoader.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/StoreLoader.java new file mode 100644 index 00000000..faa436e3 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/StoreLoader.java @@ -0,0 +1,165 @@ +/* + * 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.util; + +import org.apache.commons.codec.binary.Base64; + +import java.io.ByteArrayInputStream; +import java.io.InputStream; +import java.security.KeyFactory; +import java.security.KeyStore; +import java.security.KeyStore.TrustedCertificateEntry; +import java.security.NoSuchAlgorithmException; +import java.security.PrivateKey; +import java.security.cert.Certificate; +import java.security.cert.CertificateFactory; +import java.security.spec.InvalidKeySpecException; +import java.security.spec.PKCS8EncodedKeySpec; +import java.util.Collection; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; + +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Create Truststore from the given certificates and keys + */ +public final class StoreLoader { + + public static final String PASSWORD = "password"; + private static final String RSA = "RSA"; + private static final String X_509 = "X.509"; + private static final String SUN = "SUN"; + private static final String JKS = "JKS"; + private static final String RSA_PRIVATE_KEY = "RSA PRIVATE KEY"; + private static final String CERTIFICATE = "CERTIFICATE"; + private static org.slf4j.Logger logger = getLogger(StoreLoader.class); + + private StoreLoader() { + } + + private static String getScope(String content, String scope) { + int rindex = content.indexOf(begin(scope)); + int lindex = content.indexOf(end(scope)); + if (rindex == -1 || lindex == -1) { + return ""; + } + String substring = content.substring(rindex, lindex) + end(scope); + return substring; + } + + /** + * @param content the content of the PEM ( a PEM may contain multiple certificates) + * @return the collection of certificates in the PEM + */ + public static Set<String> getCertifacates(String content) { + String lastCertificate = ""; + Set<String> certificates = new HashSet<>(); + do { + lastCertificate = getScope(content, CERTIFICATE); + content = content.replace(lastCertificate, ""); + if (!"".equals(lastCertificate)) { + certificates.add(lastCertificate); + } + } while (!"".equals(lastCertificate)); + return certificates; + } + + private static byte[] toDer(String pem, String scope) { + return Base64.decodeBase64(pem + .replace(begin(scope), "") + .replace(end(scope), "") + .replaceAll("\\s", "")); + } + + private static String begin(String scope) { + return "-----BEGIN " + scope + "-----"; + } + + private static String end(String scope) { + return "-----END " + scope + "-----"; + } + + /** + * Create new truststore from the given certificate + * + * @param pem the certificate which used to create the store + * @param storePassword the password to protect the store + * @param keyPassword the password to protect the key + * @return the created key store + */ + public static KeyStore loadStore(String pem, String storePassword, String keyPassword) { + Optional<PrivateKey> privateKey = generatePrivateKey(pem); + Certificate[] certs = createCertificates(pem); + try { + KeyStore ks = KeyStore.getInstance(JKS, SUN); + ks.load(null, storePassword.toCharArray()); + if (privateKey.isPresent()) { + ks.setKeyEntry(PASSWORD, privateKey.get(), keyPassword.toCharArray(), certs); + } else if (certs != null) { + int index = 0; + for (Certificate cert : certs) { + TrustedCertificateEntry ts = new TrustedCertificateEntry(cert); + ks.setEntry(PASSWORD + index, ts, null); + index++; + } + } + return ks; + } catch (Exception e) { + throw new RuntimeException("Unable to create keystore", e); + } + } + + private static Certificate[] createCertificates(String pem) { + Set<Certificate> certificates = new HashSet<>(); + try { + for (String certificate : getCertifacates(pem)) { + CertificateFactory certFactory = CertificateFactory.getInstance(X_509); + + InputStream is = new ByteArrayInputStream(toDer(certificate, CERTIFICATE)); + Collection<? extends Certificate> c = certFactory.generateCertificates(is); + certificates.addAll(c); + } + } catch (Exception e) { + logger.error(e.getMessage(), e); + throw new RuntimeException("Unable to load certificates", e); + } + + if (certificates.size() > 0) { + return certificates.toArray(new Certificate[certificates.size()]); + } else { + return null; + } + } + + private static Optional<PrivateKey> generatePrivateKey(String pem) { + try { + String key = getScope(pem, RSA_PRIVATE_KEY); + if (!key.isEmpty()) { + KeyFactory keyFactory = KeyFactory.getInstance(RSA); + PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(toDer(key, RSA_PRIVATE_KEY)); + return Optional.of(keyFactory.generatePrivate(keySpec)); + } + return Optional.empty(); + } catch (NoSuchAlgorithmException | InvalidKeySpecException e) { + logger.error("Unable to load key", e); + throw new RuntimeException("Unable to load key", e); + } + } + +} 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 new file mode 100644 index 00000000..e2a2e660 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/SystemFunctions.java @@ -0,0 +1,161 @@ +/* + * 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.util; + +import com.google.common.io.ByteStreams; +import org.apache.http.impl.client.CloseableHttpClient; +import org.apache.http.impl.client.HttpClients; + +import java.io.InputStream; +import java.io.PrintStream; + +/** + * Wrapper class for static method calls to core or core libraries. + * Calls to static methods in core or core libraries are wrapped to be able to test + * the classes that uses static calls. + */ +public class SystemFunctions { + private static SystemFunctions INSTANCE; + + /** + * @return singleton instance + */ + public static SystemFunctions systemFunctions() { + if (INSTANCE != null) { + return INSTANCE; + } else { + synchronized (SystemFunctions.class) { + INSTANCE = new SystemFunctions(); + } + return INSTANCE; + } + } + + /** + * Causes the currently executing thread to sleep (temporarily cease + * execution) for the specified number of milliseconds, subject to + * the precision and accuracy of system timers and schedulers. The thread + * does not lose ownership of any monitors. + * + * @param millis the length of time to sleep in milliseconds + */ + public void sleep(long millis) { + try { + Thread.sleep(millis); + } catch (InterruptedException e) { + throw new RuntimeException(e); + } + } + + /** + * Returns the current time in milliseconds. Note that + * while the unit of time of the return value is a millisecond, + * the granularity of the value depends on the underlying + * operating system and may be larger. For example, many + * operating systems measure time in units of tens of + * milliseconds. + * <p> + * <p> See the description of the class <code>Date</code> for + * a discussion of slight discrepancies that may arise between + * Unable to load /unittests/missing * "computer time" and coordinated universal time (UTC). + * + * @return the difference, measured in milliseconds, between + * the current time and midnight, January 1, 1970 UTC. + * @see java.util.Date + */ + public long currentTimeMillis() { + return System.currentTimeMillis(); + } + + /** + * Loads a file from the class path + * + * @param url the URL of the file + * @return the content of the file + */ + public byte[] loadFile(String url) { + try { + InputStream stream = SystemFunctions.class.getClassLoader().getResourceAsStream(url); + return ByteStreams.toByteArray(stream); + } catch (Exception e) { + throw new RuntimeException("Unable to load " + url, e); + } + } + + /** + * The "standard" error output stream. This stream is already + * open and ready to accept output data. + * <p> + * Typically this stream corresponds to display output or another + * output destination specified by the host environment or user. By + * convention, this output stream is used to display error messages + * or other information that should come to the immediate attention + * of a user even if the principal output stream, the value of the + * variable <code>out</code>, has been redirected to a file or other + * destination that is typically not continuously monitored. + */ + public PrintStream err() { + return System.err; + } + + /** + * The "standard" output stream. This stream is already + * open and ready to accept output data. Typically this stream + * corresponds to display output or another output destination + * specified by the host environment or user. + * <p> + * For simple stand-alone Java applications, a typical way to write + * a line of output data is: + * <blockquote><pre> + * System.out.println(data) + * </pre></blockquote> + * <p> + * See the <code>println</code> methods in class <code>PrintStream</code>. + * + * @see java.io.PrintStream#println() + * @see java.io.PrintStream#println(boolean) + * @see java.io.PrintStream#println(char) + * @see java.io.PrintStream#println(char[]) + * @see java.io.PrintStream#println(double) + * @see java.io.PrintStream#println(float) + * @see java.io.PrintStream#println(int) + * @see java.io.PrintStream#println(long) + * @see java.io.PrintStream#println(java.lang.Object) + * @see java.io.PrintStream#println(java.lang.String) + */ + public PrintStream out() { + return System.out; + } + + /** + * The "standard" input stream. This stream is already + * open and ready to supply input data. Typically this stream + * corresponds to keyboard input or another input source specified by + * the host environment or user. + */ + public InputStream in() { + return System.in; + } + + /** + * Wraps the static call (required for being able to test) + * + * @return the default HTTP client + */ + public CloseableHttpClient getHttpClient() { + return HttpClients.createDefault(); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParams.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParams.java new file mode 100644 index 00000000..879a9567 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/AdditionalParams.java @@ -0,0 +1,213 @@ +/* + * 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.vnfm; + +import com.nokia.cbam.lcm.v32.model.*; +import com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum; + +import java.util.*; + +/** + * Represents the additional parameters to be sent during instantiation from VF-C to the driver + */ +public class AdditionalParams { + private VimInfoTypeEnum vimType; + private String domain; + private String instantiationLevel; + private List<VimComputeResourceFlavour> computeResourceFlavours = new ArrayList<>(); + private List<ZoneInfo> zones = new ArrayList<>(); + private List<VimSoftwareImage> softwareImages = new ArrayList<>(); + private List<ExtManagedVirtualLinkData> extManagedVirtualLinks = new ArrayList<>(); + private Map<String, List<NetworkAddress>> externalConnectionPointAddresses = new HashMap<>(); + private List<ExtVirtualLinkData> extVirtualLinks = new ArrayList<>(); + private Object additionalParams; + + AdditionalParams() { + //only used through reflection (gson) + } + + /** + * @return the additional parameters of the instantiation + */ + public Object getAdditionalParams() { + return additionalParams; + } + + /** + * @param additionalParams the additional parameters of the instantiation + */ + public void setAdditionalParams(Object additionalParams) { + this.additionalParams = additionalParams; + } + + /** + * @return the type of the VIM + */ + public VimInfoTypeEnum getVimType() { + return vimType; + } + + /** + * @param vimType the type of the VIM + */ + public void setVimType(VimInfoTypeEnum vimType) { + this.vimType = vimType; + } + + /** + * @return the domain of the OpenStack (required for v3 API) + */ + public String getDomain() { + return domain; + } + + /** + * @param domain + */ + public void setDomain(String domain) { + this.domain = domain; + } + + /** + * @return the flavours to be used for the VNF + */ + public List<VimComputeResourceFlavour> getComputeResourceFlavours() { + return computeResourceFlavours; + } + + /** + * @param computeResourceFlavours the flavours to be used for the VNF + */ + public void setComputeResourceFlavours(List<VimComputeResourceFlavour> computeResourceFlavours) { + this.computeResourceFlavours = computeResourceFlavours; + } + + /** + * @return the images to be used + */ + public List<VimSoftwareImage> getSoftwareImages() { + return softwareImages; + } + + /** + * @param softwareImages the images to be used + */ + public void setSoftwareImages(List<VimSoftwareImage> softwareImages) { + this.softwareImages = softwareImages; + } + + /** + * @return the zones to be used for the VNF + */ + public List<ZoneInfo> getZones() { + return zones; + } + + /** + * @param zones the zones to be used for the VNF + */ + public void setZones(List<ZoneInfo> zones) { + this.zones = zones; + } + + /** + * @return the instantiation level of the VNF + */ + public String getInstantiationLevel() { + return instantiationLevel; + } + + /** + * @param instantiationLevel the instantiation level of the VNF + */ + public void setInstantiationLevel(String instantiationLevel) { + this.instantiationLevel = instantiationLevel; + } + + /** + * @return the externally managed internal virtual links + */ + public List<ExtManagedVirtualLinkData> getExtManagedVirtualLinks() { + return extManagedVirtualLinks; + } + + /** + * @param extManagedVirtualLinks the externally managed internal virtual links + */ + public void setExtManagedVirtualLinks(List<ExtManagedVirtualLinkData> extManagedVirtualLinks) { + this.extManagedVirtualLinks = extManagedVirtualLinks; + } + + /** + * @return a binding of the extenal connection points by identifier to it's network addresses to be used + */ + public Map<String, List<NetworkAddress>> getExternalConnectionPointAddresses() { + return externalConnectionPointAddresses; + } + + /** + * @param externalConnectionPointAddresses a binding of the extenal connection points by identifier to it's network addresses to be used + */ + public void setExternalConnectionPointAddresses(Map<String, List<NetworkAddress>> externalConnectionPointAddresses) { + this.externalConnectionPointAddresses = externalConnectionPointAddresses; + } + + public List<ExtVirtualLinkData> getExtVirtualLinks() { + return extVirtualLinks; + } + + public void setExtVirtualLinks(List<ExtVirtualLinkData> extVirtualLinks) { + this.extVirtualLinks = extVirtualLinks; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + AdditionalParams that = (AdditionalParams) 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) && + Objects.equals(softwareImages, that.softwareImages) && + Objects.equals(extManagedVirtualLinks, that.extManagedVirtualLinks) && + Objects.equals(externalConnectionPointAddresses, that.externalConnectionPointAddresses) && + Objects.equals(extVirtualLinks, that.extVirtualLinks) && + Objects.equals(additionalParams, that.additionalParams); + } + + @Override + public int hashCode() { + return Objects.hash(vimType, domain, instantiationLevel, computeResourceFlavours, zones, softwareImages, extManagedVirtualLinks, externalConnectionPointAddresses, extVirtualLinks, additionalParams); + } + + @Override + public String toString() { + return "AdditionalParams{" + + "vimType=" + vimType + + ", domain='" + domain + '\'' + + ", instantiationLevel='" + instantiationLevel + '\'' + + ", computeResourceFlavours=" + computeResourceFlavours + + ", zones=" + zones + + ", softwareImages=" + softwareImages + + ", extManagedVirtualLinks=" + extManagedVirtualLinks + + ", externalConnectionPointAddresses=" + externalConnectionPointAddresses + + ", extVirtualLinks=" + extVirtualLinks + + ", additionalParams=" + additionalParams + + '}'; + } +}
\ No newline at end of file diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CatalogManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CatalogManager.java new file mode 100644 index 00000000..414c0134 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CatalogManager.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.vnfm; + +import com.google.common.io.ByteStreams; +import com.nokia.cbam.catalog.v1.ApiException; +import com.nokia.cbam.catalog.v1.api.DefaultApi; +import com.nokia.cbam.catalog.v1.model.CatalogAdapterVnfpackage; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IPackageProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.vfc.VfcPackageProvider; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.io.*; +import java.nio.file.Path; +import java.util.HashSet; +import java.util.NoSuchElementException; +import java.util.Set; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import static com.google.common.base.Splitter.on; +import static com.google.common.collect.Iterables.filter; +import static java.nio.file.Files.createTempFile; +import static java.nio.file.Files.write; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure; +import static org.slf4j.LoggerFactory.getLogger; + + +/** + * Responsible for handling the CBAM catalog + * - the VNF package is uploaded as part of the instantiation + * - the VNF package is not deleted after VNF deletion + */ +@Component +public class CatalogManager { + private static final String TOSCA_META_PATH = "TOSCA-Metadata/TOSCA.meta"; + private static final String TOSCA_VNFD_KEY = "Entry-Definitions"; + private static Logger logger = getLogger(CatalogManager.class); + private final CbamRestApiProvider cbamRestApiProvider; + private final IPackageProvider packageProvider; + + @Autowired + CatalogManager(CbamRestApiProvider cbamRestApiProvider, IPackageProvider packageProvider) { + this.cbamRestApiProvider = cbamRestApiProvider; + this.packageProvider = packageProvider; + } + + /** + * @param zip the zip + * @param path the path of the file to be returned + * @return the file in the zip + */ + public static ByteArrayOutputStream getFileInZip(InputStream zip, String path) throws IOException { + ZipInputStream zipInputStream = new ZipInputStream(zip); + ByteArrayOutputStream fileContent = getFileInZip(zipInputStream, path); + zipInputStream.close(); + return fileContent; + } + + /** + * @param stream the CBAM VNF package + * @return the location of the VNFD within the CBAM package + */ + public static String getVnfdLocation(InputStream stream) throws IOException { + String toscaMetadata = new String(getFileInZip(stream, TOSCA_META_PATH).toByteArray()); + String toscaVnfdLine = filter(on("\n").split(toscaMetadata), line -> line.contains(TOSCA_VNFD_KEY)).iterator().next(); + return toscaVnfdLine.replace(TOSCA_VNFD_KEY + ":", "").trim(); + } + + private static ByteArrayOutputStream getFileInZip(ZipInputStream zipInputStream, String path) throws IOException { + ZipEntry zipEntry; + Set<String> items = new HashSet<>(); + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + items.add(zipEntry.getName()); + if (zipEntry.getName().matches(path)) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ByteStreams.copy(zipInputStream, byteArrayOutputStream); + return byteArrayOutputStream; + } + } + logger.error("Unable to find the " + path + " in archive found: " + items); + throw new NoSuchElementException("Unable to find the " + path + " in archive found: " + items); + } + + /** + * Prepare the VNF package in CBAM. If the package is not available in the catalog it is uploaded. + * + * @param vnfmId the identifier of the VNFM + * @param csarId the CSAR identifier of the package in ONAP catalog + * @return the package in CBAM catalog + */ + public CatalogAdapterVnfpackage preparePackageInCbam(String vnfmId, String csarId) { + String cbamVnfdId = packageProvider.getCbamVnfdId(csarId); + DefaultApi cbamCatalogApi = cbamRestApiProvider.getCbamCatalogApi(vnfmId); + if (!isPackageReplicated(cbamVnfdId, cbamCatalogApi)) { + try { + Path tempFile = createTempFile("cbam", "zip"); + ByteArrayOutputStream cbamPackage = getFileInZip(new ByteArrayInputStream(packageProvider.getPackage(csarId)), VfcPackageProvider.CBAM_PACKAGE_NAME_IN_ZIP); + write(tempFile, cbamPackage.toByteArray()); + //FIXME delete file + return cbamCatalogApi.create(tempFile.toFile()); + } catch (Exception e) { + logger.debug("Probably concurrent package uploads", e); + //retest if the VNF package exists in CBAM. It might happen that an other operation + //triggered the replication making this API fail. The replication is considered to be + //successful if the package exist in CBAM even if the current package transfer failed + if (isPackageReplicated(cbamVnfdId, cbamCatalogApi)) { + return queryPackageFromCBAM(cbamVnfdId, cbamCatalogApi); + } else { + throw fatalFailure(logger, "Unable to create VNF with " + csarId + " CSAR identifier in package in CBAM", e); + } + } + } + return queryPackageFromCBAM(cbamVnfdId, cbamCatalogApi); + } + + /** + * Gets the content of the VNFD from the CBAM package uploaded to CBAM + * + * @param vnfmId the identifier of the VNFM + * @param vnfdId the identifier of the VNFD + * @return the content of the CBAM VNFD + */ + public String getCbamVnfdContent(String vnfmId, String vnfdId) { + try { + DefaultApi cbamCatalogApi = cbamRestApiProvider.getCbamCatalogApi(vnfmId); + File content = cbamRestApiProvider.getCbamCatalogApi(vnfmId).content(vnfdId); + String vnfdPath = getVnfdLocation(new FileInputStream(content)); + return new String(getFileInZip(new FileInputStream(content), vnfdPath).toByteArray()); + } catch (Exception e) { + throw fatalFailure(logger, "Unable to get package with (" + vnfdId + ")", e); + } + } + + private boolean isPackageReplicated(String cbamVnfdId, DefaultApi cbamCatalogApi) { + try { + return isPackageReplicatedToCbam(cbamVnfdId, cbamCatalogApi); + } catch (Exception e) { + throw fatalFailure(logger, "Unable to determine if the VNF package has been replicated in CBAM", e); + } + } + + private CatalogAdapterVnfpackage queryPackageFromCBAM(String cbamVnfdId, DefaultApi cbamCatalogApi) { + try { + return cbamCatalogApi.getById(cbamVnfdId); + } catch (ApiException e) { + throw fatalFailure(logger, "Unable to query VNF package with " + cbamVnfdId + " from CBAM", e); + } + } + + private boolean isPackageReplicatedToCbam(String cbamVnfdId, DefaultApi cbamCatalogApi) throws ApiException { + for (CatalogAdapterVnfpackage vnfPackage : cbamCatalogApi.list()) { + if (vnfPackage.getVnfdId().equals(cbamVnfdId)) { + return true; + } + } + return false; + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CbamRestApiProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CbamRestApiProvider.java new file mode 100644 index 00000000..5fdc919a --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CbamRestApiProvider.java @@ -0,0 +1,115 @@ +/* + * 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.vnfm; + +import com.google.common.io.BaseEncoding; +import com.nokia.cbam.catalog.v1.api.DefaultApi; +import com.nokia.cbam.lcm.v32.ApiClient; +import com.nokia.cbam.lcm.v32.api.OperationExecutionsApi; +import com.nokia.cbam.lcm.v32.api.VnfsApi; +import com.nokia.cbam.lcn.v32.api.SubscriptionsApi; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VnfmInfoProvider; +import org.onap.vnfmdriver.model.VnfmInfo; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.io.ByteArrayInputStream; + +/** + * Responsible for providing client to access CBAM REST API + */ +@Component +public class CbamRestApiProvider { + public static final String NOKIA_LCN_API_VERSION = "3.2"; + public static final String NOKIA_LCM_API_VERSION = "3.2"; + private final DriverProperties driverProperties; + private final CbamTokenProvider tokenProvider; + private final VnfmInfoProvider vnfmInfoProvider; + + @Value("${trustedCertificates}") + private String trustedCertificates; + @Value("${skipCertificateVerification}") + private boolean skipCertificateVerification; + + @Autowired + public CbamRestApiProvider(DriverProperties driverProperties, CbamTokenProvider cbamTokenProvider, VnfmInfoProvider vnfmInfoProvider) { + this.driverProperties = driverProperties; + this.tokenProvider = cbamTokenProvider; + this.vnfmInfoProvider = vnfmInfoProvider; + } + + /** + * @param vnfmId the identifier of the VNFM + * @return API to access CBAM LCM API + */ + public VnfsApi getCbamLcmApi(String vnfmId) { + return new VnfsApi(getLcmApiClient(vnfmId)); + } + + /** + * @param vnfmId the identifier of the VNFM + * @return API to access the operation executions + */ + public OperationExecutionsApi getCbamOperationExecutionApi(String vnfmId) { + return new OperationExecutionsApi(getLcmApiClient(vnfmId)); + } + + /** + * @param vnfmId the identifier of the VNFM + * @return API to access CBAM LCN subscription API + */ + public SubscriptionsApi getCbamLcnApi(String vnfmId) { + com.nokia.cbam.lcn.v32.ApiClient apiClient = new com.nokia.cbam.lcn.v32.ApiClient(); + if (!skipCertificateVerification) { + apiClient.setSslCaCert(new ByteArrayInputStream(BaseEncoding.base64().decode(trustedCertificates))); + } else { + apiClient.setVerifyingSsl(false); + } + apiClient.setBasePath(driverProperties.getCbamLcnUrl()); + apiClient.setAccessToken(tokenProvider.getToken(vnfmId)); + return new SubscriptionsApi(apiClient); + } + + /** + * @param vnfmId the identifier of the VNFM + * @return API to access CBAM catalog API + */ + public DefaultApi getCbamCatalogApi(String vnfmId) { + com.nokia.cbam.catalog.v1.ApiClient apiClient = new com.nokia.cbam.catalog.v1.ApiClient(); + if (!skipCertificateVerification) { + apiClient.setSslCaCert(new ByteArrayInputStream(BaseEncoding.base64().decode(trustedCertificates))); + } else { + apiClient.setVerifyingSsl(false); + } + apiClient.setBasePath(driverProperties.getCbamCatalogUrl()); + apiClient.setAccessToken(tokenProvider.getToken(vnfmId)); + return new DefaultApi(apiClient); + } + + private ApiClient getLcmApiClient(String vnfmId) { + VnfmInfo vnfmInfo = vnfmInfoProvider.getVnfmInfo(vnfmId); + ApiClient apiClient = new ApiClient(); + if (!skipCertificateVerification) { + apiClient.setSslCaCert(new ByteArrayInputStream(BaseEncoding.base64().decode(trustedCertificates))); + } else { + apiClient.setVerifyingSsl(false); + } + apiClient.setAccessToken(tokenProvider.getToken(vnfmId)); + apiClient.setBasePath(vnfmInfo.getUrl()); + return apiClient; + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CbamTokenProvider.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CbamTokenProvider.java new file mode 100644 index 00000000..e49c5720 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/CbamTokenProvider.java @@ -0,0 +1,250 @@ +/* + * 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.vnfm; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Joiner; +import com.google.common.io.BaseEncoding; +import com.google.gson.Gson; +import com.google.gson.annotations.SerializedName; +import okhttp3.*; +import org.apache.http.conn.ssl.DefaultHostnameVerifier; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VnfmInfoProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.StoreLoader; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions; +import org.onap.vnfmdriver.model.VnfmInfo; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; +import org.springframework.util.StringUtils; + +import javax.net.ssl.*; +import java.io.IOException; +import java.nio.charset.StandardCharsets; +import java.security.*; +import java.security.cert.CertificateException; +import java.security.cert.X509Certificate; +import java.security.spec.InvalidKeySpecException; +import java.util.Set; + +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.http.HttpHeaders.CONTENT_TYPE; +import static org.springframework.http.MediaType.APPLICATION_FORM_URLENCODED_VALUE; + +/** + * Responsible for providing a token to access CBAM APIs + */ +@Component +public class CbamTokenProvider { + public static final int MAX_RETRY_COUNT = 5; + private static final String CBAM_TOKEN_PATH = "/realms/cbam/protocol/openid-connect/token"; + private static Logger logger = getLogger(CbamTokenProvider.class); + private final VnfmInfoProvider vnfmInfoProvider; + @Value("${cbamKeyCloakBaseUrl}") + private String cbamKeyCloakBaseUrl; + @Value("${cbamUsername}") + private String username; + @Value("${cbamPassword}") + private String password; + @Value("${trustedCertificates}") + private String trustedCertificates; + @Value("${skipCertificateVerification}") + private boolean skipCertificateVerification; + @Value("${skipHostnameVerification}") + private boolean skipHostnameVerification; + private volatile CurrentToken token; + + @Autowired + CbamTokenProvider(VnfmInfoProvider vnfmInfoProvider) { + this.vnfmInfoProvider = vnfmInfoProvider; + } + + /** + * @return the token to access CBAM APIs (ex. 123456) + */ + public String getToken(String vnfmId) { + VnfmInfo vnfmInfo = vnfmInfoProvider.getVnfmInfo(vnfmId); + return getToken(vnfmInfo.getUserName(), vnfmInfo.getPassword()); + } + + private String getToken(String clientId, String clientSecret) { + logger.trace("Requesting token for accessing CBAM API"); + synchronized (this) { + long now = SystemFunctions.systemFunctions().currentTimeMillis(); + if (token == null || token.refreshAfter < now) { + if (token == null) { + logger.debug("No token: getting first token"); + } else { + logger.debug("Token expired " + (now - token.refreshAfter) + " ms ago"); + } + refresh(clientId, clientSecret); + } else { + logger.debug("Token will expire in " + (now - token.refreshAfter) + " ms"); + } + } + return token.token.accessToken; + } + + ; + + private void refresh(String clientId, String clientSecret) { + FormBody body = new FormBody.Builder() + .add("grant_type", "password") + .add("client_id", clientId) + .add("client_secret", clientSecret) + .add("username", username) + .add("password", password).build(); + Request request = new Request.Builder().url(cbamKeyCloakBaseUrl + CBAM_TOKEN_PATH).addHeader(CONTENT_TYPE, APPLICATION_FORM_URLENCODED_VALUE).post(body).build(); + OkHttpClient.Builder builder = new OkHttpClient.Builder(); + SSLSocketFactory sslSocketFac = buildSSLSocketFactory(); + HostnameVerifier hostnameVerifier = buildHostnameVerifier(); + OkHttpClient client = builder.sslSocketFactory(sslSocketFac).hostnameVerifier(hostnameVerifier).build(); + Exception lastException = null; + for (int i = 0; i < MAX_RETRY_COUNT; i++) { + try { + Response response = execute(client.newCall(request)); + if (response.isSuccessful()) { + String json = response.body().string(); + TokenResponse tokenResponse = new Gson().fromJson(json, TokenResponse.class); + //token is scheduled to be refreshed in the half time before expiring + token = new CurrentToken(tokenResponse, getTokenRefreshTime(tokenResponse)); + return; + } else { + throw new RuntimeException(); + } + } catch (Exception e) { + lastException = e; + logger.warn("Unable to get token to access CBAM API (" + (i + 1) + "/" + MAX_RETRY_COUNT + ")", e); + } + } + logger.error("Unable to get token to access CBAM API (giving up retries)", lastException); + throw new RuntimeException(lastException); + } + + @VisibleForTesting + Response execute(Call call) throws IOException { + return call.execute(); + } + + /** + * - a new token is requested after the half of the time has expired till which the currently + * used token is valid + * + * @param token the currently held token + * @return the point in time after which a new token must be requested + */ + private long getTokenRefreshTime(TokenResponse token) { + return SystemFunctions.systemFunctions().currentTimeMillis() + token.expiresIn * (1000 / 2); + } + + private HostnameVerifier buildHostnameVerifier() { + if (skipHostnameVerification) { + return new HostnameVerifier() { + @Override + public boolean verify(String hostname, SSLSession session) { + return true; + } + }; + } else { + return new DefaultHostnameVerifier(); + } + } + + @VisibleForTesting + SSLSocketFactory buildSSLSocketFactory() { + try { + TrustManager[] trustManagers = buildTrustManager(); + SSLContext sslContext = SSLContext.getInstance("TLS"); + sslContext.init(null, trustManagers, new SecureRandom()); + return sslContext.getSocketFactory(); + } catch (GeneralSecurityException e) { + logger.error("Unable to create SSL socket factory", e); + throw new RuntimeException(e); + } + } + + @VisibleForTesting + TrustManager[] buildTrustManager() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, CertificateException { + if (skipCertificateVerification) { + return new TrustManager[]{new AllTrustedTrustManager()}; + } else { + if (StringUtils.isEmpty(trustedCertificates)) { + throw new IllegalArgumentException("If the skipCertificateVerification is set to false (default) the trustedCertificates can not be empty"); + } + Set<String> trustedPems; + try { + trustedPems = StoreLoader.getCertifacates(new String(BaseEncoding.base64().decode(trustedCertificates), StandardCharsets.UTF_8)); + } catch (Exception e) { + throw new RuntimeException("The trustedCertificates must be a base64 encoded collection of PEM certificates", e); + } + KeyStore keyStore = StoreLoader.loadStore(Joiner.on("\n").join(trustedPems), "password", "password"); + TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm()); + trustManagerFactory.init(keyStore); + return trustManagerFactory.getTrustManagers(); + + } + } + + private static class CurrentToken { + private final TokenResponse token; + private final long refreshAfter; + + CurrentToken(TokenResponse token, long refreshAfter) { + this.refreshAfter = refreshAfter; + this.token = token; + } + } + + static class AllTrustedTrustManager implements X509TrustManager { + @Override + public void checkClientTrusted(X509Certificate[] chain, String authType) throws CertificateException { + + } + + @Override + public void checkServerTrusted(X509Certificate[] chain, String authType) throws CertificateException { + } + + @Override + public X509Certificate[] getAcceptedIssuers() { + return new X509Certificate[0]; + } + } + + /** + * Represents the token received from CBAM + */ + //FIXME use authentication swagger client instead + private static class TokenResponse { + @SerializedName("access_token") + String accessToken; + @SerializedName("expires_in") + int expiresIn; + @SerializedName("id_token") + String tokenId; + @SerializedName("not-before-policy") + int notBeforePolicy; + @SerializedName("refresh_expires_in") + int refreshExpiresIn; + @SerializedName("refresh_token") + String refreshToken; + @SerializedName("session_state") + String sessionState; + @SerializedName("token_type") + String tokenType; + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/DriverProperties.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/DriverProperties.java new file mode 100644 index 00000000..dfa674b7 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/DriverProperties.java @@ -0,0 +1,106 @@ +/* + * 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.vnfm; + +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.stereotype.Component; + +import java.util.Objects; + +/** + * Wraps the properties supplied to the servlet + */ +@Component +public class DriverProperties { + public static final String BASE_SUFFIX = "/" + SelfRegistrationManager.SERVICE_NAME + "/v1"; + public static final String BASE_URL = "/api" + BASE_SUFFIX; + public static final String LCN_PATH = "/lcn"; + + @Value("${cbamCatalogUrl}") + private String cbamCatalogUrl; + @Value("${cbamLcnUrl}") + private String cbamLcnUrl; + @Value("${vnfmId}") + private String vnfmId; + + /** + * @return the URL on which the CBAM catalog API can be accessed (ex. https://1.2.3.4:443/api/catalog/adapter ) + */ + public String getCbamCatalogUrl() { + return cbamCatalogUrl; + } + + /** + * @param cbamCatalogUrl the URL on which the CBAM catalog API can be accessed (ex. https://1.2.3.4:443/api/catalog/adapter ) + */ + public void setCbamCatalogUrl(String cbamCatalogUrl) { + this.cbamCatalogUrl = cbamCatalogUrl; + } + + /** + * @return the URL on which the CBAM LCN subscription API can be accessed (ex. https://1.2.3.4:443/vnfm/lcn/v3 ) + */ + public String getCbamLcnUrl() { + return cbamLcnUrl; + } + + /** + * @param cbamLcnUrl the URL on which the CBAM LCN subscription API can be accessed (ex. https://1.2.3.4:443/vnfm/lcn/v3 ) + */ + public void setCbamLcnUrl(String cbamLcnUrl) { + this.cbamLcnUrl = cbamLcnUrl; + } + + /** + * @return the identifier of the VNFM + */ + public String getVnfmId() { + return vnfmId; + } + + /** + * @param vnfmId the identifier of the VNFM + */ + public void setVnfmId(String vnfmId) { + this.vnfmId = vnfmId; + } + + @Override + public String toString() { + return "DriverProperties{" + + ", cbamCatalogUrl='" + cbamCatalogUrl + '\'' + + ", cbamLcnUrl='" + cbamLcnUrl + '\'' + + ", vnfmId='" + vnfmId + '\'' + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + DriverProperties that = (DriverProperties) o; + return Objects.equals(cbamCatalogUrl, that.cbamCatalogUrl) && + Objects.equals(cbamLcnUrl, that.cbamLcnUrl) && + Objects.equals(vnfmId, that.vnfmId); + } + + @Override + public int hashCode() { + return Objects.hash(cbamCatalogUrl, cbamLcnUrl, vnfmId); + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/ILifecycleChangeNotificationManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/ILifecycleChangeNotificationManager.java new file mode 100644 index 00000000..daf16fc3 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/ILifecycleChangeNotificationManager.java @@ -0,0 +1,59 @@ +/* + * 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.vnfm; + +import com.google.common.collect.Ordering; +import com.nokia.cbam.lcm.v32.model.OperationExecution; +import com.nokia.cbam.lcm.v32.model.VnfLifecycleChangeNotification; + +/** + * Responsible for handling CBAM notifications + */ +public interface ILifecycleChangeNotificationManager { + /** + * The key of the CBAM VNF extension for the identifier of the VNFM in ONAP + */ + String EXTERNAL_VNFM_ID = "externalVnfmId"; + + /** + * Separator for multiple keys concatenated into a single string + */ + String SEPARATOR = "_"; + + /** + * Order the operations by start time (latest first) + */ + Ordering<OperationExecution> NEWEST_OPERATIONS_FIRST = new Ordering<OperationExecution>() { + @Override + public int compare(OperationExecution left, OperationExecution right) { + return right.getStartTime().toLocalDate().compareTo(left.getStartTime().toLocalDate()); + } + }; + + /** + * Transform a CBAM LCN into ONAP LCN + * + * @param receivedNotification the CBAM LCN + */ + void handleLcn(VnfLifecycleChangeNotification receivedNotification); + + /** + * Wait for the termination finish notification to be processed + * + * @param operationExecutionId the identifier of the termination operation + */ + void waitForTerminationToBeProcessed(String operationExecutionId); +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/JobManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/JobManager.java new file mode 100644 index 00000000..d6b1cb20 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/JobManager.java @@ -0,0 +1,308 @@ +/* + * 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.vnfm; + +import com.google.common.collect.Ordering; +import com.google.common.collect.Sets; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.nokia.cbam.lcm.v32.ApiException; +import com.nokia.cbam.lcm.v32.api.OperationExecutionsApi; +import com.nokia.cbam.lcm.v32.api.VnfsApi; +import com.nokia.cbam.lcm.v32.model.OperationExecution; +import com.nokia.cbam.lcm.v32.model.VnfInfo; +import org.apache.http.HttpStatus; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.LifecycleChangeNotificationManager; +import org.onap.vnfmdriver.model.JobDetailInfo; +import org.onap.vnfmdriver.model.JobDetailInfoResponseDescriptor; +import org.onap.vnfmdriver.model.JobResponseInfo; +import org.onap.vnfmdriver.model.JobStatus; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import javax.servlet.http.HttpServletResponse; +import java.util.*; + +import static com.google.common.base.Splitter.on; +import static com.google.common.collect.Iterables.tryFind; +import static com.google.common.collect.Lists.newArrayList; +import static java.util.Optional.empty; +import static java.util.Optional.of; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions; +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.ILifecycleChangeNotificationManager.SEPARATOR; +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.util.StringUtils.isEmpty; + +/** + * Responsible for providing the status of jobs + * The job id is a composite field of the VNF identifier and an UUID. + * The second UUID is passed as mandatory parameter to each executed operation. + * This UUID is used to locate the operation execution from the ONAP job identifier + */ +@Component +public class JobManager { + private static final Ordering<JobResponseInfo> OLDEST_FIRST = new Ordering<JobResponseInfo>() { + @Override + public int compare(JobResponseInfo left, JobResponseInfo right) { + return Long.valueOf(left.getResponseId()).compareTo(Long.valueOf(right.getResponseId())); + } + }; + private static Logger logger = getLogger(JobManager.class); + private final Set<String> ongoingJobs = Sets.newConcurrentHashSet(); + private final CbamRestApiProvider cbamRestApiProvider; + private final SelfRegistrationManager selfRegistrationManager; + private volatile boolean preparingForShutDown = false; + + @Autowired + JobManager(CbamRestApiProvider cbamRestApiProvider, SelfRegistrationManager selfRegistrationManager) { + this.cbamRestApiProvider = cbamRestApiProvider; + this.selfRegistrationManager = selfRegistrationManager; + } + + /** + * @param operationParams the operation execution + * @return the ONAP job identifier of belonging to the operation execution + */ + public static String extractOnapJobId(Object operationParams) { + JsonElement operationParamsAsJson = new Gson().toJsonTree(operationParams); + JsonElement additionalParams = operationParamsAsJson.getAsJsonObject().get("additionalParams"); + if (additionalParams == null) { + throw new NoSuchElementException("The operation result " + operationParamsAsJson + " does not contain the mandatory additionalParams structure"); + } + JsonElement jobId = additionalParams.getAsJsonObject().get("jobId"); + if (jobId == null) { + throw new NoSuchElementException("The operation result " + operationParamsAsJson + " does not contain the mandatory jobId in the additionalParams structure"); + } + return jobId.getAsString(); + } + + /** + * Throws an exception in case the service is not ready to serve requests due to + * not being able to register to MSB or to subscribe to CBAM LCNs + * + * @param vnfId the identifier of the VNF + * @param response the HTTP response of the current sVNFM incomming request + * @return the identifier of the job + */ + public String spawnJob(String vnfId, HttpServletResponse response) { + String jobId = vnfId + SEPARATOR + UUID.randomUUID().toString(); + synchronized (this) { + if (preparingForShutDown) { + response.setStatus(HttpStatus.SC_SERVICE_UNAVAILABLE); + fatalFailure(logger, "The service is preparing to shut down"); + } + if (!selfRegistrationManager.isReady()) { + response.setStatus(HttpStatus.SC_SERVICE_UNAVAILABLE); + fatalFailure(logger, "The service is not yet ready"); + } + } + ongoingJobs.add(jobId); + return jobId; + } + + /** + * Signal that a job has finished + * + * @param jobId the identifier of the job + */ + public void jobFinished(String jobId) { + ongoingJobs.remove(jobId); + } + + /** + * @return the system has any ongoing jobs + */ + public boolean hasOngoingJobs() { + return ongoingJobs.size() != 0; + } + + + /** + * Wait for all jobs to be cleared from the system the refuses to let additional request in + */ + public void prepareForShutdown() { + preparingForShutDown = true; + while (true) { + synchronized (this) { + if (!hasOngoingJobs()) { + return; + } + } + systemFunctions().sleep(500L); + } + } + + /** + * @param vnfmId the identifier of the VNFM + * @param jobId the identifier of the job + * @return detailed information of the job + */ + public JobDetailInfo getJob(String vnfmId, String jobId) { + logger.debug("Retrieving the details for job with " + jobId); + ArrayList<String> jobParts = newArrayList(on(SEPARATOR).split(jobId)); + if (jobParts.size() != 2) { + throw new IllegalArgumentException("The jobId should be in the <vnfId>" + SEPARATOR + "<UUID> format, but was " + jobId); + } + String vnfId = jobParts.get(0); + if (isEmpty(vnfId)) { + throw new IllegalArgumentException("The vnfId in the jobId (" + jobId + ") can not be empty"); + } + String operationExecutionId = jobParts.get(1); + if (isEmpty(operationExecutionId)) { + throw new IllegalArgumentException("The UUID in the jobId (" + jobId + ") can not be empty"); + } + Optional<VnfInfo> vnf = getVnf(vnfmId, vnfId); + if (!vnf.isPresent()) { + return getJobDetailInfoForMissingVnf(jobId); + } else { + return getJobInfoForExistingVnf(vnfmId, jobId, vnfId, vnf); + } + } + + private JobDetailInfo getJobDetailInfoForMissingVnf(String jobId) { + if (ongoingJobs.contains(jobId)) { + return reportOngoing(jobId); + } else { + return reportFinished(jobId); + } + } + + private JobDetailInfo getJobInfoForExistingVnf(String vnfmId, String jobId, String vnfId, Optional<VnfInfo> vnf) { + try { + OperationExecution operation = findOperationByJobId(vnfmId, vnf, jobId); + switch (operation.getStatus()) { + case STARTED: + return reportOngoing(jobId); + case FINISHED: + case OTHER: + switch (operation.getOperationType()) { + case TERMINATE: + //termination includes VNF deletion in ONAP terminology + if (ongoingJobs.contains(jobId)) { + return reportOngoing(jobId); + } else { + //the VNF must be queried again since it could have been deleted since the VNF has been terminated + if (getVnf(vnfmId, vnfId).isPresent()) { + return reportFailed(jobId, "unable to delete VNF"); + } else { + return reportFinished(jobId); + } + } + default: + return reportFinished(jobId); + } + default: //all cases handled + case FAILED: + return reportFailed(jobId, operation.getError().getTitle() + ": " + operation.getError().getDetail()); + } + } catch (NoSuchElementException e) { + if (ongoingJobs.contains(jobId)) { + return reportOngoing(jobId); + } else { + return reportFailed(jobId, "The requested operation was not able to start on CBAM"); + } + } + } + + private JobDetailInfo buildJob(String jobId, JobResponseInfo... history) { + JobDetailInfo job = new JobDetailInfo(); + job.setJobId(jobId); + JobDetailInfoResponseDescriptor jobDetailInfoResponseDescriptor = new JobDetailInfoResponseDescriptor(); + job.setResponseDescriptor(jobDetailInfoResponseDescriptor); + List<JobResponseInfo> oldestFirst = OLDEST_FIRST.sortedCopy(newArrayList(history)); + JobResponseInfo newestJob = oldestFirst.get(oldestFirst.size() - 1); + jobDetailInfoResponseDescriptor.setResponseId(newestJob.getResponseId()); + jobDetailInfoResponseDescriptor.setStatus(JobStatus.valueOf(newestJob.getStatus())); + jobDetailInfoResponseDescriptor.setProgress(newestJob.getProgress()); + jobDetailInfoResponseDescriptor.setStatusDescription(newestJob.getStatusDescription()); + jobDetailInfoResponseDescriptor.setErrorCode(newestJob.getErrorCode()); + jobDetailInfoResponseDescriptor.setResponseHistoryList(oldestFirst); + return job; + } + + private JobResponseInfo buildJobPart(String description, JobStatus status, Integer progress, Integer responseId) { + JobResponseInfo currentJob = new JobResponseInfo(); + currentJob.setProgress(progress.toString()); + currentJob.setResponseId(responseId.toString()); + currentJob.setStatus(status.name()); + currentJob.setStatusDescription(description); + return currentJob; + } + + private JobDetailInfo reportOngoing(String jobId) { + return buildJob(jobId, buildJobPart("Operation started", JobStatus.STARTED, 50, 1)); + } + + private JobDetailInfo reportFailed(String jobId, String reason) { + return buildJob(jobId, + buildJobPart("Operation started", JobStatus.STARTED, 50, 1), + buildJobPart("Operation failed due to " + reason, JobStatus.ERROR, 100, 2) + ); + } + + private JobDetailInfo reportFinished(String jobId) { + return buildJob(jobId, + buildJobPart("Operation started", JobStatus.STARTED, 50, 1), + buildJobPart("Operation finished", JobStatus.FINISHED, 100, 2) + ); + } + + private OperationExecution findOperationByJobId(String vnfmId, Optional<VnfInfo> vnf, String jobId) { + OperationExecutionsApi cbamOperationExecutionApi = cbamRestApiProvider.getCbamOperationExecutionApi(vnfmId); + //the operations are sorted so that the newest operations are queried first + //performance optimization that usually the core system is interested in the operations executed last + if (vnf.get().getOperationExecutions() != null) { + for (OperationExecution operationExecution : LifecycleChangeNotificationManager.NEWEST_OPERATIONS_FIRST.sortedCopy(vnf.get().getOperationExecutions())) { + try { + Object operationParams = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operationExecution.getId(), NOKIA_LCM_API_VERSION); + if (extractOnapJobId(operationParams).equals(jobId)) { + return operationExecution; + } + } catch (ApiException e) { + logger.error("Unable to retrieve operation parameters", e); + throw new RuntimeException(e); + } + } + } + throw new NoSuchElementException(); + } + + private Optional<VnfInfo> getVnf(String vnfmId, String vnfId) { + try { + //test if the VNF exists (required to be able to distingush between failed request ) + VnfsApi cbamLcmApi = cbamRestApiProvider.getCbamLcmApi(vnfmId); + logger.debug("Listing VNFs"); + List<VnfInfo> vnfs = cbamLcmApi.vnfsGet(NOKIA_LCM_API_VERSION); + com.google.common.base.Optional<VnfInfo> vnf = tryFind(vnfs, vnfInfo -> vnfId.equals(vnfInfo.getId())); + if (!vnf.isPresent()) { + logger.debug("VNF with " + vnfId + " is missing"); + return empty(); + } else { + logger.debug("VNF with " + vnfId + " still exists"); + //query the VNF again to get operation execution result + return of(cbamLcmApi.vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION)); + } + } catch (ApiException e) { + logger.error("Unable to retrieve VNF", e); + throw new RuntimeException(e); + } + } + +} 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 new file mode 100644 index 00000000..e835e35c --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/LifecycleManager.java @@ -0,0 +1,537 @@ +/* + * 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.vnfm; + + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.nokia.cbam.catalog.v1.model.CatalogAdapterVnfpackage; +import com.nokia.cbam.lcm.v32.ApiException; +import com.nokia.cbam.lcm.v32.model.*; +import com.nokia.cbam.lcm.v32.model.ScaleDirection; +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.vnfmdriver.model.ExtVirtualLinkInfo; +import org.onap.vnfmdriver.model.*; +import org.onap.vnfmdriver.model.VimInfo; +import org.onap.vnfmdriver.model.VnfInfo; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; +import org.yaml.snakeyaml.Yaml; + +import javax.servlet.http.HttpServletResponse; +import java.util.*; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import static com.google.common.base.Splitter.on; +import static com.google.common.collect.Iterables.find; +import static com.google.common.collect.Lists.newArrayList; +import static com.nokia.cbam.lcm.v32.model.OperationType.INSTANTIATE; +import static com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum.*; +import static java.lang.Integer.parseInt; +import static java.nio.charset.StandardCharsets.UTF_8; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.*; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions; +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.ILifecycleChangeNotificationManager.*; +import static org.slf4j.LoggerFactory.getLogger; +import static org.springframework.util.StringUtils.isEmpty; + +/** + * Responsible for executing lifecycle operation on the VNF + */ +@Component +public class LifecycleManager { + public static final String ONAP_CSAR_ID = "onapCsarId"; + public static final long OPERATION_STATUS_POLLING_INTERVAL_IN_MS = 5000L; + private static Logger logger = getLogger(LifecycleManager.class); + private final CatalogManager catalogManager; + private final IGrantManager grantManager; + private final JobManager jobManager; + private final ILifecycleChangeNotificationManager notificationManager; + private final CbamRestApiProvider cbamRestApiProvider; + private final VimInfoProvider vimInfoProvider; + + /** + * Runs asynchronous operations in the background + */ + private ExecutorService executorService = Executors.newCachedThreadPool(); + + @Autowired + LifecycleManager(CatalogManager catalogManager, IGrantManager grantManager, CbamRestApiProvider restApiProvider, VimInfoProvider vimInfoProvider, JobManager jobManager, ILifecycleChangeNotificationManager notificationManager) { + this.vimInfoProvider = vimInfoProvider; + this.grantManager = grantManager; + this.cbamRestApiProvider = restApiProvider; + this.jobManager = jobManager; + this.notificationManager = notificationManager; + this.catalogManager = catalogManager; + } + + public static String getRegionName(String vimId) { + return newArrayList(on(SEPARATOR).split(vimId)).get(1); + } + + public static String getCloudOwner(String vimId) { + return newArrayList(on(SEPARATOR).split(vimId)).get(0); + } + + private static OperationExecution findLastInstantiation(List<OperationExecution> operationExecutions) { + return find(NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions), op -> INSTANTIATE.equals(op.getOperationType())); + } + + /** + * Instantiate (VF-C terminology) the VNF. It consists of the following steps + * <ul> + * <li>upload the VNF package to CBAM package (if not already there)</li> + * <li>create the VNF on CBAM</li> + * <li>modify attributes of the VNF (add onapCsarId field)</li> + * <li>asynchronously</li> + * <li>request grant from VF-C</li> + * <li>instantiate VNF on CBAM</li> + * <li>return VNF & job id (after create VNF on CBAM)</li> + * <li></li> + * </ul> + * The rollback of the failed operation is not implemented + * <ul> + * <li>delete the VNF if error occurs before instantiation</li> + * <li>terminate & delete VNf if error occurs after instantiation</li> + * </ul> + * + * @param vnfmId the identifier of the VNFM + * @param request the instantiation request + * @param httpResponse the HTTP response + * @return the instantiation response + */ + public VnfInstantiateResponse instantiate(String vnfmId, VnfInstantiateRequest request, HttpServletResponse httpResponse) { + logger.info("Additional parameters for instantiation: " + new Gson().toJson(request.getAdditionalParam())); + AdditionalParams additionalParams = convertInstantiationAdditionalParams(request.getVnfPackageId(), request.getAdditionalParam()); + validateVimType(additionalParams); + CatalogAdapterVnfpackage cbamPackage = catalogManager.preparePackageInCbam(vnfmId, request.getVnfPackageId()); + try { + CreateVnfRequest vnfCreateRequest = new CreateVnfRequest(); + vnfCreateRequest.setVnfdId(cbamPackage.getId()); + vnfCreateRequest.setName(request.getVnfInstanceName()); + vnfCreateRequest.setDescription(request.getVnfInstanceDescription()); + com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsPost(vnfCreateRequest, NOKIA_LCM_API_VERSION); + VnfInstantiateResponse response = new VnfInstantiateResponse(); + response.setVnfInstanceId(vnfInfo.getId()); + //FIXME the vimId should be send during grant response (VFC-604) + String vimId = getVimId(request.getAdditionalParam()); + addVnfdIdToVnfModifyableAttributeExtensions(vnfmId, vnfInfo.getId(), request.getVnfPackageId()); + JobInfo spawnJob = scheduleExecution(vnfInfo.getId(), httpResponse, "instantiate", (jobInfo) -> { + String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, cbamPackage.getId()); + GrantVNFResponseVim vim = grantManager.requestGrantForInstantiate(vnfmId, vnfInfo.getId(), vimId, request.getVnfPackageId(), additionalParams.getInstantiationLevel(), vnfdContent, jobInfo.getJobId()); + if (vim.getVimId() == null) { + fatalFailure(logger, "VF-C did not send VIM identifier in grant response"); + } + VimInfo vimInfo = vimInfoProvider.getVimInfo(vim.getVimId()); + InstantiateVnfRequest instantiationRequest = new InstantiateVnfRequest(); + addExernalLinksToRequest(request.getExtVirtualLink(), additionalParams, instantiationRequest, vimId); + switch (additionalParams.getVimType()) { + case OPENSTACK_V2_INFO: + instantiationRequest.getVims().add(buildOpenStackV2INFO(vimId, vim, vimInfo)); + break; + case OPENSTACK_V3_INFO: + instantiationRequest.getVims().add(buildOpenStackV3INFO(vimId, additionalParams, vim, vimInfo)); + break; + case VMWARE_VCLOUD_INFO: + instantiationRequest.getVims().add(buildVcloudInfo(vimId, vim, vimInfo)); + break; + } + instantiationRequest.setFlavourId(getFlavorId(vnfdContent)); + instantiationRequest.setComputeResourceFlavours(additionalParams.getComputeResourceFlavours()); + instantiationRequest.setGrantlessMode(true); + instantiationRequest.setInstantiationLevelId(additionalParams.getInstantiationLevel()); + instantiationRequest.setSoftwareImages(additionalParams.getSoftwareImages()); + instantiationRequest.setZones(additionalParams.getZones()); + instantiationRequest.setExtManagedVirtualLinks(additionalParams.getExtManagedVirtualLinks()); + for (ExtVirtualLinkData extVirtualLinkData : additionalParams.getExtVirtualLinks()) { + instantiationRequest.addExtVirtualLinksItem(extVirtualLinkData); + } + JsonObject root = new Gson().toJsonTree(jobInfo).getAsJsonObject(); + if (additionalParams.getAdditionalParams() != null && !isEmpty(additionalParams.getAdditionalParams().toString())) { + for (Map.Entry<String, JsonElement> item : new Gson().toJsonTree(additionalParams.getAdditionalParams()).getAsJsonObject().entrySet()) { + root.add(item.getKey(), item.getValue()); + } + } + instantiationRequest.setAdditionalParams(root); + OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdInstantiatePost(vnfInfo.getId(), instantiationRequest, NOKIA_LCM_API_VERSION); + waitForOperationToFinish(vnfmId, vnfInfo.getId(), operationExecution.getId(), jobInfo.getJobId()); + }); + response.setJobId(spawnJob.getJobId()); + return response; + } catch (Exception e) { + throw fatalFailure(logger, "Unable to create the VNF", e); + } + } + + private void validateVimType(AdditionalParams additionalParams) { + switch (additionalParams.getVimType()) { + case OPENSTACK_V2_INFO: + case OPENSTACK_V3_INFO: + case VMWARE_VCLOUD_INFO: + break; + default: + throw fatalFailure(logger, "Only " + OPENSTACK_V2_INFO + ", " + OPENSTACK_V3_INFO + " and " + VMWARE_VCLOUD_INFO + " is the supported VIM types"); + } + } + + private String getVimId(Object additionalParams) { + return childElement(new Gson().toJsonTree(additionalParams).getAsJsonObject(), "vimId").getAsString(); + } + + private AdditionalParams convertInstantiationAdditionalParams(String csarId, Object additionalParams) { + JsonObject vnfParameters = child(child(new Gson().toJsonTree(additionalParams).getAsJsonObject(), "inputs"), "vnfs"); + if (!vnfParameters.has(csarId)) { + throw fatalFailure(logger, "The additional parameter section does not contain setting for VNF with " + csarId + " CSAR id"); + } + JsonElement additionalParamsForVnf = vnfParameters.get(csarId); + return new Gson().fromJson(additionalParamsForVnf, AdditionalParams.class); + } + + private String getFlavorId(String vnfdContent) { + JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject(); + JsonObject capabilities = child(child(child(root, "topology_template"), "substitution_mappings"), "capabilities"); + JsonObject deploymentFlavorProperties = child(child(capabilities, "deployment_flavour"), "properties"); + return childElement(deploymentFlavorProperties, "flavour_id").getAsString(); + } + + private Set<String> getAcceptableOperationParameters(String vnfdContent, String categroryOfOperation, String operationName) { + JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject(); + JsonObject interfaces = child(child(child(root, "topology_template"), "substitution_mappings"), "interfaces"); + JsonObject additionalParameters = child(child(child(child(interfaces, categroryOfOperation), operationName), "inputs"), "additional_parameters"); + return additionalParameters.keySet(); + } + + private void addExernalLinksToRequest(List<ExtVirtualLinkInfo> extVirtualLinks, AdditionalParams additionalParams, InstantiateVnfRequest instantiationRequest, String vimId) { + for (ExtVirtualLinkInfo extVirtualLink : extVirtualLinks) { + ExtVirtualLinkData cbamExternalVirtualLink = new ExtVirtualLinkData(); + cbamExternalVirtualLink.setVimId(vimId); + cbamExternalVirtualLink.setResourceId(extVirtualLink.getResourceId()); + VnfExtCpData ecp = new VnfExtCpData(); + cbamExternalVirtualLink.setExtVirtualLinkId(extVirtualLink.getVlInstanceId()); + cbamExternalVirtualLink.getExtCps().add(ecp); + ecp.setCpdId(extVirtualLink.getCpdId()); + List<NetworkAddress> addresses = additionalParams.getExternalConnectionPointAddresses().get(extVirtualLink.getCpdId()); + ecp.setAddresses(addresses); + instantiationRequest.addExtVirtualLinksItem(cbamExternalVirtualLink); + } + } + + private void addVnfdIdToVnfModifyableAttributeExtensions(String vnfmId, String vnfId, String onapCsarId) { + ModifyVnfInfoRequest request = new ModifyVnfInfoRequest(); + VnfProperty onapCsarIdProperty = new VnfProperty(); + onapCsarIdProperty.setName(ONAP_CSAR_ID); + onapCsarIdProperty.setValue(onapCsarId); + request.setExtensions(new ArrayList<>()); + request.getExtensions().add(onapCsarIdProperty); + VnfProperty externalVnfmIdProperty = new VnfProperty(); + externalVnfmIdProperty.setName(EXTERNAL_VNFM_ID); + externalVnfmIdProperty.setValue(vnfmId); + request.getExtensions().add(externalVnfmIdProperty); + request.setVnfConfigurableProperties(null); + try { + OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdPatch(vnfId, request, NOKIA_LCM_API_VERSION); + waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId(), NOKIA_LCM_API_VERSION); + } catch (ApiException e) { + throw fatalFailure(logger, "Unable to set the " + ONAP_CSAR_ID + " property on the VNF", e); + } + } + + private OPENSTACKV3INFO buildOpenStackV3INFO(String vimId, AdditionalParams additionalParams, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) { + OPENSTACKV3INFO openstackv3INFO = new OPENSTACKV3INFO(); + openstackv3INFO.setVimInfoType(OPENSTACK_V3_INFO); + OpenStackAccessInfoV3 accessInfov3 = new OpenStackAccessInfoV3(); + openstackv3INFO.accessInfo(accessInfov3); + accessInfov3.setPassword(vimInfo.getPassword()); + accessInfov3.setDomain(additionalParams.getDomain()); + accessInfov3.setProject(vim.getAccessInfo().getTenant()); + accessInfov3.setRegion(getRegionName(vimId)); + accessInfov3.setUsername(vimInfo.getUserName()); + EndpointInfo interfaceInfoV3 = new EndpointInfo(); + interfaceInfoV3.setEndpoint(vimInfo.getUrl()); + if (!isEmpty(vimInfo.getSslInsecure())) { + interfaceInfoV3.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure())); + interfaceInfoV3.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure())); + } + if (!interfaceInfoV3.isSkipCertificateVerification()) { + interfaceInfoV3.setTrustedCertificates(new ArrayList<>()); + for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) { + interfaceInfoV3.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8)); + } + } + openstackv3INFO.setInterfaceInfo(interfaceInfoV3); + openstackv3INFO.setId(vimId); + return openstackv3INFO; + } + + private OPENSTACKV2INFO buildOpenStackV2INFO(String vimId, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) { + OPENSTACKV2INFO openstackv2INFO = new OPENSTACKV2INFO(); + openstackv2INFO.setVimInfoType(OPENSTACK_V2_INFO); + OpenStackAccessInfoV2 accessInfo = new OpenStackAccessInfoV2(); + openstackv2INFO.setAccessInfo(accessInfo); + accessInfo.setPassword(vimInfo.getPassword()); + accessInfo.setTenant(vim.getAccessInfo().getTenant()); + accessInfo.setUsername(vimInfo.getUserName()); + accessInfo.setRegion(getRegionName(vimId)); + EndpointInfo interfaceEndpoint = new EndpointInfo(); + if (!isEmpty(vimInfo.getSslInsecure())) { + interfaceEndpoint.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure())); + interfaceEndpoint.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure())); + } + interfaceEndpoint.setEndpoint(vimInfo.getUrl()); + if (!interfaceEndpoint.isSkipCertificateVerification()) { + interfaceEndpoint.setTrustedCertificates(new ArrayList<>()); + for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) { + interfaceEndpoint.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8)); + } + } + openstackv2INFO.setInterfaceInfo(interfaceEndpoint); + openstackv2INFO.setId(vimId); + return openstackv2INFO; + } + + private VMWAREVCLOUDINFO buildVcloudInfo(String vimId, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) { + VMWAREVCLOUDINFO vcloudInfo = new VMWAREVCLOUDINFO(); + vcloudInfo.setVimInfoType(VMWARE_VCLOUD_INFO); + VCloudAccessInfo accessInfo = new VCloudAccessInfo(); + vcloudInfo.setAccessInfo(accessInfo); + accessInfo.setPassword(vimInfo.getPassword()); + accessInfo.setUsername(vimInfo.getUserName()); + accessInfo.setOrganization(getRegionName(vimId)); + EndpointInfo interfaceEndpoint = new EndpointInfo(); + if (!isEmpty(vimInfo.getSslInsecure())) { + interfaceEndpoint.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure())); + interfaceEndpoint.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure())); + } + interfaceEndpoint.setEndpoint(vimInfo.getUrl()); + if (!interfaceEndpoint.isSkipCertificateVerification()) { + interfaceEndpoint.setTrustedCertificates(new ArrayList<>()); + for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) { + interfaceEndpoint.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8)); + } + } + vcloudInfo.setInterfaceInfo(interfaceEndpoint); + vcloudInfo.setId(vimId); + return vcloudInfo; + } + + /** + * Terminates and deletes the VNF + * <ul> + * <li>fails if the VNF does not exist</li> + * <li>terminates if instantiated</li> + * <li>deletes the VNF</li> + * </ul> + * + * @param vnfmId the identifier of the VNFM + * @param vnfId the identifier of the VNF + * @param request the termination request + * @param httpResponse the HTTP response + * @return the job for polling the progress of the termination + */ + public JobInfo terminateVnf(String vnfmId, String vnfId, VnfTerminateRequest request, HttpServletResponse httpResponse) { + return scheduleExecution(vnfId, httpResponse, "terminate", (jobInfo) -> { + TerminateVnfRequest cbamRequest = new TerminateVnfRequest(); + cbamRequest.setAdditionalParams(jobInfo); + 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); + } + } + com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION); + switch (vnf.getInstantiationState()) { + case 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); + OperationExecution finishedOperation = waitForOperationToFinish(vnfmId, vnfId, terminationOperation.getId(), jobInfo.getJobId()); + switch (finishedOperation.getStatus()) { + case FINISHED: + notificationManager.waitForTerminationToBeProcessed(finishedOperation.getId()); + logger.info("Deleting VNF with " + vnfId); + cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION); + logger.info("VNF with " + vnfId + " has been deleted"); + break; + default: + logger.error("Unable to terminate VNF the operation did not finish with success"); + } + break; + case NOT_INSTANTIATED: + cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION); + break; + } + }); + } + + private String getVimIdFromInstantiationRequest(String vnfmId, com.nokia.cbam.lcm.v32.model.VnfInfo vnf) throws ApiException { + OperationExecution lastInstantiation = findLastInstantiation(vnf.getOperationExecutions()); + Object operationParameters = cbamRestApiProvider.getCbamOperationExecutionApi(vnfmId).operationExecutionsOperationExecutionIdOperationParamsGet(lastInstantiation.getId(), NOKIA_LCM_API_VERSION); + JsonObject root = new Gson().toJsonTree(operationParameters).getAsJsonObject(); + 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 + * @return the current state of the VNF + */ + 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); + 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; + } catch (ApiException e) { + throw fatalFailure(logger, "Unable to query VNF (" + vnfId + ")", e); + } + } + + private ScaleDirection convert(org.onap.vnfmdriver.model.ScaleDirection direction) { + if (org.onap.vnfmdriver.model.ScaleDirection.IN.equals(direction)) { + return ScaleDirection.IN; + } else { + return ScaleDirection.OUT; + } + } + + /** + * Scale the VNF + * + * @param vnfmId the identifier of the VNFM + * @param vnfId the identifier of the VNF + * @param request the scale request + * @param httpResponse the HTTP response + * @return the job for tracking the scale + */ + public JobInfo scaleVnf(String vnfmId, String vnfId, VnfScaleRequest request, HttpServletResponse httpResponse) { + logger.info("Scale VNF " + vnfId + " " + new Gson().toJson(request)); + return scheduleExecution(vnfId, httpResponse, "scale", (jobInfo) -> { + ScaleVnfRequest cbamRequest = new ScaleVnfRequest(); + cbamRequest.setAspectId(request.getAspectId()); + cbamRequest.setNumberOfSteps(Integer.valueOf(request.getNumberOfSteps())); + cbamRequest.setType(convert(request.getType())); + com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION); + JsonObject root = new Gson().toJsonTree(jobInfo).getAsJsonObject(); + com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION); + String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, cbamVnfInfo.getVnfdId()); + Set<String> acceptableOperationParameters = getAcceptableOperationParameters(vnfdContent, "Basic", "scale"); + if (request.getAdditionalParam() != null) { + for (Map.Entry<String, JsonElement> item : new Gson().toJsonTree(request.getAdditionalParam()).getAsJsonObject().entrySet()) { + if (acceptableOperationParameters.contains(item.getKey())) { + root.add(item.getKey(), item.getValue()); + } + } + } + cbamRequest.setAdditionalParams(root); + grantManager.requestGrantForScale(vnfmId, vnfId, getVimIdFromInstantiationRequest(vnfmId, vnf), getVnfdIdFromModifyableAttributes(vnf), request, jobInfo.getJobId()); + OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdScalePost(vnfId, cbamRequest, NOKIA_LCM_API_VERSION); + waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId(), jobInfo.getJobId()); + }); + } + + /** + * Heal the VNF + * + * @param vnfmId the identifier of the VNFM + * @param vnfId the identifier of the VNF + * @param request the heal request + * @param httpResponse the HTTP response + * @return the job for tracking the heal + */ + public JobInfo healVnf(String vnfmId, String vnfId, VnfHealRequest request, HttpServletResponse httpResponse) { + return scheduleExecution(vnfId, httpResponse, "heal", (job) -> { + HealVnfRequest cbamHealRequest = new HealVnfRequest(); + Map<String, String> additionalParams = new HashMap<>(); + additionalParams.put("vmName", request.getAffectedvm().getVmname()); + additionalParams.put("action", request.getAction()); + additionalParams.put("jobId", job.getJobId()); + cbamHealRequest.setAdditionalParams(additionalParams); + com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION); + String vimId = getVimIdFromInstantiationRequest(vnfmId, vnf); + grantManager.requestGrantForHeal(vnfmId, vnfId, vimId, getVnfdIdFromModifyableAttributes(vnf), request, job.getJobId()); + OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdHealPost(vnfId, cbamHealRequest, NOKIA_LCM_API_VERSION); + waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId(), job.getJobId()); + }); + } + + private JobInfo scheduleExecution(String vnfId, HttpServletResponse httpResponse, String operation, AsynchronousExecution asynchronExecution) { + JobInfo jobInfo = new JobInfo(); + jobInfo.setJobId(jobManager.spawnJob(vnfId, httpResponse)); + executorService.submit(() -> { + try { + asynchronExecution.execute(jobInfo); + } catch (RuntimeException e) { + logger.error("Unable to " + operation + " VNF with " + vnfId + " identifier", e); + jobManager.jobFinished(jobInfo.getJobId()); + throw e; + } catch (Exception e) { + String msg = "Unable to " + operation + " VNF with " + vnfId + " identifier"; + logger.error(msg, e); + //the job can only be signaled to be finished after the error is logged + jobManager.jobFinished(jobInfo.getJobId()); + throw new RuntimeException(msg, e); + } + jobManager.jobFinished(jobInfo.getJobId()); + }); + return jobInfo; + } + + private OperationExecution waitForOperationToFinish(String vnfmId, String vnfId, String operationExecutionId, String jobId) { + while (true) { + try { + OperationExecution operationExecution = find(cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdOperationExecutionsGet(vnfId, NOKIA_LCM_API_VERSION), opEx -> operationExecutionId.equals(opEx.getId())); + switch (operationExecution.getStatus()) { + case FINISHED: + case FAILED: + logger.debug("Operation finished with " + operationExecution.getId()); + return operationExecution; + } + } catch (Exception e) { + //swallow exception and retry + logger.warn("Unable to retrieve operations details", e); + } + systemFunctions().sleep(OPERATION_STATUS_POLLING_INTERVAL_IN_MS); + } + } + + private interface AsynchronousExecution { + void execute(JobInfo job) throws Exception; + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/LifecycleChangeNotificationManager.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/LifecycleChangeNotificationManager.java new file mode 100644 index 00000000..142072d5 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/LifecycleChangeNotificationManager.java @@ -0,0 +1,211 @@ +/* + * 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.vnfm.notification; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.collect.Iterables; +import com.google.common.collect.Sets; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.nokia.cbam.lcm.v32.ApiException; +import com.nokia.cbam.lcm.v32.api.OperationExecutionsApi; +import com.nokia.cbam.lcm.v32.api.VnfsApi; +import com.nokia.cbam.lcm.v32.model.*; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.INotificationSender; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.DriverProperties; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.ILifecycleChangeNotificationManager; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Component; + +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Set; + +import static com.google.common.collect.Iterables.filter; +import static com.google.common.collect.Iterables.tryFind; +import static com.google.common.collect.Sets.newConcurrentHashSet; +import static com.nokia.cbam.lcm.v32.model.OperationType.INSTANTIATE; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.childElement; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.fatalFailure; +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.CbamRestApiProvider.NOKIA_LCN_API_VERSION; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Responsible for handling lifecycle change notifications from CBAM. + * The received LCNs are transformed into ONAP LCNs. + * The following CBAM LCNs are processed: + * - HEAL + * - INSTANTIATE + * - SCALE + * - TERMINATE + * The current limitations + * - if a LCN can not be be processed due to VNF having been deleted the problem is logged and CBAM is notified that + * the LCN has been processed (even if not in reality) because the signaling of failed LCN delivery blocks the delivery + * on all LCN deliveries. The consequence of this is that the information known by VF-C / A&AI may be inconsistent with + * reality (VNF having been deleted) + */ +@Component +public class LifecycleChangeNotificationManager implements ILifecycleChangeNotificationManager { + + public static final String PROBLEM = "All operations must return the { \"operationResult\" : { \"cbam_pre\" : [<fillMeOut>], \"cbam_post\" : [<fillMeOut>] } } structure"; + /** + * < Separates the VNF id and the resource id within a VNF + */ + private static final Set<OperationStatus> terminalStatus = Sets.newHashSet(OperationStatus.FINISHED, OperationStatus.FAILED); + private static Logger logger = getLogger(LifecycleChangeNotificationManager.class); + + private final CbamRestApiProvider restApiProvider; + private final DriverProperties driverProperties; + private final INotificationSender notificationSender; + private Set<ProcessedNotification> processedNotifications = newConcurrentHashSet(); + + @Autowired + LifecycleChangeNotificationManager(CbamRestApiProvider restApiProvider, DriverProperties driverProperties, INotificationSender notificationSender) { + this.notificationSender = notificationSender; + this.driverProperties = driverProperties; + this.restApiProvider = restApiProvider; + } + + @VisibleForTesting + static OperationExecution findLastInstantiationBefore(List<OperationExecution> operationExecutions, OperationExecution currentOperation) { + for (OperationExecution opExs : filter(NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions), (OperationExecution opex2) -> !opex2.getStartTime().isAfter(currentOperation.getStartTime()))) { + if (INSTANTIATE.equals(opExs.getOperationType()) && + (opExs.getStartTime().toLocalDate().isBefore(currentOperation.getStartTime().toLocalDate()) || + opExs.getStartTime().toLocalDate().isEqual(currentOperation.getStartTime().toLocalDate()) + )) { + return opExs; + } + } + throw new NoSuchElementException(); + } + + @Override + public void handleLcn(VnfLifecycleChangeNotification recievedNotification) { + logger.info("Received LCN: " + new Gson().toJson(recievedNotification)); + VnfsApi cbamLcmApi = restApiProvider.getCbamLcmApi(driverProperties.getVnfmId()); + try { + List<VnfInfo> vnfs = cbamLcmApi.vnfsGet(NOKIA_LCM_API_VERSION); + com.google.common.base.Optional<VnfInfo> currentVnf = tryFind(vnfs, vnf -> vnf.getId().equals(recievedNotification.getVnfInstanceId())); + if (!currentVnf.isPresent()) { + logger.warn("The VNF with " + recievedNotification.getVnfInstanceId() + " disappeared before being able to process the LCN"); + //swallow LCN + return; + } else { + VnfInfo vnf = cbamLcmApi.vnfsVnfInstanceIdGet(recievedNotification.getVnfInstanceId(), NOKIA_LCN_API_VERSION); + com.google.common.base.Optional<VnfProperty> externalVnfmId = tryFind(vnf.getExtensions(), prop -> prop.getName().equals(EXTERNAL_VNFM_ID)); + if (!externalVnfmId.isPresent()) { + logger.warn("The VNF with " + vnf.getId() + " identifier is not a managed VNF"); + return; + } + if (!externalVnfmId.get().getValue().equals(driverProperties.getVnfmId())) { + logger.warn("The VNF with " + vnf.getId() + " identifier is not a managed by the VNFM with id " + externalVnfmId.get().getValue()); + return; + } + } + } catch (Exception e) { + logger.error("Unable to list VNFs / query VNF", e); + throw new RuntimeException("Unable to list VNFs / query VNF", e); + } + OperationExecutionsApi cbamOperationExecutionApi = restApiProvider.getCbamOperationExecutionApi(driverProperties.getVnfmId()); + try { + List<OperationExecution> operationExecutions = cbamLcmApi.vnfsVnfInstanceIdOperationExecutionsGet(recievedNotification.getVnfInstanceId(), NOKIA_LCM_API_VERSION); + OperationExecution operationExecution = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdGet(recievedNotification.getLifecycleOperationOccurrenceId(), NOKIA_LCM_API_VERSION); + OperationExecution closestInstantiationToOperation = findLastInstantiationBefore(operationExecutions, operationExecution); + String vimId; + try { + Object operationParams = cbamOperationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(closestInstantiationToOperation.getId(), NOKIA_LCM_API_VERSION); + vimId = getVimId(operationParams); + } catch (Exception e) { + logger.error("Unable to detect last instantiation operation", e); + throw new RuntimeException("Unable to detect last instantiation operation", e); + } + notificationSender.processNotification(recievedNotification, operationExecution, buildAffectedCps(operationExecution), vimId); + if (OperationType.TERMINATE.equals(recievedNotification.getOperation()) && terminalStatus.contains(recievedNotification.getStatus())) { + processedNotifications.add(new ProcessedNotification(recievedNotification.getLifecycleOperationOccurrenceId(), recievedNotification.getStatus())); + } + } catch (ApiException e) { + logger.error("Unable to retrieve the current VNF " + recievedNotification.getVnfInstanceId(), e); + throw new RuntimeException("Unable to retrieve the current VNF " + recievedNotification.getVnfInstanceId(), e); + } + } + + @Override + public void waitForTerminationToBeProcessed(String operationExecutionId) { + while (true) { + com.google.common.base.Optional<ProcessedNotification> notification = Iterables.tryFind(processedNotifications, processedNotification -> processedNotification.getOperationExecutionId().equals(operationExecutionId)); + if (notification.isPresent()) { + processedNotifications.remove(notification.get()); + return; + } + SystemFunctions.systemFunctions().sleep(500); + } + } + + private String getVimId(Object instantiationParameters) { + InstantiateVnfRequest request = new Gson().fromJson(new Gson().toJson(instantiationParameters), InstantiateVnfRequest.class); + return request.getVims().get(0).getId(); + } + + private ReportedAffectedConnectionPoints buildAffectedCps(OperationExecution operationExecution) { + switch (operationExecution.getOperationType()) { + case TERMINATE: + String terminationType = childElement(new Gson().toJsonTree(operationExecution.getOperationParams()).getAsJsonObject(), "terminationType").getAsString(); + if (TerminationType.FORCEFUL.name().equals(terminationType)) { + //in case of force full termination the Ansible is not executed, so the connection points can not be + //calculated from operation execution result + logger.warn("Unable to send information related to affected connection points during forceful termination"); + return null; + } + } + try { + JsonElement root = new Gson().toJsonTree(operationExecution.getAdditionalData()); + if (root.getAsJsonObject().has("operationResult")) { + JsonObject operationResult = root.getAsJsonObject().get("operationResult").getAsJsonObject(); + if (!isPresent(operationResult, "cbam_pre") || !isPresent(operationResult, "cbam_post")) { + handleFailure(operationExecution, null); + } + return new Gson().fromJson(operationResult, ReportedAffectedConnectionPoints.class); + } + } catch (Exception e) { + handleFailure(operationExecution, e); + } + return new ReportedAffectedConnectionPoints(); + } + + private boolean isPresent(JsonObject operationResult, String key) { + return operationResult.has(key) && operationResult.get(key).isJsonArray(); + } + + private void handleFailure(OperationExecution operationExecution, Exception e) { + switch (operationExecution.getStatus()) { + case FAILED: + case OTHER: + logger.warn("The operation failed and the affected connection points were not reported"); + break; + case STARTED: //can not happen (the changed resources are only executed for terminal state + case FINISHED: + if (e != null) { + fatalFailure(logger, PROBLEM, e); + } + fatalFailure(logger, PROBLEM); + } + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ProcessedNotification.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ProcessedNotification.java new file mode 100644 index 00000000..044e1ca2 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ProcessedNotification.java @@ -0,0 +1,85 @@ +/* + * 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.vnfm.notification; + +import com.nokia.cbam.lcm.v32.model.OperationStatus; + +import java.util.Objects; + +/** + * Represents a notification successfully processed by the {@link LifecycleChangeNotificationManager} + */ +class ProcessedNotification { + private String operationExecutionId; + //do not remove field the {@link LifecycleChangeNotificationManager} uses the equals + // method to compare notifications + private OperationStatus status; + + ProcessedNotification(String operationExecutionId, OperationStatus status) { + this.operationExecutionId = operationExecutionId; + this.status = status; + } + + /** + * @return the identifier of the operation + */ + public String getOperationExecutionId() { + return operationExecutionId; + } + + /** + * @param operationExecutionId the identifier of the operation + */ + public void setOperationExecutionId(String operationExecutionId) { + this.operationExecutionId = operationExecutionId; + } + + /** + * @return the status of the operation + */ + public OperationStatus getStatus() { + return status; + } + + /** + * @param status the status of the operation + */ + public void setStatus(OperationStatus status) { + this.status = status; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ProcessedNotification that = (ProcessedNotification) o; + return Objects.equals(operationExecutionId, that.operationExecutionId) && + status == that.status; + } + + @Override + public int hashCode() { + return Objects.hash(operationExecutionId, status); + } + + @Override + public String toString() { + return "ProcessedNotification{" + + "operationExecutionId=" + operationExecutionId + '"' + + ", status=" + status + + '}'; + } +} diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ReportedAffectedConnectionPoints.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ReportedAffectedConnectionPoints.java new file mode 100644 index 00000000..9bf629e3 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ReportedAffectedConnectionPoints.java @@ -0,0 +1,83 @@ +/* + * 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.vnfm.notification; + +import com.google.gson.annotations.SerializedName; + +import java.util.HashSet; +import java.util.Objects; +import java.util.Set; + +/** + * The connection points reported by each operation + */ +public class ReportedAffectedConnectionPoints { + @SerializedName("cbam_pre") + private Set<ReportedAffectedCp> pre = new HashSet<>(); + @SerializedName("cbam_post") + private Set<ReportedAffectedCp> post = new HashSet<>(); + + /** + * @return the connection points that were present after the operation has finished + */ + public Set<ReportedAffectedCp> getPost() { + return post; + } + + /** + * @param post the connection points that were present after the operation has finished + */ + public void setPost(Set<ReportedAffectedCp> post) { + this.post = post; + } + + /** + * @return the connection points that were present before the operation was started + */ + public Set<ReportedAffectedCp> getPre() { + return pre; + } + + /** + * @param pre the connection points that were present before the operation was started + */ + public void setPre(Set<ReportedAffectedCp> pre) { + this.pre = pre; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ReportedAffectedConnectionPoints that = (ReportedAffectedConnectionPoints) o; + return Objects.equals(pre, that.pre) && + Objects.equals(post, that.post); + } + + @Override + public int hashCode() { + + return Objects.hash(pre, post); + } + + @Override + public String toString() { + return "ReportedAffectedConnectionPoints{" + + "pre=" + pre + + ", post=" + post + + '}'; + } +}
\ No newline at end of file diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ReportedAffectedCp.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ReportedAffectedCp.java new file mode 100644 index 00000000..ab9d6314 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/ReportedAffectedCp.java @@ -0,0 +1,231 @@ +/* + * 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.vnfm.notification; + +import com.nokia.cbam.lcm.v32.model.ChangeType; + +import java.util.Objects; + +/** + * Represent a single port change in the VNF + */ +public class ReportedAffectedCp { + private String providerId; + private String cpdId; + private String ecpdId; + private String cpId; //the location of the resource in the Heat stack + private String tenantId; + private String ipAddress; + private String macAddress; + private String serverProviderId; + private String name; + private String networkProviderId; + private ChangeType changeType; + + /** + * @return the provider id of the port + */ + public String getProviderId() { + return providerId; + } + + /** + * @param providerId the provider id of the port + */ + public void setProviderId(String providerId) { + this.providerId = providerId; + } + + /** + * @return the identifier of the connection point of the port (may be null) + */ + public String getCpdId() { + return cpdId; + } + + /** + * @param cpdId the identifier of the connection point of the port (may be null) + */ + public void setCpdId(String cpdId) { + this.cpdId = cpdId; + } + + /** + * @return the identifier of the external connection point of the port (may be null) + */ + public String getEcpdId() { + return ecpdId; + } + + /** + * @param ecpdId the identifier of the connection point of the port (may be null) + */ + public void setEcpdId(String ecpdId) { + this.ecpdId = ecpdId; + } + + /** + * @return the identifier of the connection point instance of the port + */ + public String getCpId() { + return cpId; + } + + /** + * @param cpId the identifier of the connection point instance of the port + */ + public void setCpId(String cpId) { + this.cpId = cpId; + } + + /** + * @return the identifier of the tenant owning the port + */ + public String getTenantId() { + return tenantId; + } + + /** + * @param tenantId the identifier of the tenant owning the port + */ + public void setTenantId(String tenantId) { + this.tenantId = tenantId; + } + + /** + * @return the IP address of the port (may be null) + */ + public String getIpAddress() { + return ipAddress; + } + + /** + * @param ipAddress the IP address of the port (may be null) + */ + public void setIpAddress(String ipAddress) { + this.ipAddress = ipAddress; + } + + /** + * @return the MAC address of the port + */ + public String getMacAddress() { + return macAddress; + } + + /** + * @param macAddress the MAC address of the port + */ + public void setMacAddress(String macAddress) { + this.macAddress = macAddress; + } + + /** + * @return the provider id of the server to which the port is attached to (may be null) + */ + public String getServerProviderId() { + return serverProviderId; + } + + /** + * @param serverProviderId the provider id of the server to which the port is attached to (may be null) + */ + public void setServerProviderId(String serverProviderId) { + this.serverProviderId = serverProviderId; + } + + /** + * @return the name of the port (may be null) + */ + public String getName() { + return name; + } + + /** + * @param name the name of the port + */ + public void setName(String name) { + this.name = name; + } + + /** + * @return the provider id of the network of the port + */ + public String getNetworkProviderId() { + return networkProviderId; + } + + /** + * @param networkProviderId the provider id of the network of the port + */ + public void setNetworkProviderId(String networkProviderId) { + this.networkProviderId = networkProviderId; + } + + /** + * @return the state of the port in the current operation + */ + public ChangeType getChangeType() { + return changeType; + } + + /** + * @param changeType the state of the port in the current operation + */ + public void setChangeType(ChangeType changeType) { + this.changeType = changeType; + } + + @Override + public String toString() { + return "ReportedAffectedCp{" + + "providerId='" + providerId + '\'' + + ", cpdId='" + cpdId + '\'' + + ", ecpdId='" + ecpdId + '\'' + + ", cpId='" + cpId + '\'' + + ", tenantId='" + tenantId + '\'' + + ", ipAddress='" + ipAddress + '\'' + + ", macAddress='" + macAddress + '\'' + + ", serverProviderId='" + serverProviderId + '\'' + + ", name='" + name + '\'' + + ", networkProviderId='" + networkProviderId + '\'' + + ", changeType=" + changeType + + '}'; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + ReportedAffectedCp that = (ReportedAffectedCp) o; + return Objects.equals(providerId, that.providerId) && + Objects.equals(cpdId, that.cpdId) && + Objects.equals(ecpdId, that.ecpdId) && + Objects.equals(cpId, that.cpId) && + Objects.equals(tenantId, that.tenantId) && + Objects.equals(ipAddress, that.ipAddress) && + Objects.equals(macAddress, that.macAddress) && + Objects.equals(serverProviderId, that.serverProviderId) && + Objects.equals(name, that.name) && + Objects.equals(networkProviderId, that.networkProviderId) && + changeType == that.changeType; + } + + @Override + public int hashCode() { + return Objects.hash(providerId, cpdId, ecpdId, cpId, tenantId, ipAddress, macAddress, serverProviderId, name, networkProviderId, changeType); + } +}
\ No newline at end of file diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/package-info.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/package-info.java new file mode 100644 index 00000000..eb4ca242 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/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 the interactions with the VNFM. + */ +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm; diff --git a/nokiav2/driver/src/main/resources/MainServiceTemplate.meta b/nokiav2/driver/src/main/resources/MainServiceTemplate.meta new file mode 100644 index 00000000..01f85b17 --- /dev/null +++ b/nokiav2/driver/src/main/resources/MainServiceTemplate.meta @@ -0,0 +1,7 @@ +metadata: + vnf_product_name: VNF_PRODUCT_NAME + vnf_provider_id: Nokia + vnf_package_version: VNF_PACKAGE_VERSION + vnf_release_data_time: 2017.01.01T10:00+03:00 + +source: MainServiceTemplate.yaml
\ No newline at end of file diff --git a/nokiav2/driver/src/main/resources/TOSCA.meta b/nokiav2/driver/src/main/resources/TOSCA.meta new file mode 100644 index 00000000..5cb64478 --- /dev/null +++ b/nokiav2/driver/src/main/resources/TOSCA.meta @@ -0,0 +1,4 @@ +TOSCA-Meta-Version: 1.0 +CSAR-Version: 1.0 +Created-By: Kuku +Entry-Definitions: Definitions/MainServiceTemplate.yaml diff --git a/nokiav2/driver/src/main/resources/cbam.collectConnectionPoints.js b/nokiav2/driver/src/main/resources/cbam.collectConnectionPoints.js new file mode 100644 index 00000000..f5cfc675 --- /dev/null +++ b/nokiav2/driver/src/main/resources/cbam.collectConnectionPoints.js @@ -0,0 +1,71 @@ +var collectConnectionPoints = function(resourceModel, diff) { + return collectPorts(resourceModel, diff) +}; + +function collectPorts(resourceModel, diff){ + pathToResource = {} + collectResources('', resourceModel, pathToResource, true); + transformedPorts = [] + Object.keys(pathToResource).forEach(function (path) { + var port = pathToResource[path]; + transformedPort = {} + transformedPort.name = port.attributes.name; + transformedPort.providerId = port.attributes.id; + transformedPort.cpId = path; + var managedPort = false; + if(port.hasOwnProperty('externalConnectionPoint')){ + transformedPort.ecpdId = port.externalConnectionPoint; + managedPort = true; + } + if(port.hasOwnProperty('connectionPoint')){ + transformedPort.cpdId = port.connectionPoint; + managedPort = true; + } + transformedPort.tenantId = port.attributes.tenant_id; + transformedPort.ipAddress = port.attributes.fixed_ips[0].ip_address; + transformedPort.macAddress = port.attributes.mac_address; + transformedPort.serverProviderId = port.attributes.device_id; + transformedPort.networkProviderId = port.attributes.network_id; + transformedPort.changeType = 'untouched'; + var added = contains(diff.add, path); + var removed = contains(diff.remove, path); + if(added && removed){ + transformedPort.changeType = "MODIFIED"; + } + else{ + if(removed){ + transformedPort.changeType = "REMOVED"; + } + if(added){ + transformedPort.changeType = "ADDED"; + } + } + if('untouched' != transformedPort.changeType && managedPort){ + transformedPorts.push(transformedPort) + } + }) + return transformedPorts; +}; + +function contains(resourceChanges, path){ + var keys = Object.keys(resourceChanges); + return keys.indexOf(path) !== -1; +} + +function collectResources(path, root, pathToResouceMap, onResources){ + root && Object.keys(root).forEach(function(item) { + if(item == 'resource_type' && root[item] == 'OS::Neutron::Port'){ + pathToResouceMap[path] = root + } + else if(typeof root[item] === "object"){ + var newItem = onResources ? "" : item; + var newPath = path; + if('' != newItem && path != ''){ + newPath += "."; + } + newPath += newItem; + collectResources(newPath, root[item], pathToResouceMap, !onResources) + } + }); +}; + diff --git a/nokiav2/driver/src/main/resources/cbam.post.collectConnectionPoints.js b/nokiav2/driver/src/main/resources/cbam.post.collectConnectionPoints.js new file mode 100644 index 00000000..c70d36ed --- /dev/null +++ b/nokiav2/driver/src/main/resources/cbam.post.collectConnectionPoints.js @@ -0,0 +1,4 @@ +return { + "cbam_post" : collectConnectionPoints($.resource_model, $.model_diff), + "cbam_pre" : $.operation_result.cbam_pre + } diff --git a/nokiav2/driver/src/main/resources/cbam.pre.collectConnectionPoints.js b/nokiav2/driver/src/main/resources/cbam.pre.collectConnectionPoints.js new file mode 100644 index 00000000..64153a20 --- /dev/null +++ b/nokiav2/driver/src/main/resources/cbam.pre.collectConnectionPoints.js @@ -0,0 +1 @@ +return { "cbam_pre" : collectConnectionPoints($.resource_model, $.model_diff) } diff --git a/nokiav2/driver/src/main/resources/self.swagger.json b/nokiav2/driver/src/main/resources/self.swagger.json new file mode 100644 index 00000000..f8d24a0b --- /dev/null +++ b/nokiav2/driver/src/main/resources/self.swagger.json @@ -0,0 +1,798 @@ +{ + "basePath": "/api/NokiaSVNFM/v1", + "consumes": [ + "application/json" + ], + "produces": [ + "application/json" + ], + "schemes": [ + "http" + ], + "swagger": "2.0", + "info": { + "contact": { + "email": "onap-discuss@lists.onap.org", + "name": "Nokia team", + "url": "https://gerrit.onap.org/r/#/admin/projects/vfc/nfvo/lcm" + }, + "description": "ONAP Nokia CBAM Driver API.", + "title": "ONAP Nokia CBAM Driver API", + "version": "1.0.0" + }, + "definitions": { + "JobDetailInfo": { + "properties": { + "jobId": { + "type": "string" + }, + "responseDescriptor": { + "properties": { + "errorCode": { + "type": "string" + }, + "progress": { + "description": "The progress of the job. Value between 0 and 100.", + "type": "string" + }, + "responseHistoryList": { + "items": { + "$ref": "#/definitions/jobResponseInfo" + }, + "type": "array" + }, + "responseId": { + "type": "string" + }, + "status": { + "$ref": "#/definitions/JobStatus", + "description": "The status of the job" + }, + "statusDescription": { + "description": "The reason of the current status of the job.", + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "JobInfo": { + "properties": { + "jobId": { + "type": "string" + } + }, + "type": "object" + }, + "JobStatus": { + "description": "The status of the job", + "enum": [ + "started", + "processing", + "finished", + "error", + "timeout" + ], + "type": "string" + }, + "ScaleDirection": { + "description": "The direction of the scaling", + "enum": [ + "SCALE_IN", + "SCALE_OUT" + ], + "type": "string" + }, + "VimInfo": { + "properties": { + "createTime": { + "description": "vim info createTime", + "type": "string" + }, + "description": { + "description": "vim description", + "type": "string" + }, + "name": { + "description": "vim name", + "type": "string" + }, + "password": { + "description": "vim login password", + "type": "string" + }, + "sslCacert": { + "description": "The collection of trusted certificates towards the VIM connection.", + "type": "string" + }, + "sslInsecure": { + "description": "Whether to verify VIM's certificate", + "type": "string" + }, + "status": { + "description": "The status of external system", + "type": "string" + }, + "type": { + "description": "vim type", + "type": "string" + }, + "url": { + "description": "vim url", + "type": "string" + }, + "userName": { + "description": "vim login username", + "type": "string" + }, + "vendor": { + "description": "vendor name", + "type": "string" + }, + "version": { + "description": "vim version", + "type": "string" + }, + "vimId": { + "description": "vim Id", + "type": "string" + } + }, + "type": "object" + }, + "VnfHealRequest": { + "properties": { + "action": { + "type": "string" + }, + "affectedvm": { + "properties": { + "vduid": { + "type": "string" + }, + "vimid": { + "type": "string" + }, + "vmname": { + "type": "string" + } + }, + "type": "object" + } + }, + "type": "object" + }, + "VnfInfo": { + "properties": { + "version": { + "type": "string" + }, + "vnfInstanceDescription": { + "type": "string" + }, + "vnfId": { + "type": "string" + }, + "vnfInstanceName": { + "type": "string" + }, + "vnfPackageId": { + "type": "string" + }, + "vnfProvider": { + "type": "string" + }, + "vnfStatus": { + "type": "string" + }, + "vnfType": { + "type": "string" + }, + "vnfdId": { + "type": "string" + } + }, + "type": "object" + }, + "VnfInstInfo": { + "properties": { + "vnfId": { + "description": "VNF instance ID", + "type": "string" + }, + "vnfInstanceName": { + "description": "VNF instance name", + "type": "string" + } + }, + "type": "object" + }, + "VnfInstListInfo": { + "items": { + "$ref": "#/definitions/VnfInstInfo" + }, + "type": "array" + }, + "VnfInstantiateRequest": { + "properties": { + "additionalParam": { + "type": "object" + }, + "extVirtualLink": { + "items": { + "$ref": "#/definitions/extVirtualLinkInfo" + }, + "type": "array" + }, + "vnfDescriptorId": { + "type": "string" + }, + "vnfInstanceDescription": { + "type": "string" + }, + "vnfInstanceName": { + "type": "string" + }, + "vnfPackageId": { + "type": "string" + } + }, + "type": "object" + }, + "VnfInstantiateResponse": { + "properties": { + "jobId": { + "type": "string" + }, + "vnfId": { + "type": "string" + } + }, + "type": "object" + }, + "VnfScaleRequest": { + "properties": { + "additionalParam": { + "description": "Additional parameters passed by the NFVO as input to the scaling process, specific to the VNF being scaled", + "type": "object" + }, + "aspectId": { + "description": "Identifies the aspect of the VNF that is requested to be scaled", + "type": "string" + }, + "numberOfSteps": { + "description": "Number of scaling steps to be executed as part of this ScaleVnf operation. It shall be a positive number", + "type": "string" + }, + "type": { + "$ref": "#/definitions/ScaleDirection", + "description": "The direction of the scaling." + } + }, + "type": "object" + }, + "VnfTerminateRequest": { + "properties": { + "gracefulTerminationTimeout": { + "description": "The time interval(second) to wait for the VNF to be taken out of service during graceful termination.", + "type": "string" + }, + "terminationType": { + "$ref": "#/definitions/VnfTerminationType", + "description": "The type of the termination" + } + }, + "type": "object" + }, + "VnfTerminationType": { + "description": "The type of the termination.", + "enum": [ + "graceful", + "forceful" + ], + "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" + } + } + } + } + }, + "jobResponseInfo": { + "properties": { + "errorCode": { + "type": "string" + }, + "progress": { + "type": "string" + }, + "responseId": { + "type": "string" + }, + "status": { + "type": "string" + }, + "statusDescription": { + "type": "string" + } + }, + "type": "object" + }, + "vimInfo": { + "properties": { + "accessInfo": { + "properties": { + "password": { + "description": "Password of login user", + "type": "string" + }, + "tenant": { + "description": "Tenant Name of tenant", + "type": "string" + }, + "username": { + "description": "Username for login", + "type": "string" + } + }, + "type": "object" + }, + "interfaceEndpoint": { + "description": "Information about the interface endpoint. It is a URL", + "type": "string" + }, + "interfaceInfo": { + "properties": { + "apiVersion": { + "description": "The api Version Type value will be ", + "type": "string" + }, + "protocolType": { + "description": "The protocol Type value will be http or https", + "type": "string" + }, + "vimType": { + "description": "The vim Type value wil be openstack", + "type": "string" + } + }, + "type": "object" + }, + "vimId": { + "type": "string" + }, + "vimInfoId": { + "type": "string" + } + }, + "type": "object" + }, + "VnfLifecycleChangeNotification": { + "type": "object", + "description": "The lifecycle change notifications send from CBAM" + } + }, + "paths": { + "/{vnfmId}/vnfs": { + "post": { + "consumes": [ + "application/json" + ], + "description": "VNF create&instantiate Rest API should be provided by the VNFM Driver", + "operationId": "vnf_instantiate", + "parameters": [ + { + "description": "The value of vnfmid should be the VNFM Instantiate ID", + "in": "path", + "name": "vnfmId", + "required": true, + "type": "string" + }, + { + "description": "instantiate request param", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/VnfInstantiateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "", + "schema": { + "$ref": "#/definitions/VnfInstantiateResponse" + } + } + }, + "summary": "vnf create&instantiate", + "tags": [ + "VNFMDriver" + ] + } + }, + "/{vnfmId}/vnfs/{vnfId}": { + "get": { + "consumes": [ + "application/json" + ], + "description": "", + "operationId": "query_vnf", + "parameters": [ + { + "description": "The value of vnfmId should be the VNFM Instantiate ID", + "in": "path", + "name": "vnfmId", + "required": true, + "type": "string" + }, + { + "description": "The value of vnfId should be the VNF Instantiate ID", + "in": "path", + "name": "vnfId", + "required": true, + "type": "string" + } + ], + "produces": [ + "application/json" + ], + "responses": { + "200": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/VnfInfo" + } + }, + "404": { + "description": "the vnf instance id is wrong" + }, + "500": { + "description": "the url is invalid" + } + }, + "summary": "query the specified vnf info", + "tags": [ + "VNFMDriver" + ] + } + }, + "/{vnfmId}/vnfs/{vnfId}/heal": { + "post": { + "consumes": [ + "application/json" + ], + "description": "VNF Heal Rest API should be provided by the VNFM Driver", + "operationId": "vnf_heal", + "parameters": [ + { + "description": "The value of vnfmId should be the VNFM Instantiate ID", + "in": "path", + "name": "vnfmId", + "required": true, + "type": "string" + }, + { + "description": "The value of vnfId should be the VNF Instantiate ID", + "in": "path", + "name": "vnfId", + "required": true, + "type": "string" + }, + { + "description": "instantiate request param", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/VnfHealRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "", + "schema": { + "$ref": "#/definitions/JobInfo" + } + }, + "404": { + "description": "the VNF instance id is wrong" + }, + "500": { + "description": "the url is invalid" + } + }, + "summary": "vnf heal", + "tags": [ + "VNFMDriver" + ] + } + }, + "/{vnfmId}/vnfs/{vnfId}/scale": { + "post": { + "consumes": [ + "application/json" + ], + "description": "VNF Scale Rest API should be provided by the VNFM Driver", + "operationId": "vnf_scale", + "parameters": [ + { + "description": "The value of vnfmId should be the VNFM Instantiate ID", + "in": "path", + "name": "vnfmId", + "required": true, + "type": "string" + }, + { + "description": "The value of vnfId should be the VNF Instantiate ID", + "in": "path", + "name": "vnfId", + "required": true, + "type": "string" + }, + { + "description": "instantiate request param", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/VnfScaleRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "201": { + "description": "", + "schema": { + "$ref": "#/definitions/JobInfo" + } + }, + "404": { + "description": "the VNF instance id is wrong" + }, + "500": { + "description": "the url is invalid" + } + }, + "summary": "vnf Scale", + "tags": [ + "VNFMDriver" + ] + } + }, + "/{vnfmId}/vnfs/{vnfId}/terminate": { + "post": { + "consumes": [ + "application/json" + ], + "description": "VNF terminate&delete Rest API should be provided by the VNFM Driver", + "operationId": "terminate_vnf", + "parameters": [ + { + "description": "The value of vnfmId should be the VNFM Instantiate ID", + "in": "path", + "name": "vnfmId", + "required": true, + "type": "string" + }, + { + "description": "The value of vnfId should be the VNF Instantiate ID", + "in": "path", + "name": "vnfId", + "required": true, + "type": "string" + }, + { + "description": "instantiate request param", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/VnfTerminateRequest" + } + } + ], + "produces": [ + "application/json" + ], + "responses": { + "204": { + "description": "successful operation", + "schema": { + "$ref": "#/definitions/JobInfo" + } + }, + "404": { + "description": "the VNF instance id is wrong" + }, + "500": { + "description": "the url is invalid" + } + }, + "summary": "terminate&delete vnf", + "tags": [ + "VNFMDriver" + ] + } + }, + "/{vnfmId}/jobs/{jobId}": { + "get": { + "tags": [ + "VNFMDriver" + ], + "summary": "jobstatus", + "description": "Job Infomation API should be provided by VNFM Driver", + "operationId": "get_jobstatus", + "parameters": [ + { + "required": true, + "type": "string", + "description": "job Id", + "name": "jobId", + "in": "path" + }, + { + "required": true, + "type": "string", + "description": "The value of vnfmId should be the VNFM Instantiate ID", + "name": "vnfmId", + "in": "path" + }, + { + "required": true, + "type": "string", + "description": "job response message id", + "name": "responseId", + "in": "query" + } + ], + "responses": { + "202": { + "description": "", + "schema": { + "$ref": "#/definitions/JobDetailInfo" + } + } + } + } + }, + "/lcn":{ + "get": { + "tags": [ + "SBI" + ], + "summary": "Test LCN connectivity from CBAM to driver", + "description": "Test LCN connectivity from CBAM to driver", + "responses": { + "204": { + "description": "Used for connectivity test" + } + } + }, + "post": { + "tags": [ + "SBI" + ], + "consumes": [ + "application/json" + ], + "summary": "Send LCN from CBAM", + "description": "Test LCN connectivity from CBAM to driver", + "parameters": [ + { + "description": "The life cycle change notification", + "in": "body", + "name": "body", + "required": true, + "schema": { + "$ref": "#/definitions/VnfLifecycleChangeNotification" + } + } + ], + "responses": { + "204": { + "description": "Used for connectivity test" + } + } + } + }, + "/swagger.json": { + "get": { + "tags": [ + "Utilities" + ], + "summary": "The Nokia SVNFM API definition", + "description": "The Nokia SVNFM API definition", + "responses": { + "202": { + "description": "The swagger API definition" + } + } + } + }, + "/convert": { + "post": { + "tags": [ + "Utilities" + ], + "consumes":[ + "multipart/form-data" + ], + "produces":[ + "application/octet-stream" + ], + "parameters" : [ + { + "description": "The CBAM VNF package", + "in": "formData", + "name": "upfile", + "type": "file" + } + ], + "summary": "Converts the Nokia CBAM package to ONAP package", + "description": "Converts the Nokia CBAM package to ONAP package", + "responses": { + "200": { + "description": "The converted package", + "schema":{ + "type": "file" + } + } + } + }, + "get": { + "tags": [ + "Utilities" + ], + "produces":[ + "text/html" + ], + "summary": "UI to convert the Nokia CBAM package to ONAP package", + "description": "UI to convert the Nokia CBAM package to ONAP package", + "responses": { + "200": { + "description": "The converted package" + } + } + } + + } + } +} diff --git a/nokiav2/driver/src/main/resources/upload.html b/nokiav2/driver/src/main/resources/upload.html new file mode 100644 index 00000000..a5c686f4 --- /dev/null +++ b/nokiav2/driver/src/main/resources/upload.html @@ -0,0 +1,12 @@ +<!DOCTYPE html> +<html> +<body> + +<form action="/api/NokiaSVNFM/v1/convert" method="post" enctype="multipart/form-data"> + Select CBAM package to upload: + <input type="file" name="fileToUpload" id="fileToUpload"> + <input type="submit" value="Upload" name="submit"> +</form> + +</body> +</html>
\ No newline at end of file diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/FullUnitTestSuite.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/FullUnitTestSuite.java new file mode 100644 index 00000000..f5f60fb1 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/FullUnitTestSuite.java @@ -0,0 +1,99 @@ +/* + * 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; + +import org.junit.runner.RunWith; +import org.junit.runners.Suite; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.TestCbamRestApiProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.TestGenericExternalSystemInfoProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.TestIpMappingProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.TestMsbApiProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.vfc.*; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.TestCbamVnfPackageBuilder; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.TestCbamVnfdBuilder; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.TestOnapVnfPackageBuilder; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.TestOnapVnfdBuilder; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.restapi.*; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.TestConditions; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.TestRealConfig; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.TestServletInitializer; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestCbamUtils; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestStoreLoader; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestSystemFunctions; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.*; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.TestLifecycleChangeNotificationManager; + +@RunWith(Suite.class) +@Suite.SuiteClasses({ + + TestCbamRestApiProvider.class, + TestGenericExternalSystemInfoProvider.class, + TestIpMappingProvider.class, + TestMsbApiProvider.class, + + TestVfcExternalSystemInfoProvider.class, + TestVfcGrantManager.class, + TestVfcPackageProvider.class, + TestVfcRestApiProvider.class, + TestVfcNotificationSender.class, + + TestCbamVnfdBuilder.class, + TestOnapVnfdBuilder.class, + TestCbamVnfPackageBuilder.class, + TestOnapVnfPackageBuilder.class, + + TestConverterApi.class, + TestLcmApi.class, + TestLcnApi.class, + TestSwaggerApi.class, + TestSwaggerDefinitionConsistency.class, + + TestConditions.class, + TestServletInitializer.class, + TestRealConfig.class, + + TestCbamUtils.class, + TestStoreLoader.class, + TestSystemFunctions.class, + + TestAdditionalParams.class, + TestCbamCatalogManager.class, + TestCbamTokenProvider.class, + TestDriverProperties.class, + TestJobManager.class, + TestVfcGrantManager.class, + TestLifecycleChangeNotificationManager.class, + TestLifecycleManager.class, + TestSelfRegistrationManager.class, + + TestNokiaSvnfmApplication.class, + +}) +public class FullUnitTestSuite { +} + + + + + + + + + + + + + diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/TestNokiaSvnfmApplication.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/TestNokiaSvnfmApplication.java new file mode 100644 index 00000000..47e441ff --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/TestNokiaSvnfmApplication.java @@ -0,0 +1,151 @@ +/* + * 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; + +import junit.framework.TestCase; +import org.apache.log4j.Logger; +import org.junit.Before; +import org.junit.Test; +import org.mockito.*; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.JobManager; +import org.springframework.boot.context.event.ApplicationReadyEvent; +import org.springframework.context.event.ContextClosedEvent; +import org.springframework.test.util.ReflectionTestUtils; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; +import static org.mockito.Mockito.verify; + + +public class TestNokiaSvnfmApplication { + @Mock + private SelfRegistrationManager selfRegistrationManager; + @Mock + private JobManager jobManager; + @Mock + private Logger logger; + @InjectMocks + private NokiaSvnfmApplication.SelfRegistrationTrigger selfRegistrationTriggerer; + @InjectMocks + private NokiaSvnfmApplication.SelfDeRegistrationTrigger selfUnregistrationTriggerer; + + + @Before + public void initMocks() throws Exception { + MockitoAnnotations.initMocks(this); + ReflectionTestUtils.setField(NokiaSvnfmApplication.class, "logger", logger); + } + + /** + * Assert that the entry point of the application does not change + */ + @Test + public void doNotRename() { + //verify + //1. if the entry point is renamed the main class of spring boot in the driverwar must also be changed + //2. all classes that use @Autowrire must be in a subpackage relative to this class + assertEquals("org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.NokiaSvnfmApplication", NokiaSvnfmApplication.class.getCanonicalName()); + } + + /** + * Assert that the self registration process is started after the servlet is up and is able to answer REST requests. + */ + @Test + public void testRegistrationIsCalledAfterComponentIsUp() throws Exception { + //given + ApplicationReadyEvent event = Mockito.mock(ApplicationReadyEvent.class); + //when + selfRegistrationTriggerer.onApplicationEvent(event); + //verify + verify(selfRegistrationManager).register(); + verify(logger).info("Self registration started"); + verify(logger).info("Self registration finished"); + // this forces the event to be fired after the servlet is up (prevents refactor) + assertTrue(ApplicationReadyEvent.class.isAssignableFrom(event.getClass())); + } + + /** + * Assert that the self de-registration process is started after the servlet has been ramped down + */ + @Test + public void testUnRegistrationIsCalledAfterComponentIsUp() throws Exception { + //given + ContextClosedEvent event = Mockito.mock(ContextClosedEvent.class); + //when + selfUnregistrationTriggerer.onApplicationEvent(event); + //verify + InOrder inOrder = Mockito.inOrder(jobManager, selfRegistrationManager); + inOrder.verify(jobManager).prepareForShutdown(); + inOrder.verify(selfRegistrationManager).deRegister(); + verify(logger).info("Self de-registration started"); + verify(logger).info("Self de-registration finished"); + // this forces the event to be fired after the servlet is down (prevents refactor) + assertTrue(ContextClosedEvent.class.isAssignableFrom(event.getClass())); + } + + /** + * Failures in registration is logged and propagated + */ + @Test + public void failedRegistration() { + //given + RuntimeException expectedException = new RuntimeException(); + Mockito.doThrow(expectedException).when(selfRegistrationManager).register(); + ApplicationReadyEvent event = Mockito.mock(ApplicationReadyEvent.class); + //when + try { + selfRegistrationTriggerer.onApplicationEvent(event); + //verify + TestCase.fail(); + } catch (RuntimeException e) { + assertEquals(e, expectedException); + } + verify(logger).error("Self registration failed", expectedException); + } + + /** + * Failures in de-registration is logged and propagated + */ + @Test + public void failedDeRegistration() { + //given + RuntimeException expectedException = new RuntimeException(); + Mockito.doThrow(expectedException).when(selfRegistrationManager).deRegister(); + ContextClosedEvent event = Mockito.mock(ContextClosedEvent.class); + //when + try { + selfUnregistrationTriggerer.onApplicationEvent(event); + //verify + TestCase.fail(); + } catch (RuntimeException e) { + assertEquals(e, expectedException); + } + verify(logger).error("Self de-registration failed", expectedException); + } + + /** + * static entry point calling an other static entry point can not be tested + */ + @Test + public void useless() throws Exception { + try { + NokiaSvnfmApplication.main(null); + } catch (Exception e) { + + } + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/ct/CTReal.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/ct/CTReal.java new file mode 100644 index 00000000..e013142a --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/ct/CTReal.java @@ -0,0 +1,42 @@ +/* + * 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.ct; + +import org.junit.Test; +import org.junit.runner.RunWith; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.NokiaSvnfmApplication; +import org.springframework.boot.test.context.SpringBootTest; +import org.springframework.test.context.ActiveProfiles; +import org.springframework.test.context.junit4.SpringRunner; + +@RunWith(value = SpringRunner.class) +@SpringBootTest(classes = NokiaSvnfmApplication.class, webEnvironment = SpringBootTest.WebEnvironment.DEFINED_PORT) +@ActiveProfiles("real") +public class CTReal { + + /** + * The following is not a real test, but only start the driver locally. + * It takes parameters from application-real.properties + */ + @Test + public void testBasicWorkflow() throws Exception { + + + Thread.sleep(10000000 * 1000L); + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestCbamRestApiProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestCbamRestApiProvider.java new file mode 100644 index 00000000..45a3216a --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestCbamRestApiProvider.java @@ -0,0 +1,236 @@ +/* + * 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.core; + +import com.nokia.cbam.catalog.v1.api.DefaultApi; +import com.nokia.cbam.lcm.v32.ApiClient; +import com.nokia.cbam.lcm.v32.api.OperationExecutionsApi; +import com.nokia.cbam.lcm.v32.api.VnfsApi; +import com.nokia.cbam.lcn.v32.api.SubscriptionsApi; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.onap.msb.sdk.discovery.entity.MicroServiceFullInfo; +import org.onap.msb.sdk.discovery.entity.NodeInfo; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VnfmInfoProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamTokenProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.onap.vnfmdriver.model.VnfmInfo; +import org.springframework.core.env.Environment; + +import java.util.Base64; +import java.util.HashSet; +import java.util.Set; + +import static junit.framework.TestCase.*; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.springframework.test.util.ReflectionTestUtils.setField; + +public class TestCbamRestApiProvider extends TestBase { + @Mock + private Environment environment; + @Mock + private CbamTokenProvider cbamTokenProvider; + private MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo(); + private Set<NodeInfo> nodes = new HashSet<>(); + + private CbamRestApiProvider cbamRestApiProvider; + + @Before + public void init() { + microServiceInfo.setNodes(nodes); + CbamRestApiProvider real = new CbamRestApiProvider(driverProperties, cbamTokenProvider, vnfmInfoProvider); + setField(real, "trustedCertificates", "mytrustedCertificates"); + setField(real, "skipCertificateVerification", true); + cbamRestApiProvider = spy(real); + when(environment.getProperty(IpMappingProvider.IP_MAP, String.class, "")).thenReturn(""); + when(environment.getProperty(VnfmInfoProvider.VNFM_INFO_CACHE_EVICTION_IN_MS, Long.class, Long.valueOf(10 * 60 * 1000))).thenReturn(10 * 60 * 1000L); + } + + /** + * test CBAM LCM API retrieval without SSL verification + */ + @Test + public void testCbamLcmApi() throws Exception { + VnfmInfo expectedVnfmInfo = new VnfmInfo(); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + expectedVnfmInfo.setUrl("https://cbamUrl:123/d"); + when(cbamTokenProvider.getToken(VNFM_ID)).thenReturn("myToken"); + //when + VnfsApi cbamLcmApi = cbamRestApiProvider.getCbamLcmApi(VNFM_ID); + //verify + ApiClient apiClient = cbamLcmApi.getApiClient(); + assertEquals("https://cbamUrl:123/d", apiClient.getBasePath()); + assertNull(apiClient.getSslCaCert()); + assertEquals("myToken", ((com.nokia.cbam.lcm.v32.auth.OAuth) apiClient.getAuthentication("OauthClient")).getAccessToken()); + assertEquals(2, cbamLcmApi.getApiClient().getAuthentications().size()); + assertTrue(!cbamLcmApi.getApiClient().isVerifyingSsl()); + } + + /** + * test CBAM LCM API retrieval with SSL verification + */ + @Test + public void testCbamLcmApiWithSslVerfy() throws Exception { + VnfmInfo expectedVnfmInfo = new VnfmInfo(); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + expectedVnfmInfo.setUrl("https://cbamUrl:123/d"); + when(cbamTokenProvider.getToken(VNFM_ID)).thenReturn("myToken"); + setField(cbamRestApiProvider, "skipCertificateVerification", false); + setField(cbamRestApiProvider, "trustedCertificates", Base64.getEncoder().encodeToString(TestUtil.loadFile("unittests/sample.cert.pem"))); + //when + VnfsApi cbamLcmApi = cbamRestApiProvider.getCbamLcmApi(VNFM_ID); + //verify + ApiClient apiClient = cbamLcmApi.getApiClient(); + assertEquals("https://cbamUrl:123/d", apiClient.getBasePath()); + assertNotNull(apiClient.getSslCaCert()); + assertEquals("myToken", ((com.nokia.cbam.lcm.v32.auth.OAuth) apiClient.getAuthentication("OauthClient")).getAccessToken()); + assertEquals(2, cbamLcmApi.getApiClient().getAuthentications().size()); + assertTrue(cbamLcmApi.getApiClient().isVerifyingSsl()); + } + + /** + * test CBAM Catalog API retrieval without SSL verification + */ + @Test + public void testCbamCatalogApi() throws Exception { + VnfmInfo expectedVnfmInfo = new VnfmInfo(); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + when(cbamTokenProvider.getToken(VNFM_ID)).thenReturn("myToken"); + when(driverProperties.getCbamCatalogUrl()).thenReturn("https://1.2.3.4/path"); + //when + DefaultApi cbamCatalogApi = cbamRestApiProvider.getCbamCatalogApi(VNFM_ID); + //verify + com.nokia.cbam.catalog.v1.ApiClient apiClient = cbamCatalogApi.getApiClient(); + assertEquals("https://1.2.3.4/path", apiClient.getBasePath()); + assertNull(apiClient.getSslCaCert()); + assertEquals("myToken", ((com.nokia.cbam.catalog.v1.auth.OAuth) apiClient.getAuthentication("OauthClient")).getAccessToken()); + assertEquals(2, cbamCatalogApi.getApiClient().getAuthentications().size()); + assertTrue(!cbamCatalogApi.getApiClient().isVerifyingSsl()); + } + + /** + * test CBAM Catalog API retrieval with SSL verification + */ + @Test + public void testCbamCatalogApiWithSslVerfy() throws Exception { + VnfmInfo expectedVnfmInfo = new VnfmInfo(); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + when(cbamTokenProvider.getToken(VNFM_ID)).thenReturn("myToken"); + when(driverProperties.getCbamCatalogUrl()).thenReturn("https://1.2.3.4/path"); + setField(cbamRestApiProvider, "skipCertificateVerification", false); + setField(cbamRestApiProvider, "trustedCertificates", Base64.getEncoder().encodeToString(TestUtil.loadFile("unittests/sample.cert.pem"))); + //when + DefaultApi cbamLcmApi = cbamRestApiProvider.getCbamCatalogApi(VNFM_ID); + //verify + com.nokia.cbam.catalog.v1.ApiClient apiClient = cbamLcmApi.getApiClient(); + assertEquals("https://1.2.3.4/path", apiClient.getBasePath()); + assertNotNull(apiClient.getSslCaCert()); + assertEquals("myToken", ((com.nokia.cbam.catalog.v1.auth.OAuth) apiClient.getAuthentication("OauthClient")).getAccessToken()); + assertEquals(2, cbamLcmApi.getApiClient().getAuthentications().size()); + assertTrue(cbamLcmApi.getApiClient().isVerifyingSsl()); + } + + /** + * test CBAM Lcn API retrieval without SSL verification + */ + @Test + public void testCbamLcnApi() throws Exception { + VnfmInfo expectedVnfmInfo = new VnfmInfo(); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + when(cbamTokenProvider.getToken(VNFM_ID)).thenReturn("myToken"); + when(driverProperties.getCbamLcnUrl()).thenReturn("https://1.2.3.4/path"); + //when + SubscriptionsApi cbamLcnApi = cbamRestApiProvider.getCbamLcnApi(VNFM_ID); + //verify + com.nokia.cbam.lcn.v32.ApiClient apiClient = cbamLcnApi.getApiClient(); + assertEquals("https://1.2.3.4/path", apiClient.getBasePath()); + assertNull(apiClient.getSslCaCert()); + assertEquals("myToken", ((com.nokia.cbam.lcn.v32.auth.OAuth) apiClient.getAuthentication("OauthClient")).getAccessToken()); + assertEquals(2, cbamLcnApi.getApiClient().getAuthentications().size()); + assertTrue(!cbamLcnApi.getApiClient().isVerifyingSsl()); + } + + /** + * test CBAM Lcn API retrieval with SSL verification + */ + @Test + public void testCbamLcnApiWithSslVerfy() throws Exception { + VnfmInfo expectedVnfmInfo = new VnfmInfo(); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + when(cbamTokenProvider.getToken(VNFM_ID)).thenReturn("myToken"); + when(driverProperties.getCbamLcnUrl()).thenReturn("https://1.2.3.4/path"); + setField(cbamRestApiProvider, "skipCertificateVerification", false); + setField(cbamRestApiProvider, "trustedCertificates", Base64.getEncoder().encodeToString(TestUtil.loadFile("unittests/sample.cert.pem"))); + //when + SubscriptionsApi cbamLcnApi = cbamRestApiProvider.getCbamLcnApi(VNFM_ID); + //verify + com.nokia.cbam.lcn.v32.ApiClient apiClient = cbamLcnApi.getApiClient(); + assertEquals("https://1.2.3.4/path", apiClient.getBasePath()); + assertNotNull(apiClient.getSslCaCert()); + assertEquals("myToken", ((com.nokia.cbam.lcn.v32.auth.OAuth) apiClient.getAuthentication("OauthClient")).getAccessToken()); + assertEquals(2, cbamLcnApi.getApiClient().getAuthentications().size()); + assertTrue(cbamLcnApi.getApiClient().isVerifyingSsl()); + } + + /** + * test CBAM operation exeution API retrieval without SSL verification + */ + @Test + public void testCbamOpexApi() throws Exception { + VnfmInfo expectedVnfmInfo = new VnfmInfo(); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + when(cbamTokenProvider.getToken(VNFM_ID)).thenReturn("myToken"); + when(nsLcmApi.queryVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + expectedVnfmInfo.setUrl("https://cbamUrl:123/d"); + //when + OperationExecutionsApi cbamLcnApi = cbamRestApiProvider.getCbamOperationExecutionApi(VNFM_ID); + //verify + ApiClient apiClient = cbamLcnApi.getApiClient(); + assertEquals("https://cbamUrl:123/d", apiClient.getBasePath()); + assertNull(apiClient.getSslCaCert()); + assertEquals("myToken", ((com.nokia.cbam.lcm.v32.auth.OAuth) apiClient.getAuthentication("OauthClient")).getAccessToken()); + assertEquals(2, cbamLcnApi.getApiClient().getAuthentications().size()); + assertTrue(!cbamLcnApi.getApiClient().isVerifyingSsl()); + } + + /** + * test CBAM operation execution API retrieval with SSL verification + */ + @Test + public void testCbamOpexApiWithSslVerfy() throws Exception { + when(cbamTokenProvider.getToken(VNFM_ID)).thenReturn("myToken"); + setField(cbamRestApiProvider, "skipCertificateVerification", false); + setField(cbamRestApiProvider, "trustedCertificates", Base64.getEncoder().encodeToString(TestUtil.loadFile("unittests/sample.cert.pem"))); + VnfmInfo expectedVnfmInfo = new VnfmInfo(); + when(nsLcmApi.queryVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + expectedVnfmInfo.setUrl("https://cbamUrl:123/d"); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(expectedVnfmInfo); + //when + OperationExecutionsApi cbamLcnApi = cbamRestApiProvider.getCbamOperationExecutionApi(VNFM_ID); + //verify + ApiClient apiClient = cbamLcnApi.getApiClient(); + assertEquals("https://cbamUrl:123/d", apiClient.getBasePath()); + assertNotNull(apiClient.getSslCaCert()); + assertEquals("myToken", ((com.nokia.cbam.lcm.v32.auth.OAuth) apiClient.getAuthentication("OauthClient")).getAccessToken()); + assertEquals(2, cbamLcnApi.getApiClient().getAuthentications().size()); + assertTrue(cbamLcnApi.getApiClient().isVerifyingSsl()); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestGenericExternalSystemInfoProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestGenericExternalSystemInfoProvider.java new file mode 100644 index 00000000..44263835 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestGenericExternalSystemInfoProvider.java @@ -0,0 +1,104 @@ +/* + * 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.core; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.onap.vnfmdriver.model.VimInfo; +import org.onap.vnfmdriver.model.VnfmInfo; +import org.springframework.core.env.Environment; +import org.springframework.test.util.ReflectionTestUtils; + +import static java.lang.Long.valueOf; +import static junit.framework.TestCase.assertEquals; +import static org.mockito.Mockito.*; + +public class TestGenericExternalSystemInfoProvider extends TestBase { + + private GenericExternalSystemInfoProvider genericExternalSystemInfoProvider; + + @Before + public void init() { + when(environment.getProperty(IpMappingProvider.IP_MAP, String.class, "")).thenReturn(""); + ReflectionTestUtils.setField(GenericExternalSystemInfoProvider.class, "logger", logger); + genericExternalSystemInfoProvider = Mockito.spy(new TestClass(environment)); + } + + /** + * the VNFM info is not retrieved within the cache eviction period + */ + @Test + public void testQueryVnfmInfoWithin() throws Exception { + VnfmInfo expectedVnfmInfo = Mockito.mock(VnfmInfo.class); + when(genericExternalSystemInfoProvider.queryVnfmInfoFromSource(VNFM_ID)).thenReturn(expectedVnfmInfo); + when(environment.getProperty(GenericExternalSystemInfoProvider.VNFM_INFO_CACHE_EVICTION_IN_MS, Long.class, valueOf(GenericExternalSystemInfoProvider.DEFAULT_CACHE_EVICTION_TIMEOUT_IN_MS))).thenReturn(Long.valueOf(1234)); + genericExternalSystemInfoProvider.afterPropertiesSet(); + //when + VnfmInfo vnfmInfo = genericExternalSystemInfoProvider.getVnfmInfo(VNFM_ID); + //verify + verify(logger).info("Quering VNFM info from source with " + VNFM_ID + " identifier"); + assertEquals(expectedVnfmInfo, vnfmInfo); + //when + VnfmInfo vnfmInfo2 = genericExternalSystemInfoProvider.getVnfmInfo(VNFM_ID); + //verify source system not called again + verify(logger).info("Quering VNFM info from source with " + VNFM_ID + " identifier"); + verify(genericExternalSystemInfoProvider, Mockito.times(1)).queryVnfmInfoFromSource(VNFM_ID); + } + + /** + * the VNFM info is retrieved without the cache eviction period + */ + @Test + public void testQueryVnfmInfoOutside() throws Exception { + VnfmInfo expectedVnfmInfo = Mockito.mock(VnfmInfo.class); + when(genericExternalSystemInfoProvider.queryVnfmInfoFromSource(VNFM_ID)).thenReturn(expectedVnfmInfo); + when(environment.getProperty(GenericExternalSystemInfoProvider.VNFM_INFO_CACHE_EVICTION_IN_MS, Long.class, valueOf(GenericExternalSystemInfoProvider.DEFAULT_CACHE_EVICTION_TIMEOUT_IN_MS))).thenReturn(Long.valueOf(1)); + genericExternalSystemInfoProvider.afterPropertiesSet(); + + //when + VnfmInfo vnfmInfo = genericExternalSystemInfoProvider.getVnfmInfo(VNFM_ID); + //verify + assertEquals(expectedVnfmInfo, vnfmInfo); + //when + //sleeping is required to make time pass (for cache to notice the change) + Thread.sleep(10); + VnfmInfo vnfmInfo2 = genericExternalSystemInfoProvider.getVnfmInfo(VNFM_ID); + //verify source system called again + verify(logger, times(2)).info("Quering VNFM info from source with " + VNFM_ID + " identifier"); + verify(genericExternalSystemInfoProvider, Mockito.times(2)).queryVnfmInfoFromSource(VNFM_ID); + } + + class TestClass extends GenericExternalSystemInfoProvider { + + TestClass(Environment environment) { + super(environment); + } + + @Override + public VnfmInfo queryVnfmInfoFromSource(String vnfmId) { + return null; + } + + @Override + public VimInfo getVimInfo(String vimId) { + return null; + } + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestIpMappingProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestIpMappingProvider.java new file mode 100644 index 00000000..a1f91855 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestIpMappingProvider.java @@ -0,0 +1,61 @@ +/* + * 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.core; + +import org.junit.Before; +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.springframework.core.env.Environment; + +import static junit.framework.TestCase.assertEquals; +import static org.mockito.Mockito.when; + +public class TestIpMappingProvider extends TestBase { + + private IpMappingProvider ipMappingProvider; + + @Before + public void init() { + ipMappingProvider = new TestClass(environment); + } + + /** + * the IP addresses are correctly mapped + */ + @Test + public void testIpMapping() throws Exception { + when(environment.getProperty(IpMappingProvider.IP_MAP, String.class, "")).thenReturn(" 1.2.3.4 -> 2.3.4.5 , 1.2.3.5 -> 3.4.5.6"); + //when + ipMappingProvider.afterPropertiesSet(); + //verify + assertEquals("2.3.4.5", ipMappingProvider.mapPrivateIpToPublicIp("1.2.3.4")); + assertEquals(".......", ipMappingProvider.mapPrivateIpToPublicIp(".......")); + assertEquals("3.4.5.6", ipMappingProvider.mapPrivateIpToPublicIp("1.2.3.5")); + assertEquals("1.2.3.5.", ipMappingProvider.mapPrivateIpToPublicIp("1.2.3.5.")); + + } + + class TestClass extends IpMappingProvider { + + TestClass(Environment environment) { + super(environment); + } + + } + + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestMsbApiProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestMsbApiProvider.java new file mode 100644 index 00000000..e6d8ebb4 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/core/TestMsbApiProvider.java @@ -0,0 +1,146 @@ +/* + * 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.core; + +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.onap.msb.sdk.discovery.common.RouteException; +import org.onap.msb.sdk.discovery.entity.MicroServiceFullInfo; +import org.onap.msb.sdk.discovery.entity.NodeInfo; +import org.onap.msb.sdk.httpclient.msb.MSBServiceClient; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamTokenProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.springframework.core.env.Environment; + +import java.util.HashSet; +import java.util.Set; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.fail; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.test.util.ReflectionTestUtils.setField; + +public class TestMsbApiProvider extends TestBase { + @Mock + private Environment environment; + @Mock + private CbamTokenProvider cbamTokenProvider; + private MicroServiceFullInfo microServiceInfo = new MicroServiceFullInfo(); + private Set<NodeInfo> nodes = new HashSet<>(); + private MsbApiProvider msbApiProvider; + + @Before + public void init() { + setField(MsbApiProvider.class, "logger", logger); + msbApiProvider = new MsbApiProvider(environment); + microServiceInfo.setNodes(nodes); + } + + /** + * test MSB client is created based on driver properties + */ + @Test + public void testMsbClient() { + setFieldWithPropertyAnnotation(msbApiProvider, "${messageBusIp}", "mymessageBusIp"); + setFieldWithPropertyAnnotation(msbApiProvider, "${messageBusPort}", "123"); + //when + MSBServiceClient msbClient = msbApiProvider.getMsbClient(); + //verify + assertEquals("mymessageBusIp:123", msbClient.getMsbSvrAddress()); + } + + /** + * error is propagated if no suitable micro service endpoint is found + */ + @Test + public void testNoSuitableMicroService() throws Exception { + NodeInfo dockerAccessPoint = new NodeInfo(); + dockerAccessPoint.setIp("172.1.2.3"); + microServiceInfo.setServiceName("serviceName"); + microServiceInfo.setVersion("v1"); + microServiceInfo.setUrl("/lead/nslcm/v1"); + when(environment.getProperty(IpMappingProvider.IP_MAP, String.class, "")).thenReturn(""); + nodes.add(dockerAccessPoint); + msbApiProvider = new MsbApiProvider(environment) { + @Override + public MSBServiceClient getMsbClient() { + return msbClient; + } + }; + when(msbClient.queryMicroServiceInfo("serviceName", "v1")).thenReturn(microServiceInfo); + //when + try { + msbApiProvider.getMicroServiceUrl("serviceName", "v1"); + fail(); + } catch (Exception e) { + assertEquals("The serviceName service with v1 does not have any valid nodes[172.1.2.3:null ttl:]", e.getMessage()); + verify(logger).error("The serviceName service with v1 does not have any valid nodes[172.1.2.3:null ttl:]"); + } + } + + /** + * non Docker endpoint is selected + */ + @Test + public void testExistingValidEndpoint() throws Exception { + NodeInfo nonDocker = new NodeInfo(); + nonDocker.setIp("173.1.2.3"); + nonDocker.setPort("234"); + microServiceInfo.setServiceName("serviceName"); + microServiceInfo.setVersion("v1"); + microServiceInfo.setUrl("/lead/nslcm/v1"); + when(environment.getProperty(IpMappingProvider.IP_MAP, String.class, "")).thenReturn("173.1.2.3->1.2.3.4"); + nodes.add(nonDocker); + msbApiProvider = new MsbApiProvider(environment) { + @Override + public MSBServiceClient getMsbClient() { + return msbClient; + } + }; + when(msbClient.queryMicroServiceInfo("serviceName", "v1")).thenReturn(microServiceInfo); + msbApiProvider.afterPropertiesSet(); + //when + assertEquals("http://1.2.3.4:234/lead/nslcm/v1", msbApiProvider.getMicroServiceUrl("serviceName", "v1")); + } + + /** + * if unable to get micro service info the error is propagated + */ + @Test + public void testUnableQueryMicroserviInfo() throws Exception { + msbApiProvider = new MsbApiProvider(environment) { + @Override + public MSBServiceClient getMsbClient() { + return msbClient; + } + }; + RouteException expectedException = new RouteException(); + when(msbClient.queryMicroServiceInfo("serviceName", "v1")).thenThrow(expectedException); + + //when + try { + msbApiProvider.getMicroServiceUrl("serviceName", "v1"); + fail(); + } catch (Exception e) { + assertEquals("Unable to get micro service URL for serviceName with version v1", e.getMessage()); + verify(logger).error("Unable to get micro service URL for serviceName with version v1", expectedException); + } + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcExternalSystemInfoProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcExternalSystemInfoProvider.java new file mode 100644 index 00000000..1081b93c --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcExternalSystemInfoProvider.java @@ -0,0 +1,100 @@ +/* + * 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.vfc; + +import org.junit.Before; +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.onap.vnfmdriver.ApiException; +import org.onap.vnfmdriver.model.VimInfo; +import org.onap.vnfmdriver.model.VnfmInfo; +import org.springframework.test.util.ReflectionTestUtils; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.fail; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +public class TestVfcExternalSystemInfoProvider extends TestBase { + private VfcExternalSystemInfoProvider vfcExternalSystemInfoProvider; + + @Before + public void init() { + vfcExternalSystemInfoProvider = new VfcExternalSystemInfoProvider(environment, vfcRestApiProvider); + ReflectionTestUtils.setField(VfcExternalSystemInfoProvider.class, "logger", logger); + } + + /** + * VIM is queried using VF-C APIs + */ + @Test + public void testVimRetrieval() throws Exception { + VimInfo expectedVimInfo = new VimInfo(); + when(nsLcmApi.queryVIMInfo(VIM_ID)).thenReturn(expectedVimInfo); + //when + VimInfo vimInfo = vfcExternalSystemInfoProvider.getVimInfo(VIM_ID); + //verify + assertEquals(expectedVimInfo, vimInfo); + } + + /** + * failure to retrieve VIM from VF-C is propagated + */ + @Test + public void testUnableToQueryVim() throws Exception { + ApiException expectedException = new ApiException(); + when(nsLcmApi.queryVIMInfo(VIM_ID)).thenThrow(expectedException); + //when + try { + vfcExternalSystemInfoProvider.getVimInfo(VIM_ID); + fail(); + } catch (Exception e) { + assertEquals("Unable to query VIM from VF-C with myVimId identifier", e.getMessage()); + verify(logger).error("Unable to query VIM from VF-C with myVimId identifier", expectedException); + } + } + + /** + * VNFM is queried using VF-C APIs + */ + @Test + public void testVnfmRetrieval() throws Exception { + VnfmInfo expectedVimInfo = new VnfmInfo(); + when(nsLcmApi.queryVnfmInfo(VNFM_ID)).thenReturn(expectedVimInfo); + //when + VnfmInfo vimInfo = vfcExternalSystemInfoProvider.queryVnfmInfoFromSource(VNFM_ID); + //verify + assertEquals(expectedVimInfo, vimInfo); + } + + /** + * failure to retrieve VNFM from VF-C is propagated + */ + @Test + public void testUnableToQueryVnfm() throws Exception { + ApiException expectedException = new ApiException(); + when(nsLcmApi.queryVnfmInfo(VNFM_ID)).thenThrow(expectedException); + //when + try { + vfcExternalSystemInfoProvider.queryVnfmInfoFromSource(VNFM_ID); + fail(); + } catch (Exception e) { + assertEquals("Unable to query VNFM from VF-C with myVnfmId identifier", e.getMessage()); + verify(logger).error("Unable to query VNFM from VF-C with myVnfmId identifier", expectedException); + } + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcGrantManager.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcGrantManager.java new file mode 100644 index 00000000..7ca19d63 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcGrantManager.java @@ -0,0 +1,337 @@ +/* + * 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.vfc; + +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.JsonObject; +import com.nokia.cbam.lcm.v32.model.*; +import com.nokia.cbam.lcm.v32.model.VnfInfo; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager; +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.vnfmdriver.ApiException; +import org.onap.vnfmdriver.model.*; +import org.onap.vnfmdriver.model.ScaleDirection; + +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import static java.nio.file.Files.readAllBytes; +import static junit.framework.TestCase.*; +import static org.mockito.Mockito.*; +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 TestVfcGrantManager extends TestBase { + + private ArgumentCaptor<GrantVNFRequest> grantRequest = ArgumentCaptor.forClass(GrantVNFRequest.class); + private GrantVNFResponseVim vim = new GrantVNFResponseVim(); + private GrantVNFResponse grantResponse = new GrantVNFResponse(); + @Mock + private CatalogManager cbamCatalogManager; + @InjectMocks + private VfcGrantManager vfcGrantManager; + + @Before + public void initMocks() throws Exception { + setField(VfcGrantManager.class, "logger", logger); + when(nsLcmApi.grantvnf(grantRequest.capture())).thenReturn(grantResponse); + grantResponse.setVim(vim); + } + + /** + * test grant request for instantiation + */ + @Test + public void testGrantDuringInstantiation() throws Exception { + String cbamVnfdContent = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/vnfd.instantiation.yaml").toURI()))); + //when + vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, "level1", cbamVnfdContent, JOB_ID); + //verify + assertEquals(1, grantRequest.getAllValues().size()); + GrantVNFRequest request = grantRequest.getValue(); + assertVduInGrant(request.getAddResource(), "vdu1", 1); + assertVduInGrant(request.getAddResource(), "vdu2", 2); + assertEquals(0, request.getRemoveResource().size()); + assertBasicGrantAttributes(request, org.onap.vnfmdriver.model.OperationType.INSTANTIATE); + } + + /** + * test failure logging & propagation during grant request for instantiation + */ + @Test + public void testFailureDuringGrantPreparation() throws Exception { + String cbamVnfdContent = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/vnfd.instantiation.yaml").toURI()))); + //when + try { + vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, "missingLevel", cbamVnfdContent, JOB_ID); + //verify + fail(); + } catch (RuntimeException e) { + verify(logger).error(Mockito.eq("Unable to prepare grant request for instantiation"), Mockito.any(RuntimeException.class)); + verifyNoMoreInteractions(nsLcmApi); + } + } + + /** + * test grant request for instantiation + */ + @Test + public void testFailureDuringGrantRequest() throws Exception { + String cbamVnfdContent = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/vnfd.instantiation.yaml").toURI()))); + ApiException expectedException = new ApiException("a"); + when(nsLcmApi.grantvnf(Mockito.any())).thenThrow(expectedException); + //when + try { + vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, "level1", cbamVnfdContent, JOB_ID); + //verify + fail(); + } catch (RuntimeException e) { + verify(logger).error("Unable to request grant", expectedException); + } + } + + /** + * No grant is requested for termination if the the VNF is not instantiated + */ + @Test + public void testNoGrantIsRequestedIfNotInstantiated() { + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnf.setInstantiationState(InstantiationState.NOT_INSTANTIATED); + //when + vfcGrantManager.requestGrantForTerminate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, vnf, JOB_ID); + //verify + verifyNoMoreInteractions(nsLcmApi); + } + + /** + * grant is requested for termination if the the VNF is instantiated + */ + @Test + public void testGrantIsRequestedIfInstantiated() { + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnf.setInstantiationState(InstantiationState.INSTANTIATED); + InstantiatedVnfInfo instantiatedVnfInfo = new InstantiatedVnfInfo(); + VnfcResourceInfo vnfc = new VnfcResourceInfo(); + vnfc.setId("vnfcId1"); + vnfc.setVduId("vdu1"); + instantiatedVnfInfo.setVnfcResourceInfo(new ArrayList<>()); + instantiatedVnfInfo.getVnfcResourceInfo().add(vnfc); + vnf.setInstantiatedVnfInfo(instantiatedVnfInfo); + VnfProperty prop = new VnfProperty(); + prop.setName(LifecycleManager.ONAP_CSAR_ID); + prop.setValue(ONAP_CSAR_ID); + vnf.setVnfConfigurableProperties(new ArrayList<>()); + vnf.getVnfConfigurableProperties().add(prop); + //when + vfcGrantManager.requestGrantForTerminate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, vnf, JOB_ID); + //verify + assertEquals(1, grantRequest.getAllValues().size()); + GrantVNFRequest request = grantRequest.getValue(); + assertVduInGrant(request.getRemoveResource(), "vdu1", 1); + assertVduInGrant(request.getRemoveResource(), "vdu2", 0); + assertEquals(0, request.getAddResource().size()); + assertBasicGrantAttributes(request, org.onap.vnfmdriver.model.OperationType.TERMINAL); + } + + /** + * test failure logging & propagation during grant request for instantiation + */ + @Test + public void testFailureDuringTerminationGrantPreparation() throws Exception { + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnf.setInstantiatedVnfInfo(null); + vnf.setInstantiationState(InstantiationState.INSTANTIATED); + //when + try { + vfcGrantManager.requestGrantForTerminate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, vnf, JOB_ID); + //verify + fail(); + } catch (RuntimeException e) { + verify(logger).error(Mockito.eq("Unable to prepare grant request for termination"), Mockito.any(RuntimeException.class)); + verifyNoMoreInteractions(nsLcmApi); + } + } + + /** + * failuire is to request grant is logged + */ + @Test + public void testFailureToRequestGrantIsLogged() throws Exception { + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnf.setInstantiationState(InstantiationState.INSTANTIATED); + InstantiatedVnfInfo instantiatedVnfInfo = new InstantiatedVnfInfo(); + VnfcResourceInfo vnfc = new VnfcResourceInfo(); + vnfc.setId("vnfcId1"); + vnfc.setVduId("vdu1"); + instantiatedVnfInfo.setVnfcResourceInfo(new ArrayList<>()); + instantiatedVnfInfo.getVnfcResourceInfo().add(vnfc); + vnf.setInstantiatedVnfInfo(instantiatedVnfInfo); + VnfProperty prop = new VnfProperty(); + prop.setName(LifecycleManager.ONAP_CSAR_ID); + prop.setValue(ONAP_CSAR_ID); + vnf.setVnfConfigurableProperties(new ArrayList<>()); + vnf.getVnfConfigurableProperties().add(prop); + ApiException expectedException = new ApiException(); + when(nsLcmApi.grantvnf(Mockito.any())).thenThrow(expectedException); + //when + try { + vfcGrantManager.requestGrantForTerminate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, vnf, JOB_ID); + //verify + fail(); + } catch (RuntimeException e) { + verify(logger).error(Mockito.eq("Unable to request grant"), Mockito.eq(expectedException)); + } + } + + /** + * failuire is to request grant is logged + */ + @Test + public void testFailureToRequestGrantForScaleIsLogged() throws Exception { + String cbamVnfdContent = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/vnfd.scale.yaml").toURI()))); + VnfScaleRequest scaleRequest = new VnfScaleRequest(); + scaleRequest.setType(ScaleDirection.OUT); + scaleRequest.setAspectId("aspect1"); + scaleRequest.setNumberOfSteps("2"); + com.nokia.cbam.lcm.v32.ApiException expectedException = new com.nokia.cbam.lcm.v32.ApiException(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //when + try { + vfcGrantManager.requestGrantForScale(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, scaleRequest, JOB_ID); + //verify + fail(); + } catch (RuntimeException e) { + verify(logger).error(Mockito.eq("Unable to query VNF myVnfId"), Mockito.eq(expectedException)); + assertEquals(e.getCause(), expectedException); + } + } + + /** + * test grant request for scale out + */ + @Test + public void testGrantDuringScaleOut() throws Exception { + String cbamVnfdContent = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/vnfd.scale.yaml").toURI()))); + VnfScaleRequest scaleRequest = new VnfScaleRequest(); + scaleRequest.setType(ScaleDirection.OUT); + scaleRequest.setAspectId("aspect1"); + scaleRequest.setNumberOfSteps("2"); + VnfInfo vnf = new VnfInfo(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnf); + vnf.setVnfdId(CBAM_VNFD_ID); + when(cbamCatalogManager.getCbamVnfdContent(VNFM_ID, CBAM_VNFD_ID)).thenReturn(cbamVnfdContent); + //when + vfcGrantManager.requestGrantForScale(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, scaleRequest, JOB_ID); + //verify + assertEquals(1, grantRequest.getAllValues().size()); + GrantVNFRequest request = grantRequest.getValue(); + assertVduInGrant(request.getAddResource(), "vdu1", 4); + assertVduInGrant(request.getAddResource(), "vdu2", 2); + assertEquals(0, request.getRemoveResource().size()); + assertBasicGrantAttributes(request, org.onap.vnfmdriver.model.OperationType.SCALEOUT); + } + + /** + * test grant request for scale in + */ + @Test + public void testGrantDuringScaleIn() throws Exception { + String cbamVnfdContent = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/vnfd.scale.yaml").toURI()))); + VnfScaleRequest scaleRequest = new VnfScaleRequest(); + scaleRequest.setType(ScaleDirection.IN); + scaleRequest.setAspectId("aspect1"); + scaleRequest.setNumberOfSteps("2"); + VnfInfo vnf = new VnfInfo(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnf); + vnf.setVnfdId(CBAM_VNFD_ID); + when(cbamCatalogManager.getCbamVnfdContent(VNFM_ID, CBAM_VNFD_ID)).thenReturn(cbamVnfdContent); + //when + vfcGrantManager.requestGrantForScale(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, scaleRequest, JOB_ID); + //verify + assertEquals(1, grantRequest.getAllValues().size()); + GrantVNFRequest request = grantRequest.getValue(); + assertVduInGrant(request.getRemoveResource(), "vdu1", 4); + assertVduInGrant(request.getRemoveResource(), "vdu2", 2); + assertEquals(0, request.getAddResource().size()); + assertBasicGrantAttributes(request, org.onap.vnfmdriver.model.OperationType.SCALEIN); + } + + + /** + * test grant request for healing + */ + @Test + public void testGrantDuringHealing() throws Exception { + //when + VnfHealRequest healRequest = new VnfHealRequest(); + VnfHealRequestAffectedvm affectedVm = new VnfHealRequestAffectedvm(); + affectedVm.setVduid("vdu1"); + healRequest.setAffectedvm(affectedVm); + vfcGrantManager.requestGrantForHeal(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, healRequest, JOB_ID); + //verify + assertEquals(1, grantRequest.getAllValues().size()); + GrantVNFRequest request = grantRequest.getValue(); + assertVduInGrant(request.getAddResource(), "vdu1", 1); + assertVduInGrant(request.getRemoveResource(), "vdu1", 1); + assertBasicGrantAttributes(request, org.onap.vnfmdriver.model.OperationType.HEAL); + } + + private void assertBasicGrantAttributes(GrantVNFRequest request, org.onap.vnfmdriver.model.OperationType type) { + assertEquals(JOB_ID, request.getJobId()); + assertEquals(type, request.getLifecycleOperation()); + assertEquals(ONAP_CSAR_ID, request.getVnfDescriptorId()); + assertEquals(VNF_ID, request.getVnfInstanceId()); + JsonObject additionalParams = new Gson().toJsonTree(request.getAdditionalParam()).getAsJsonObject(); + assertEquals(VIM_ID, additionalParams.get("vimId").getAsString()); + assertEquals(VNFM_ID, additionalParams.get("vnfmId").getAsString()); + } + + private void assertVduInGrant(List<ResourceChange> changes, String vduName, int count) { + ArrayList<ResourceChange> clonedChanges = Lists.newArrayList(changes); + for (int i = 0; i < count + 1; i++) { + Iterator<ResourceChange> iter = clonedChanges.iterator(); + boolean found = false; + while (iter.hasNext()) { + ResourceChange change = iter.next(); + if (change.getVdu().equals(vduName)) { + iter.remove(); + found = true; + break; + } + } + if (i >= count) { + assertFalse(found); + } else { + assertTrue(found); + } + } + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcNotificationSender.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcNotificationSender.java new file mode 100644 index 00000000..42906c7b --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcNotificationSender.java @@ -0,0 +1,760 @@ +/* + * 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.vfc; + +import com.google.common.collect.Lists; +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.nokia.cbam.lcm.v32.model.AffectedVirtualLink; +import com.nokia.cbam.lcm.v32.model.AffectedVirtualStorage; +import com.nokia.cbam.lcm.v32.model.AffectedVnfc; +import com.nokia.cbam.lcm.v32.model.ChangeType; +import com.nokia.cbam.lcm.v32.model.*; +import com.nokia.cbam.lcm.v32.model.OperationType; +import com.nokia.cbam.lcm.v32.model.ScaleDirection; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.ReportedAffectedConnectionPoints; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.ReportedAffectedCp; +import org.onap.vnfmdriver.ApiException; +import org.onap.vnfmdriver.model.*; +import org.threeten.bp.OffsetDateTime; + +import java.util.ArrayList; +import java.util.List; + +import static junit.framework.TestCase.*; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.*; +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 TestVfcNotificationSender extends TestBase { + private VfcNotificationSender vfcNotificationSender; + private ArgumentCaptor<VNFLCMNotification> sentLcnToVfc = ArgumentCaptor.forClass(VNFLCMNotification.class); + private VnfLifecycleChangeNotification recievedLcn = new VnfLifecycleChangeNotification(); + private List<OperationExecution> operationExecutions = new ArrayList<>(); + private OperationExecution instantiationOperation = new OperationExecution(); + private OperationExecution scaleOperation = new OperationExecution(); + private OperationExecution healOperation = new OperationExecution(); + private OperationExecution terminationOperation = new OperationExecution(); + private ReportedAffectedConnectionPoints affectedCp; + + + @Before + public void init() throws Exception { + vfcNotificationSender = new VfcNotificationSender(driverProperties, vfcRestApiProvider); + setField(VfcNotificationSender.class, "logger", logger); + Mockito.doNothing().when(nsLcmApi).vNFLCMNotification(eq(VNFM_ID), eq(VNF_ID), sentLcnToVfc.capture()); + instantiationOperation.setId("instantiationOperationExecutionId"); + instantiationOperation.setStartTime(OffsetDateTime.now()); + instantiationOperation.setOperationType(OperationType.INSTANTIATE); + scaleOperation.setId("scaleOperationExecutionId"); + scaleOperation.setStartTime(OffsetDateTime.now().plusDays(1)); + scaleOperation.setOperationType(OperationType.SCALE); + terminationOperation.setId("terminationExecutionId"); + terminationOperation.setStartTime(OffsetDateTime.now().plusDays(1)); + terminationOperation.setOperationType(OperationType.TERMINATE); + healOperation.setId("healOperaitonExecutionId"); + healOperation.setOperationType(OperationType.HEAL); + healOperation.setStartTime(OffsetDateTime.now().plusDays(1)); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(operationExecutions); + prepOperation(instantiationOperation); + prepOperation(scaleOperation); + prepOperation(healOperation); + prepOperation(terminationOperation); + recievedLcn.setVnfInstanceId(VNF_ID); + } + + private void prepOperation(OperationExecution operationExecution) throws com.nokia.cbam.lcm.v32.ApiException { + addEmptyModifiedConnectionPoints(operationExecution); + JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}"); + operationExecution.setOperationParams(root); + switch (operationExecution.getOperationType()) { + case TERMINATE: + root.getAsJsonObject().addProperty("terminationType", "GRACEFULL"); + } + when(operationExecutionApi.operationExecutionsOperationExecutionIdGet(operationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(operationExecution); + operationExecutions.add(operationExecution); + } + + private void addEmptyModifiedConnectionPoints(OperationExecution operationExecution) { + OperationResult operationResult = new OperationResult(); + operationResult.operationResult = new ReportedAffectedConnectionPoints(); + JsonElement additionalData = new Gson().toJsonTree(operationResult); + operationExecution.setAdditionalData(additionalData); + } + + /** + * test start notification success scenario + * - the affected resources are not processed even if present + * - LCN is sent to VF-C + */ + @Test + public void testStartLcn() { + recievedLcn.setStatus(OperationStatus.STARTED); + recievedLcn.setOperation(OperationType.INSTANTIATE); + //when + vfcNotificationSender.processNotification(recievedLcn, instantiationOperation, affectedCp, VIM_ID); + //verify + assertEquals(1, sentLcnToVfc.getAllValues().size()); + assertNull(sentLcnToVfc.getValue().getAffectedVl()); + assertNull(sentLcnToVfc.getValue().getAffectedVnfc()); + assertNull(sentLcnToVfc.getValue().getAffectedCp()); + assertNull(sentLcnToVfc.getValue().getAffectedVirtualStorage()); + + assertEquals(JOB_ID, sentLcnToVfc.getValue().getJobId()); + assertEquals(org.onap.vnfmdriver.model.OperationType.INSTANTIATE, sentLcnToVfc.getValue().getOperation()); + assertEquals(VnfLcmNotificationStatus.START, sentLcnToVfc.getValue().getStatus()); + assertEquals(VNF_ID, sentLcnToVfc.getValue().getVnfInstanceId()); + } + + /** + * test end notification success scenario + * - LCN is sent to VF-C + */ + @Test + public void testFinishLcn() { + //given + recievedLcn.setOperation(OperationType.INSTANTIATE); + recievedLcn.setStatus(OperationStatus.FINISHED); + AffectedVnfc affectedVnfc = new AffectedVnfc(); + affectedVnfc.setChangeType(ChangeType.ADDED); + affectedVnfc.setId("myVnfcId"); + affectedVnfc.setVduId("myVduId"); + affectedVnfc.setStorageResourceIds(Lists.newArrayList("storageId1")); + affectedVnfc.setComputeResource(new ResourceHandle()); + affectedVnfc.getComputeResource().setResourceId("serverProviderId"); + affectedVnfc.getComputeResource().setVimId(VIM_ID); + affectedVnfc.getComputeResource().setAdditionalData(new JsonParser().parse("{ \"name\" : \"myVmName\" } ")); + recievedLcn.setAffectedVnfcs(new ArrayList<>()); + recievedLcn.getAffectedVnfcs().add(affectedVnfc); + + AffectedVirtualLink affectedVirtualLink = new AffectedVirtualLink(); + affectedVirtualLink.setChangeType(ChangeType.ADDED); + affectedVirtualLink.setId("vlId"); + affectedVirtualLink.setVirtualLinkDescId("vlVnfdId"); + affectedVirtualLink.setResource(new ResourceHandle()); + affectedVirtualLink.getResource().setVimId(VIM_ID); + affectedVirtualLink.getResource().setResourceId("networkProviderId"); + recievedLcn.setAffectedVirtualLinks(new ArrayList<>()); + recievedLcn.getAffectedVirtualLinks().add(affectedVirtualLink); + + AffectedVirtualStorage affectedStorage = new AffectedVirtualStorage(); + affectedStorage.setChangeType(ChangeType.ADDED); + affectedStorage.setId("storageId"); + affectedStorage.setVirtualStorageDescId("storageVnfdId"); + affectedStorage.setResource(new ResourceHandle()); + affectedStorage.getResource().setVimId(VIM_ID); + affectedStorage.getResource().setResourceId("storageProviderId"); + recievedLcn.setAffectedVirtualStorages(new ArrayList<>()); + recievedLcn.getAffectedVirtualStorages().add(affectedStorage); + + ReportedAffectedConnectionPoints affectedConnectionPoints = new ReportedAffectedConnectionPoints(); + ReportedAffectedCp affectedCp = new ReportedAffectedCp(); + affectedCp.setChangeType(ChangeType.ADDED); + affectedCp.setCpdId("cpVnfdId"); + affectedCp.setIpAddress("1.2.3.4"); + affectedCp.setMacAddress("myMac"); + affectedCp.setName("myPortName"); + affectedCp.setCpId("cpId"); + + affectedCp.setNetworkProviderId("networkProviderId"); + affectedCp.setProviderId("portProviderId"); + affectedCp.setServerProviderId("serverProviderId"); + affectedCp.setTenantId("tenantId"); + affectedConnectionPoints.getPost().add(affectedCp); + + OperationResult operationResult = new OperationResult(); + operationResult.operationResult = affectedConnectionPoints; + JsonElement additionalData = new Gson().toJsonTree(operationResult); + instantiationOperation.setAdditionalData(additionalData); + //when + vfcNotificationSender.processNotification(recievedLcn, instantiationOperation, affectedConnectionPoints, VIM_ID); + //verify + assertEquals(1, sentLcnToVfc.getAllValues().size()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVl().size()); + org.onap.vnfmdriver.model.AffectedVirtualLink actualAffectedVl = sentLcnToVfc.getValue().getAffectedVl().get(0); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.ADDED, actualAffectedVl.getChangeType()); + assertEquals("vlVnfdId", actualAffectedVl.getVldid()); + assertEquals("myVnfId_vlId", actualAffectedVl.getVlInstanceId()); + assertEquals("networkProviderId", actualAffectedVl.getNetworkResource().getResourceId()); + assertEquals(AffectedVirtualLinkType.NETWORK, actualAffectedVl.getNetworkResource().getResourceType()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVnfc().size()); + org.onap.vnfmdriver.model.AffectedVnfc actualAffectdVnfc = sentLcnToVfc.getValue().getAffectedVnfc().get(0); + assertEquals("myVduId", actualAffectdVnfc.getVduId()); + assertEquals(VIM_ID, actualAffectdVnfc.getVimid()); + assertEquals("myVmName", actualAffectdVnfc.getVmname()); + assertEquals("serverProviderId", actualAffectdVnfc.getVmid()); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.ADDED, actualAffectdVnfc.getChangeType()); + assertEquals("myVnfId_myVnfcId", actualAffectdVnfc.getVnfcInstanceId()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedCp().size()); + AffectedCp actualAffectedCp = sentLcnToVfc.getValue().getAffectedCp().get(0); + assertEquals("cpVnfdId", actualAffectedCp.getCpdid()); + assertEquals("myVnfId_cpId", actualAffectedCp.getCpinstanceid()); + assertEquals(null, actualAffectedCp.getOwnerId()); + assertEquals(null, actualAffectedCp.getOwnerType()); + assertEquals("networkProviderId", actualAffectedCp.getVirtualLinkInstanceId()); + assertEquals("1.2.3.4", actualAffectedCp.getPortResource().getIpAddress()); + assertEquals("myMac", actualAffectedCp.getPortResource().getMacAddress()); + assertEquals("tenantId", actualAffectedCp.getPortResource().getTenant()); + assertEquals(VIM_ID, actualAffectedCp.getPortResource().getVimid()); + assertEquals("serverProviderId", actualAffectedCp.getPortResource().getInstId()); + assertEquals("portProviderId", actualAffectedCp.getPortResource().getResourceid()); + assertEquals("myPortName", actualAffectedCp.getPortResource().getResourceName()); + assertEquals(VnfCpNotificationType.ADDED, actualAffectedCp.getChangeType()); + + assertNull(sentLcnToVfc.getValue().getAffectedVirtualStorage()); + assertEquals(JOB_ID, sentLcnToVfc.getValue().getJobId()); + assertEquals(org.onap.vnfmdriver.model.OperationType.INSTANTIATE, sentLcnToVfc.getValue().getOperation()); + assertEquals(VnfLcmNotificationStatus.RESULT, sentLcnToVfc.getValue().getStatus()); + assertEquals(VNF_ID, sentLcnToVfc.getValue().getVnfInstanceId()); + } + + /** + * test end notification success scenario for ECP + */ + @Test + public void testFinishLcnForEcp() { + //given + recievedLcn.setOperation(OperationType.INSTANTIATE); + recievedLcn.setStatus(OperationStatus.FINISHED); + AffectedVnfc affectedVnfc = new AffectedVnfc(); + affectedVnfc.setChangeType(ChangeType.ADDED); + affectedVnfc.setId("myVnfcId"); + affectedVnfc.setVduId("myVduId"); + affectedVnfc.setStorageResourceIds(Lists.newArrayList("storageId1")); + affectedVnfc.setComputeResource(new ResourceHandle()); + affectedVnfc.getComputeResource().setResourceId("serverProviderId"); + affectedVnfc.getComputeResource().setVimId(VIM_ID); + affectedVnfc.getComputeResource().setAdditionalData(new JsonParser().parse("{ \"name\" : \"myVmName\" } ")); + recievedLcn.setAffectedVnfcs(new ArrayList<>()); + recievedLcn.getAffectedVnfcs().add(affectedVnfc); + + ReportedAffectedConnectionPoints affectedConnectionPoints = new ReportedAffectedConnectionPoints(); + ReportedAffectedCp affectedCp = new ReportedAffectedCp(); + affectedCp.setChangeType(ChangeType.ADDED); + //affectedCp.setCpdId("cpVnfdId"); + affectedCp.setIpAddress("1.2.3.4"); + affectedCp.setMacAddress("myMac"); + affectedCp.setName("myPortName"); + affectedCp.setCpId("cpId"); + affectedCp.setEcpdId("ecpdId"); + affectedCp.setNetworkProviderId("networkProviderId"); + affectedCp.setProviderId("portProviderId"); + affectedCp.setServerProviderId("serverProviderId"); + affectedCp.setTenantId("tenantId"); + affectedConnectionPoints.getPost().add(affectedCp); + + OperationResult operationResult = new OperationResult(); + operationResult.operationResult = affectedConnectionPoints; + JsonElement additionalData = new Gson().toJsonTree(operationResult); + instantiationOperation.setAdditionalData(additionalData); + //when + vfcNotificationSender.processNotification(recievedLcn, instantiationOperation, affectedConnectionPoints, VIM_ID); + //verify + assertEquals(1, sentLcnToVfc.getAllValues().size()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedCp().size()); + AffectedCp actualAffectedCp = sentLcnToVfc.getValue().getAffectedCp().get(0); + assertEquals("ecpdId", actualAffectedCp.getCpdid()); + assertEquals("myVnfId_cpId", actualAffectedCp.getCpinstanceid()); + assertEquals(null, actualAffectedCp.getOwnerId()); + assertEquals(null, actualAffectedCp.getOwnerType()); + assertEquals("networkProviderId", actualAffectedCp.getVirtualLinkInstanceId()); + assertEquals("1.2.3.4", actualAffectedCp.getPortResource().getIpAddress()); + assertEquals("myMac", actualAffectedCp.getPortResource().getMacAddress()); + assertEquals("tenantId", actualAffectedCp.getPortResource().getTenant()); + assertEquals(VIM_ID, actualAffectedCp.getPortResource().getVimid()); + assertEquals("serverProviderId", actualAffectedCp.getPortResource().getInstId()); + assertEquals("portProviderId", actualAffectedCp.getPortResource().getResourceid()); + assertEquals("myPortName", actualAffectedCp.getPortResource().getResourceName()); + assertEquals(VnfCpNotificationType.ADDED, actualAffectedCp.getChangeType()); + } + + /** + * test end notification success scenario with termination + */ + @Test + public void testFinishLcnWithTerminate() { + //given + recievedLcn.setOperation(OperationType.TERMINATE); + recievedLcn.setStatus(OperationStatus.FINISHED); + AffectedVnfc affectedVnfc = new AffectedVnfc(); + affectedVnfc.setChangeType(ChangeType.REMOVED); + affectedVnfc.setId("myVnfcId"); + affectedVnfc.setVduId("myVduId"); + affectedVnfc.setStorageResourceIds(Lists.newArrayList("storageId1")); + affectedVnfc.setComputeResource(new ResourceHandle()); + affectedVnfc.getComputeResource().setResourceId("serverProviderId"); + affectedVnfc.getComputeResource().setVimId(VIM_ID); + affectedVnfc.getComputeResource().setAdditionalData(new JsonParser().parse("{ \"name\" : \"myVmName\" } ")); + recievedLcn.setAffectedVnfcs(new ArrayList<>()); + recievedLcn.getAffectedVnfcs().add(affectedVnfc); + + AffectedVirtualLink affectedVirtualLink = new AffectedVirtualLink(); + affectedVirtualLink.setChangeType(ChangeType.REMOVED); + affectedVirtualLink.setId("vlId"); + affectedVirtualLink.setVirtualLinkDescId("vlVnfdId"); + affectedVirtualLink.setResource(new ResourceHandle()); + affectedVirtualLink.getResource().setVimId(VIM_ID); + affectedVirtualLink.getResource().setResourceId("networkProviderId"); + recievedLcn.setAffectedVirtualLinks(new ArrayList<>()); + recievedLcn.getAffectedVirtualLinks().add(affectedVirtualLink); + + AffectedVirtualStorage affectedStorage = new AffectedVirtualStorage(); + affectedStorage.setChangeType(ChangeType.REMOVED); + affectedStorage.setId("storageId"); + affectedStorage.setVirtualStorageDescId("storageVnfdId"); + affectedStorage.setResource(new ResourceHandle()); + affectedStorage.getResource().setVimId(VIM_ID); + affectedStorage.getResource().setResourceId("storageProviderId"); + recievedLcn.setAffectedVirtualStorages(new ArrayList<>()); + recievedLcn.getAffectedVirtualStorages().add(affectedStorage); + + ReportedAffectedConnectionPoints affectedConnectionPoints = new ReportedAffectedConnectionPoints(); + ReportedAffectedCp affectedCp = new ReportedAffectedCp(); + affectedCp.setChangeType(ChangeType.REMOVED); + affectedCp.setCpdId("cpVnfdId"); + affectedCp.setIpAddress("1.2.3.4"); + affectedCp.setMacAddress("myMac"); + affectedCp.setName("myPortName"); + affectedCp.setCpId("cpId"); + + // affectedCp.setEcpdId("ecpdId"); + affectedCp.setNetworkProviderId("networkProviderId"); + affectedCp.setProviderId("portProviderId"); + affectedCp.setServerProviderId("serverProviderId"); + affectedCp.setTenantId("tenantId"); + affectedConnectionPoints.getPost().add(affectedCp); + + OperationResult operationResult = new OperationResult(); + operationResult.operationResult = affectedConnectionPoints; + JsonElement additionalData = new Gson().toJsonTree(operationResult); + instantiationOperation.setAdditionalData(additionalData); + //when + vfcNotificationSender.processNotification(recievedLcn, terminationOperation, affectedConnectionPoints, VIM_ID); + //verify + assertEquals(1, sentLcnToVfc.getAllValues().size()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVl().size()); + org.onap.vnfmdriver.model.AffectedVirtualLink actualAffectedVl = sentLcnToVfc.getValue().getAffectedVl().get(0); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.REMOVED, actualAffectedVl.getChangeType()); + assertEquals("vlVnfdId", actualAffectedVl.getVldid()); + assertEquals("myVnfId_vlId", actualAffectedVl.getVlInstanceId()); + assertEquals("networkProviderId", actualAffectedVl.getNetworkResource().getResourceId()); + assertEquals(AffectedVirtualLinkType.NETWORK, actualAffectedVl.getNetworkResource().getResourceType()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVnfc().size()); + org.onap.vnfmdriver.model.AffectedVnfc actualAffectdVnfc = sentLcnToVfc.getValue().getAffectedVnfc().get(0); + assertEquals("myVduId", actualAffectdVnfc.getVduId()); + assertEquals(VIM_ID, actualAffectdVnfc.getVimid()); + assertEquals("myVmName", actualAffectdVnfc.getVmname()); + assertEquals("serverProviderId", actualAffectdVnfc.getVmid()); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.REMOVED, actualAffectdVnfc.getChangeType()); + assertEquals("myVnfId_myVnfcId", actualAffectdVnfc.getVnfcInstanceId()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedCp().size()); + AffectedCp actualAffectedCp = sentLcnToVfc.getValue().getAffectedCp().get(0); + assertEquals("cpVnfdId", actualAffectedCp.getCpdid()); + assertEquals("myVnfId_cpId", actualAffectedCp.getCpinstanceid()); + assertEquals(null, actualAffectedCp.getOwnerId()); + assertEquals(null, actualAffectedCp.getOwnerType()); + assertEquals("networkProviderId", actualAffectedCp.getVirtualLinkInstanceId()); + assertEquals("1.2.3.4", actualAffectedCp.getPortResource().getIpAddress()); + assertEquals("myMac", actualAffectedCp.getPortResource().getMacAddress()); + assertEquals("tenantId", actualAffectedCp.getPortResource().getTenant()); + assertEquals(VnfCpNotificationType.REMOVED, actualAffectedCp.getChangeType()); + assertEquals(VIM_ID, actualAffectedCp.getPortResource().getVimid()); + assertEquals("serverProviderId", actualAffectedCp.getPortResource().getInstId()); + assertEquals("portProviderId", actualAffectedCp.getPortResource().getResourceid()); + assertEquals("myPortName", actualAffectedCp.getPortResource().getResourceName()); + + assertNull(sentLcnToVfc.getValue().getAffectedVirtualStorage()); + assertEquals(JOB_ID, sentLcnToVfc.getValue().getJobId()); + assertEquals(org.onap.vnfmdriver.model.OperationType.TERMINAL, sentLcnToVfc.getValue().getOperation()); + assertEquals(VnfLcmNotificationStatus.RESULT, sentLcnToVfc.getValue().getStatus()); + assertEquals(VNF_ID, sentLcnToVfc.getValue().getVnfInstanceId()); + } + + /** + * test end notification success scenario for modifiction (heal) + * - LCN is sent to VF-C + */ + @Test + public void testFinishLcnForModification() { + //given + recievedLcn.setOperation(OperationType.HEAL); + recievedLcn.setStatus(OperationStatus.FINISHED); + AffectedVnfc affectedVnfc = new AffectedVnfc(); + affectedVnfc.setChangeType(ChangeType.MODIFIED); + affectedVnfc.setId("myVnfcId"); + affectedVnfc.setVduId("myVduId"); + affectedVnfc.setStorageResourceIds(Lists.newArrayList("storageId1")); + affectedVnfc.setComputeResource(new ResourceHandle()); + affectedVnfc.getComputeResource().setResourceId("serverProviderId"); + affectedVnfc.getComputeResource().setVimId(VIM_ID); + affectedVnfc.getComputeResource().setAdditionalData(new JsonParser().parse("{ \"name\" : \"myVmName\" } ")); + recievedLcn.setAffectedVnfcs(new ArrayList<>()); + recievedLcn.getAffectedVnfcs().add(affectedVnfc); + + AffectedVirtualLink affectedVirtualLink = new AffectedVirtualLink(); + affectedVirtualLink.setChangeType(ChangeType.MODIFIED); + affectedVirtualLink.setId("vlId"); + affectedVirtualLink.setVirtualLinkDescId("vlVnfdId"); + affectedVirtualLink.setResource(new ResourceHandle()); + affectedVirtualLink.getResource().setVimId(VIM_ID); + affectedVirtualLink.getResource().setResourceId("networkProviderId"); + recievedLcn.setAffectedVirtualLinks(new ArrayList<>()); + recievedLcn.getAffectedVirtualLinks().add(affectedVirtualLink); + + + AffectedVirtualStorage affectedStorage = new AffectedVirtualStorage(); + affectedStorage.setChangeType(ChangeType.MODIFIED); + affectedStorage.setId("storageId"); + affectedStorage.setVirtualStorageDescId("storageVnfdId"); + affectedStorage.setResource(new ResourceHandle()); + affectedStorage.getResource().setVimId(VIM_ID); + affectedStorage.getResource().setResourceId("storageProviderId"); + recievedLcn.setAffectedVirtualStorages(new ArrayList<>()); + recievedLcn.getAffectedVirtualStorages().add(affectedStorage); + + ReportedAffectedConnectionPoints affectedConnectionPoints = new ReportedAffectedConnectionPoints(); + ReportedAffectedCp affectedCp = new ReportedAffectedCp(); + affectedCp.setChangeType(ChangeType.MODIFIED); + affectedCp.setCpdId("cpVnfdId"); + affectedCp.setIpAddress("1.2.3.4"); + affectedCp.setMacAddress("myMac"); + affectedCp.setName("myPortName"); + affectedCp.setCpId("cpId"); + + // affectedCp.setEcpdId("ecpdId"); + affectedCp.setNetworkProviderId("networkProviderId"); + affectedCp.setProviderId("portProviderId"); + affectedCp.setServerProviderId("serverProviderId"); + affectedCp.setTenantId("tenantId"); + affectedConnectionPoints.getPost().add(affectedCp); + + + OperationResult operationResult = new OperationResult(); + operationResult.operationResult = affectedConnectionPoints; + JsonElement additionalData = new Gson().toJsonTree(operationResult); + instantiationOperation.setAdditionalData(additionalData); + //when + vfcNotificationSender.processNotification(recievedLcn, healOperation, affectedConnectionPoints, VIM_ID); + //verify + assertEquals(1, sentLcnToVfc.getAllValues().size()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVl().size()); + org.onap.vnfmdriver.model.AffectedVirtualLink actualAffectedVl = sentLcnToVfc.getValue().getAffectedVl().get(0); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.MODIFIED, actualAffectedVl.getChangeType()); + assertEquals("vlVnfdId", actualAffectedVl.getVldid()); + assertEquals("myVnfId_vlId", actualAffectedVl.getVlInstanceId()); + assertEquals("networkProviderId", actualAffectedVl.getNetworkResource().getResourceId()); + assertEquals(AffectedVirtualLinkType.NETWORK, actualAffectedVl.getNetworkResource().getResourceType()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVnfc().size()); + org.onap.vnfmdriver.model.AffectedVnfc actualAffectdVnfc = sentLcnToVfc.getValue().getAffectedVnfc().get(0); + assertEquals("myVduId", actualAffectdVnfc.getVduId()); + assertEquals(VIM_ID, actualAffectdVnfc.getVimid()); + assertEquals("myVmName", actualAffectdVnfc.getVmname()); + assertEquals("serverProviderId", actualAffectdVnfc.getVmid()); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.MODIFIED, actualAffectdVnfc.getChangeType()); + assertEquals("myVnfId_myVnfcId", actualAffectdVnfc.getVnfcInstanceId()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedCp().size()); + AffectedCp actualAffectedCp = sentLcnToVfc.getValue().getAffectedCp().get(0); + assertEquals("cpVnfdId", actualAffectedCp.getCpdid()); + assertEquals("myVnfId_cpId", actualAffectedCp.getCpinstanceid()); + assertEquals(null, actualAffectedCp.getOwnerId()); + assertEquals(null, actualAffectedCp.getOwnerType()); + assertEquals("networkProviderId", actualAffectedCp.getVirtualLinkInstanceId()); + assertEquals("1.2.3.4", actualAffectedCp.getPortResource().getIpAddress()); + assertEquals("myMac", actualAffectedCp.getPortResource().getMacAddress()); + assertEquals("tenantId", actualAffectedCp.getPortResource().getTenant()); + assertEquals(VIM_ID, actualAffectedCp.getPortResource().getVimid()); + assertEquals("serverProviderId", actualAffectedCp.getPortResource().getInstId()); + assertEquals("portProviderId", actualAffectedCp.getPortResource().getResourceid()); + assertEquals("myPortName", actualAffectedCp.getPortResource().getResourceName()); + assertEquals(VnfCpNotificationType.CHANGED, actualAffectedCp.getChangeType()); + + assertNull(sentLcnToVfc.getValue().getAffectedVirtualStorage()); + assertEquals(JOB_ID, sentLcnToVfc.getValue().getJobId()); + assertEquals(org.onap.vnfmdriver.model.OperationType.HEAL, sentLcnToVfc.getValue().getOperation()); + assertEquals(VnfLcmNotificationStatus.RESULT, sentLcnToVfc.getValue().getStatus()); + assertEquals(VNF_ID, sentLcnToVfc.getValue().getVnfInstanceId()); + } + + /** + * test end notification success scenario for scale-out + * - LCN is sent to VF-C + */ + @Test + public void testFinishLcnForScaleout() { + //given + recievedLcn.setOperation(OperationType.SCALE); + recievedLcn.setStatus(OperationStatus.FINISHED); + recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId()); + ScaleVnfRequest request = new ScaleVnfRequest(); + request.setAdditionalParams(new JsonParser().parse("{ \"jobId\" : \"" + JOB_ID + "\" }")); + request.setType(ScaleDirection.OUT); + scaleOperation.setOperationParams(request); + scaleOperation.setOperationType(OperationType.SCALE); + AffectedVnfc affectedVnfc = new AffectedVnfc(); + affectedVnfc.setChangeType(ChangeType.ADDED); + affectedVnfc.setId("myVnfcId"); + affectedVnfc.setVduId("myVduId"); + affectedVnfc.setStorageResourceIds(Lists.newArrayList("storageId1")); + affectedVnfc.setComputeResource(new ResourceHandle()); + affectedVnfc.getComputeResource().setResourceId("serverProviderId"); + affectedVnfc.getComputeResource().setVimId(VIM_ID); + affectedVnfc.getComputeResource().setAdditionalData(new JsonParser().parse("{ \"name\" : \"myVmName\" } ")); + recievedLcn.setAffectedVnfcs(new ArrayList<>()); + recievedLcn.getAffectedVnfcs().add(affectedVnfc); + + AffectedVirtualLink affectedVirtualLink = new AffectedVirtualLink(); + affectedVirtualLink.setChangeType(ChangeType.ADDED); + affectedVirtualLink.setId("vlId"); + affectedVirtualLink.setVirtualLinkDescId("vlVnfdId"); + affectedVirtualLink.setResource(new ResourceHandle()); + affectedVirtualLink.getResource().setVimId(VIM_ID); + affectedVirtualLink.getResource().setResourceId("networkProviderId"); + recievedLcn.setAffectedVirtualLinks(new ArrayList<>()); + recievedLcn.getAffectedVirtualLinks().add(affectedVirtualLink); + + + AffectedVirtualStorage affectedStorage = new AffectedVirtualStorage(); + affectedStorage.setChangeType(ChangeType.ADDED); + affectedStorage.setId("storageId"); + affectedStorage.setVirtualStorageDescId("storageVnfdId"); + affectedStorage.setResource(new ResourceHandle()); + affectedStorage.getResource().setVimId(VIM_ID); + affectedStorage.getResource().setResourceId("storageProviderId"); + recievedLcn.setAffectedVirtualStorages(new ArrayList<>()); + recievedLcn.getAffectedVirtualStorages().add(affectedStorage); + + ReportedAffectedConnectionPoints affectedConnectionPoints = new ReportedAffectedConnectionPoints(); + ReportedAffectedCp affectedCp = new ReportedAffectedCp(); + affectedCp.setChangeType(ChangeType.ADDED); + affectedCp.setCpdId("cpVnfdId"); + affectedCp.setIpAddress("1.2.3.4"); + affectedCp.setMacAddress("myMac"); + affectedCp.setName("myPortName"); + affectedCp.setCpId("cpId"); + + // affectedCp.setEcpdId("ecpdId"); + affectedCp.setNetworkProviderId("networkProviderId"); + affectedCp.setProviderId("portProviderId"); + affectedCp.setServerProviderId("serverProviderId"); + affectedCp.setTenantId("tenantId"); + affectedConnectionPoints.getPost().add(affectedCp); + + OperationResult operationResult = new OperationResult(); + operationResult.operationResult = affectedConnectionPoints; + JsonElement additionalData = new Gson().toJsonTree(operationResult); + scaleOperation.setAdditionalData(additionalData); + //when + vfcNotificationSender.processNotification(recievedLcn, scaleOperation, affectedConnectionPoints, VIM_ID); + //verify + assertEquals(1, sentLcnToVfc.getAllValues().size()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVl().size()); + org.onap.vnfmdriver.model.AffectedVirtualLink actualAffectedVl = sentLcnToVfc.getValue().getAffectedVl().get(0); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.ADDED, actualAffectedVl.getChangeType()); + assertEquals("vlVnfdId", actualAffectedVl.getVldid()); + assertEquals("myVnfId_vlId", actualAffectedVl.getVlInstanceId()); + assertEquals("networkProviderId", actualAffectedVl.getNetworkResource().getResourceId()); + assertEquals(AffectedVirtualLinkType.NETWORK, actualAffectedVl.getNetworkResource().getResourceType()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVnfc().size()); + org.onap.vnfmdriver.model.AffectedVnfc actualAffectdVnfc = sentLcnToVfc.getValue().getAffectedVnfc().get(0); + assertEquals("myVduId", actualAffectdVnfc.getVduId()); + assertEquals(VIM_ID, actualAffectdVnfc.getVimid()); + assertEquals("myVmName", actualAffectdVnfc.getVmname()); + assertEquals("serverProviderId", actualAffectdVnfc.getVmid()); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.ADDED, actualAffectdVnfc.getChangeType()); + assertEquals("myVnfId_myVnfcId", actualAffectdVnfc.getVnfcInstanceId()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedCp().size()); + AffectedCp actualAffectedCp = sentLcnToVfc.getValue().getAffectedCp().get(0); + assertEquals("cpVnfdId", actualAffectedCp.getCpdid()); + assertEquals("myVnfId_cpId", actualAffectedCp.getCpinstanceid()); + assertEquals(null, actualAffectedCp.getOwnerId()); + assertEquals(null, actualAffectedCp.getOwnerType()); + assertEquals("networkProviderId", actualAffectedCp.getVirtualLinkInstanceId()); + assertEquals("1.2.3.4", actualAffectedCp.getPortResource().getIpAddress()); + assertEquals("myMac", actualAffectedCp.getPortResource().getMacAddress()); + assertEquals("tenantId", actualAffectedCp.getPortResource().getTenant()); + assertEquals(VIM_ID, actualAffectedCp.getPortResource().getVimid()); + assertEquals("serverProviderId", actualAffectedCp.getPortResource().getInstId()); + assertEquals("portProviderId", actualAffectedCp.getPortResource().getResourceid()); + assertEquals("myPortName", actualAffectedCp.getPortResource().getResourceName()); + assertEquals(VnfCpNotificationType.ADDED, actualAffectedCp.getChangeType()); + + assertNull(sentLcnToVfc.getValue().getAffectedVirtualStorage()); + assertEquals(JOB_ID, sentLcnToVfc.getValue().getJobId()); + assertEquals(org.onap.vnfmdriver.model.OperationType.SCALEOUT, sentLcnToVfc.getValue().getOperation()); + assertEquals(VnfLcmNotificationStatus.RESULT, sentLcnToVfc.getValue().getStatus()); + assertEquals(VNF_ID, sentLcnToVfc.getValue().getVnfInstanceId()); + } + + /** + * test end notification success scenario for scale-out + * - LCN is sent to VF-C + */ + @Test + public void testFinishLcnForScaleIn() { + //given + recievedLcn.setOperation(OperationType.SCALE); + recievedLcn.setStatus(OperationStatus.FINISHED); + recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId()); + ScaleVnfRequest request = new ScaleVnfRequest(); + request.setAdditionalParams(new JsonParser().parse("{ \"jobId\" : \"" + JOB_ID + "\" }")); + request.setType(ScaleDirection.IN); + scaleOperation.setOperationParams(request); + AffectedVnfc affectedVnfc = new AffectedVnfc(); + affectedVnfc.setChangeType(ChangeType.REMOVED); + affectedVnfc.setId("myVnfcId"); + affectedVnfc.setVduId("myVduId"); + affectedVnfc.setStorageResourceIds(Lists.newArrayList("storageId1")); + affectedVnfc.setComputeResource(new ResourceHandle()); + affectedVnfc.getComputeResource().setResourceId("serverProviderId"); + affectedVnfc.getComputeResource().setVimId(VIM_ID); + affectedVnfc.getComputeResource().setAdditionalData(new JsonParser().parse("{ \"name\" : \"myVmName\" } ")); + recievedLcn.setAffectedVnfcs(new ArrayList<>()); + recievedLcn.getAffectedVnfcs().add(affectedVnfc); + + AffectedVirtualLink affectedVirtualLink = new AffectedVirtualLink(); + affectedVirtualLink.setChangeType(ChangeType.REMOVED); + affectedVirtualLink.setId("vlId"); + affectedVirtualLink.setVirtualLinkDescId("vlVnfdId"); + affectedVirtualLink.setResource(new ResourceHandle()); + affectedVirtualLink.getResource().setVimId(VIM_ID); + affectedVirtualLink.getResource().setResourceId("networkProviderId"); + recievedLcn.setAffectedVirtualLinks(new ArrayList<>()); + recievedLcn.getAffectedVirtualLinks().add(affectedVirtualLink); + + + AffectedVirtualStorage affectedStorage = new AffectedVirtualStorage(); + affectedStorage.setChangeType(ChangeType.REMOVED); + affectedStorage.setId("storageId"); + affectedStorage.setVirtualStorageDescId("storageVnfdId"); + affectedStorage.setResource(new ResourceHandle()); + affectedStorage.getResource().setVimId(VIM_ID); + affectedStorage.getResource().setResourceId("storageProviderId"); + recievedLcn.setAffectedVirtualStorages(new ArrayList<>()); + recievedLcn.getAffectedVirtualStorages().add(affectedStorage); + + ReportedAffectedConnectionPoints affectedConnectionPoints = new ReportedAffectedConnectionPoints(); + ReportedAffectedCp affectedCp = new ReportedAffectedCp(); + affectedCp.setChangeType(ChangeType.REMOVED); + affectedCp.setCpdId("cpVnfdId"); + affectedCp.setIpAddress("1.2.3.4"); + affectedCp.setMacAddress("myMac"); + affectedCp.setName("myPortName"); + affectedCp.setCpId("cpId"); + + // affectedCp.setEcpdId("ecpdId"); + affectedCp.setNetworkProviderId("networkProviderId"); + affectedCp.setProviderId("portProviderId"); + affectedCp.setServerProviderId("serverProviderId"); + affectedCp.setTenantId("tenantId"); + affectedConnectionPoints.getPost().add(affectedCp); + + + OperationResult operationResult = new OperationResult(); + operationResult.operationResult = affectedConnectionPoints; + JsonElement additionalData = new Gson().toJsonTree(operationResult); + scaleOperation.setAdditionalData(additionalData); + scaleOperation.setOperationType(OperationType.SCALE); + //when + vfcNotificationSender.processNotification(recievedLcn, scaleOperation, affectedConnectionPoints, VIM_ID); + //verify + assertEquals(1, sentLcnToVfc.getAllValues().size()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVl().size()); + org.onap.vnfmdriver.model.AffectedVirtualLink actualAffectedVl = sentLcnToVfc.getValue().getAffectedVl().get(0); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.REMOVED, actualAffectedVl.getChangeType()); + assertEquals("vlVnfdId", actualAffectedVl.getVldid()); + assertEquals("myVnfId_vlId", actualAffectedVl.getVlInstanceId()); + assertEquals("networkProviderId", actualAffectedVl.getNetworkResource().getResourceId()); + assertEquals(AffectedVirtualLinkType.NETWORK, actualAffectedVl.getNetworkResource().getResourceType()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedVnfc().size()); + org.onap.vnfmdriver.model.AffectedVnfc actualAffectdVnfc = sentLcnToVfc.getValue().getAffectedVnfc().get(0); + assertEquals("myVduId", actualAffectdVnfc.getVduId()); + assertEquals(VIM_ID, actualAffectdVnfc.getVimid()); + assertEquals("myVmName", actualAffectdVnfc.getVmname()); + assertEquals("serverProviderId", actualAffectdVnfc.getVmid()); + assertEquals(org.onap.vnfmdriver.model.VnfNotificationType.REMOVED, actualAffectdVnfc.getChangeType()); + assertEquals("myVnfId_myVnfcId", actualAffectdVnfc.getVnfcInstanceId()); + + assertEquals(1, sentLcnToVfc.getValue().getAffectedCp().size()); + AffectedCp actualAffectedCp = sentLcnToVfc.getValue().getAffectedCp().get(0); + assertEquals("cpVnfdId", actualAffectedCp.getCpdid()); + assertEquals("myVnfId_cpId", actualAffectedCp.getCpinstanceid()); + assertEquals(null, actualAffectedCp.getOwnerId()); + assertEquals(null, actualAffectedCp.getOwnerType()); + assertEquals("networkProviderId", actualAffectedCp.getVirtualLinkInstanceId()); + assertEquals("1.2.3.4", actualAffectedCp.getPortResource().getIpAddress()); + assertEquals("myMac", actualAffectedCp.getPortResource().getMacAddress()); + assertEquals("tenantId", actualAffectedCp.getPortResource().getTenant()); + assertEquals(VIM_ID, actualAffectedCp.getPortResource().getVimid()); + assertEquals("serverProviderId", actualAffectedCp.getPortResource().getInstId()); + assertEquals("portProviderId", actualAffectedCp.getPortResource().getResourceid()); + assertEquals("myPortName", actualAffectedCp.getPortResource().getResourceName()); + assertEquals(VnfCpNotificationType.REMOVED, actualAffectedCp.getChangeType()); + + assertNull(sentLcnToVfc.getValue().getAffectedVirtualStorage()); + assertEquals(JOB_ID, sentLcnToVfc.getValue().getJobId()); + assertEquals(org.onap.vnfmdriver.model.OperationType.SCALEIN, sentLcnToVfc.getValue().getOperation()); + assertEquals(VnfLcmNotificationStatus.RESULT, sentLcnToVfc.getValue().getStatus()); + assertEquals(VNF_ID, sentLcnToVfc.getValue().getVnfInstanceId()); + } + + /** + * Unable to send notification to VF-C results in error + */ + @Test + public void testUnableToSendNotificationToVfc() throws Exception { + ApiException expectedException = new ApiException(); + doThrow(expectedException).when(nsLcmApi).vNFLCMNotification(any(), any(), any()); + recievedLcn.setStatus(OperationStatus.STARTED); + recievedLcn.setOperation(OperationType.INSTANTIATE); + //when + try { + vfcNotificationSender.processNotification(recievedLcn, instantiationOperation, affectedCp, VIM_ID); + //verify + fail(); + } catch (Exception e) { + verify(logger).error("Unable to send LCN to VF-C", expectedException); + assertEquals(expectedException, e.getCause()); + } + } + + class OperationResult { + ReportedAffectedConnectionPoints operationResult; + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcPackageProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcPackageProvider.java new file mode 100644 index 00000000..62ffdb4f --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcPackageProvider.java @@ -0,0 +1,156 @@ +/* + * 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.vfc; + +import org.apache.http.HttpHeaders; +import org.apache.http.client.methods.HttpGet; +import org.junit.Assert; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.IpMappingProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.onap.vfccatalog.ApiException; +import org.onap.vfccatalog.model.VnfPkgDetailInfo; +import org.onap.vfccatalog.model.VnfPkgInfo; + +import java.io.ByteArrayInputStream; +import java.io.IOException; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.fail; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.test.util.ReflectionTestUtils.setField; + +public class TestVfcPackageProvider extends TestBase { + + private static final String CSAR_ID = "csarId"; + private static final String CBAM_VNFD_ID = "CBAM_VNFD_ID"; + @Mock + private IpMappingProvider ipMappingProvider; + + @Mock + private VfcPackageProvider vfcPackageProvider; + + + @Before + public void initMocks() throws Exception { + setField(VfcPackageProvider.class, "logger", logger); + vfcPackageProvider = new VfcPackageProvider(vfcRestApiProvider, ipMappingProvider); + } + + /** + * query CBAM VNFD identifier from VF-C catalog + */ + @Test + public void testGetCbamVnfd() throws Exception { + VnfPkgDetailInfo vnfPackageDetails = new VnfPkgDetailInfo(); + vnfPackageDetails.setCsarId(CSAR_ID); + vnfPackageDetails.setPackageInfo(new VnfPkgInfo()); + vnfPackageDetails.getPackageInfo().setVnfdModel("{ \"metadata\" : { \"resourceVendorModelNumber\" : \"" + CBAM_VNFD_ID + "\" }}"); + vnfPackageDetails.getPackageInfo().setDownloadUrl("http://127.0.0.1/a.csar"); + when(vfcCatalogApi.queryVnfPackage(CSAR_ID)).thenReturn(vnfPackageDetails); + //when + String cbamVnfdId = vfcPackageProvider.getCbamVnfdId(CSAR_ID); + //verify + assertEquals(CBAM_VNFD_ID, cbamVnfdId); + } + + /** + * download ONAP VNFD from VF-C catalog + */ + @Test + public void testDownload() throws Exception { + VnfPkgDetailInfo vnfPackageDetails = new VnfPkgDetailInfo(); + vnfPackageDetails.setCsarId(CSAR_ID); + vnfPackageDetails.setPackageInfo(new VnfPkgInfo()); + vnfPackageDetails.getPackageInfo().setVnfdModel("{ \"metadata\" : { \"resourceVendorModelNumber\" : \"" + CBAM_VNFD_ID + "\" }}"); + vnfPackageDetails.getPackageInfo().setDownloadUrl("http://127.0.0.1/a.csar"); + when(vfcCatalogApi.queryVnfPackage(CSAR_ID)).thenReturn(vnfPackageDetails); + byte[] onapPackageContent = TestUtil.loadFile("unittests/TestCbamCatalogManager.sample.csar"); + when(ipMappingProvider.mapPrivateIpToPublicIp("127.0.0.1")).thenReturn("1.2.3.4"); + when(entity.getContent()).thenReturn(new ByteArrayInputStream(onapPackageContent)); + //when + byte[] actualContent = vfcPackageProvider.getPackage(CSAR_ID); + //verify + Assert.assertArrayEquals(onapPackageContent, actualContent); + assertEquals(HttpGet.class, request.getValue().getClass()); + assertEquals("http://1.2.3.4/a.csar", request.getValue().getURI().toString()); + assertEquals("application/octet-stream", request.getValue().getFirstHeader(HttpHeaders.ACCEPT).getValue()); + } + + /** + * failure to query package from VF-C is propagated + */ + @Test + public void unableToGetCbamVnfdFromCatalog() throws Exception { + ApiException expectedException = new ApiException(); + when(vfcCatalogApi.queryVnfPackage(CSAR_ID)).thenThrow(expectedException); + //when + try { + vfcPackageProvider.getCbamVnfdId(CSAR_ID); + fail(); + } catch (Exception e) { + verify(logger).error("Unable to query VNF package with csarId from VF-C", expectedException); + assertEquals(expectedException, e.getCause()); + } + } + + /** + * failure to download package from VF-C is propagated + */ + @Test + public void unableToDownloadFromCatalog() throws Exception { + VnfPkgDetailInfo vnfPackageDetails = new VnfPkgDetailInfo(); + vnfPackageDetails.setCsarId(CSAR_ID); + vnfPackageDetails.setPackageInfo(new VnfPkgInfo()); + vnfPackageDetails.getPackageInfo().setVnfdModel("{ \"metadata\" : { \"resourceVendorModelNumber\" : \"" + CBAM_VNFD_ID + "\" }}"); + vnfPackageDetails.getPackageInfo().setDownloadUrl("http://127.0.0.1/a.csar"); + when(vfcCatalogApi.queryVnfPackage(CSAR_ID)).thenReturn(vnfPackageDetails); + byte[] onapPackageContent = TestUtil.loadFile("unittests/TestCbamCatalogManager.sample.csar"); + when(ipMappingProvider.mapPrivateIpToPublicIp("127.0.0.1")).thenReturn("1.2.3.4"); + IOException expectedException = new IOException(); + when(httpClient.execute(Mockito.any())).thenThrow(expectedException); + //when + try { + vfcPackageProvider.getPackage(CSAR_ID); + fail(); + } catch (Exception e) { + verify(logger).error("Unable to download package from http://1.2.3.4/a.csar from VF-C", expectedException); + assertEquals(expectedException, e.getCause()); + } + } + + /** + * failure to query package for download package from VF-C is propagated + */ + @Test + public void unableToQueryPackageForDownloadFromCatalog() throws Exception { + ApiException expectedException = new ApiException(); + when(vfcCatalogApi.queryVnfPackage(CSAR_ID)).thenThrow(expectedException); + //when + try { + vfcPackageProvider.getPackage(CSAR_ID); + fail(); + } catch (Exception e) { + verify(logger).error("Unable to query VNF package with csarId from VF-C", expectedException); + assertEquals(expectedException, e.getCause()); + } + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcRestApiProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcRestApiProvider.java new file mode 100644 index 00000000..a527b568 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/onap/vfc/TestVfcRestApiProvider.java @@ -0,0 +1,64 @@ +/* + * 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.vfc; + +import org.junit.Before; +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.onap.vfccatalog.api.VnfpackageApi; +import org.onap.vnfmdriver.api.NslcmApi; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertNull; +import static org.mockito.Mockito.when; + +public class TestVfcRestApiProvider extends TestBase { + private VfcRestApiProvider vfcRestApiProvider; + + @Before + public void init() { + vfcRestApiProvider = new VfcRestApiProvider(msbApiProvider); + } + + /** + * test VF-C NSLCM API retrieval + */ + @Test + public void testNsLcmApi() throws Exception { + when(msbApiProvider.getMicroServiceUrl(VfcRestApiProvider.NSLCM_API_SERVICE_NAME, VfcRestApiProvider.NSLCM_API_VERION)).thenReturn("http://1.2.3.4:1234/nslcm/v1/lead"); + //when + NslcmApi nsLcmApi = vfcRestApiProvider.getNsLcmApi(); + //verify + assertEquals("http://1.2.3.4:1234/lead", nsLcmApi.getApiClient().getBasePath()); + assertNull(nsLcmApi.getApiClient().getSslCaCert()); + assertEquals(0, nsLcmApi.getApiClient().getAuthentications().size()); + } + + /** + * test VF-C catalog API retrieval + */ + @Test + public void testNsCatalogApi() throws Exception { + when(msbApiProvider.getMicroServiceUrl(VfcRestApiProvider.NSCATALOG_SERVICE_NAME, VfcRestApiProvider.NSCATALOG_API_VERSION)).thenReturn("http://1.2.3.4:1234/lead"); + //when + VnfpackageApi nsCatalogApi = vfcRestApiProvider.getOnapCatalogApi(); + //verify + assertEquals("http://1.2.3.4:1234/lead", nsCatalogApi.getApiClient().getBasePath()); + assertNull(nsCatalogApi.getApiClient().getSslCaCert()); + assertEquals(0, nsCatalogApi.getApiClient().getAuthentications().size()); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestCbamVnfPackageBuilder.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestCbamVnfPackageBuilder.java new file mode 100644 index 00000000..3b80eca0 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestCbamVnfPackageBuilder.java @@ -0,0 +1,54 @@ +/* + * 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.packagetransformer; + +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; + +import static org.mockito.Mockito.when; + + +public class TestCbamVnfPackageBuilder extends TestBase { + private CbamVnfPackageBuilder cbamVnfPackageBuilder = new CbamVnfPackageBuilder(); + + /** + * + */ + @Test + public void testEmpty() throws Exception { + byte[] zipContent = TestUtil.loadFile("unittests/packageconverter/cbam.package.zip"); + when(systemFunctions.loadFile("cbam.pre.collectConnectionPoints.js")).thenCallRealMethod(); + when(systemFunctions.loadFile("cbam.post.collectConnectionPoints.js")).thenCallRealMethod(); + when(systemFunctions.loadFile("cbam.collectConnectionPoints.js")).thenCallRealMethod(); + + //when + byte[] modifiedContent = cbamVnfPackageBuilder.toModifiedCbamVnfPackage(zipContent, "vnfdloc/a.yaml", "modifiedContent"); + //verify + assertFileInZip(modifiedContent, "keep/me", "kuku\n".getBytes()); + assertFileInZip(modifiedContent, "TOSCA-Metadata/TOSCA.meta", ("TOSCA-Meta-File-Version: 1.0\n" + + "CSAR-Version: 1.1\n" + + "Created-By: Nokia\n" + + "Entry-Definitions: vnfdloc/a.yaml\n").getBytes()); + assertFileInZip(modifiedContent, "javascript/cbam.pre.collectConnectionPoints.js", TestUtil.loadFile("cbam.pre.collectConnectionPoints.js")); + assertFileInZip(modifiedContent, "javascript/cbam.post.collectConnectionPoints.js", TestUtil.loadFile("cbam.post.collectConnectionPoints.js")); + assertFileInZip(modifiedContent, "javascript/cbam.collectConnectionPoints.js", TestUtil.loadFile("cbam.collectConnectionPoints.js")); + + + } + + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestCbamVnfdBuilder.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestCbamVnfdBuilder.java new file mode 100644 index 00000000..5840ef4e --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestCbamVnfdBuilder.java @@ -0,0 +1,47 @@ +/* + * 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.packagetransformer; + +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; + +import static junit.framework.TestCase.assertEquals; + + +public class TestCbamVnfdBuilder extends TestBase { + private CbamVnfdBuilder packageTransformer = new CbamVnfdBuilder(); + + /** + * test package conversion on the most mininal VNFD possible + */ + @Test + public void testEmpty() throws Exception { + String out = packageTransformer.build(new String(TestUtil.loadFile("unittests/packageconverter/cbam.minimal.original.vnfd.yaml"))); + String expected = new String(TestUtil.loadFile("unittests/packageconverter/cbam.minimal.modified.vnfd.yaml")); + assertEquals(expected, out); + } + + /** + * test package conversion on the most full VNFD possible + */ + @Test + public void testFull() throws Exception { + String out = packageTransformer.build(new String(TestUtil.loadFile("unittests/packageconverter/cbam.full.original.vnfd.yaml"))); + String expected = new String(TestUtil.loadFile("unittests/packageconverter/cbam.full.modified.vnfd.yaml")); + assertEquals(expected, out); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestOnapVnfPackageBuilder.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestOnapVnfPackageBuilder.java new file mode 100644 index 00000000..9c9f7958 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestOnapVnfPackageBuilder.java @@ -0,0 +1,74 @@ +/* + * 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.packagetransformer; + +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; + +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; + +import static junit.framework.TestCase.assertEquals; +import static org.mockito.Mockito.when; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager.getFileInZip; + + +public class TestOnapVnfPackageBuilder extends TestBase { + + /** + * The the main reads from standard in and writes to standard out + */ + @Test + public void testInputStreams() throws Exception { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + PrintStream actualOut = new PrintStream(bos, true); + when(systemFunctions.out()).thenReturn(actualOut); + when(systemFunctions.in()).thenReturn(new ByteArrayInputStream(TestUtil.loadFile("unittests/packageconverter/cbam.package.zip"))); + when(systemFunctions.loadFile("cbam.pre.collectConnectionPoints.js")).thenCallRealMethod(); + when(systemFunctions.loadFile("cbam.collectConnectionPoints.js")).thenCallRealMethod(); + when(systemFunctions.loadFile("cbam.post.collectConnectionPoints.js")).thenCallRealMethod(); + when(systemFunctions.loadFile("TOSCA.meta")).thenCallRealMethod(); + when(systemFunctions.loadFile("MainServiceTemplate.meta")).thenCallRealMethod(); + + + String cbamVnfd = new String(TestUtil.loadFile("unittests/packageconverter/cbam.package.zip.vnfd")); + String expectedOnapVnfd = new OnapVnfdBuilder().toOnapVnfd(cbamVnfd); + + //when + OnapVnfPackageBuilder.main(null); + //verify + assertFileInZip(bos.toByteArray(), "TOSCA-Metadata/TOSCA.meta", TestUtil.loadFile("TOSCA.meta")); + assertFileInZip(bos.toByteArray(), "Definitions/MainServiceTemplate.yaml", expectedOnapVnfd.getBytes()); + assertFileInZip(bos.toByteArray(), "MainServiceTemplate.yaml", expectedOnapVnfd.getBytes()); + assertFileInZip(bos.toByteArray(), "MainServiceTemplate.meta", TestUtil.loadFile("MainServiceTemplate.meta")); + ByteArrayOutputStream actualModifiedCbamVnfPackage = getFileInZip(new ByteArrayInputStream(bos.toByteArray()), "Artifacts/Deployment/OTHER/cbam.package.zip"); + byte[] expectedModifiedCbamPackage = new CbamVnfPackageBuilder().toModifiedCbamVnfPackage(TestUtil.loadFile("unittests/packageconverter/cbam.package.zip"), "vnfdloc/a.yaml", new CbamVnfdBuilder().build(cbamVnfd)); + assertItenticalZips(expectedModifiedCbamPackage, actualModifiedCbamVnfPackage.toByteArray()); + } + + + /** + * Prevents moving the class (customer documentation) must be updated + */ + @Test + public void testPreventMove() { + assertEquals("org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.OnapVnfPackageBuilder", OnapVnfPackageBuilder.class.getCanonicalName()); + } + + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestOnapVnfdBuilder.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestOnapVnfdBuilder.java new file mode 100644 index 00000000..1edf5eca --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/TestOnapVnfdBuilder.java @@ -0,0 +1,60 @@ +/* + * 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.packagetransformer; + +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; + +import java.util.NoSuchElementException; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.fail; + + +public class TestOnapVnfdBuilder extends TestBase { + private OnapVnfdBuilder packageTransformer = new OnapVnfdBuilder(); + + /** + * Test empty VNFD conversion + */ + @Test + public void testEmpty() { + assertEquals(new String(TestUtil.loadFile("unittests/packageconverter/empty.vnfd.onap.yaml")), packageTransformer.toOnapVnfd(new String(TestUtil.loadFile("unittests/packageconverter/empty.vnfd.cbam.yaml")))); + } + + /** + * Test all Tosca nodes conversions for successful scenario + */ + @Test + public void testNodes() { + assertEquals(new String(TestUtil.loadFile("unittests/packageconverter/nodes.vnfd.onap.yaml")), packageTransformer.toOnapVnfd(new String(TestUtil.loadFile("unittests/packageconverter/nodes.vnfd.cbam.yaml")))); + } + + /** + * if a node refers to a non existing node it results in a failure + */ + @Test + public void testInconsitentVnfd() { + try { + packageTransformer.toOnapVnfd(new String(TestUtil.loadFile("unittests/packageconverter/nodes.vnfd.inconsistent.cbam.yaml"))); + fail(); + } catch (NoSuchElementException e) { + assertEquals("The VNFD does not have a node called myComputeMissing but required by an other node", e.getMessage()); + } + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestConverterApi.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestConverterApi.java new file mode 100644 index 00000000..9ac38914 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestConverterApi.java @@ -0,0 +1,114 @@ +/* + * 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 com.google.common.collect.Lists; +import junit.framework.TestCase; +import org.apache.http.entity.ContentType; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.CbamVnfPackageBuilder; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.CbamVnfdBuilder; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer.OnapVnfdBuilder; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.springframework.http.HttpHeaders; +import org.springframework.http.HttpStatus; +import org.springframework.mock.web.DelegatingServletOutputStream; + +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.Part; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.PrintStream; +import java.util.Arrays; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager.getFileInZip; +import static org.springframework.test.util.ReflectionTestUtils.setField; + + +public class TestConverterApi extends TestBase { + + + @InjectMocks + private ConverterApi converterApi; + @Mock + private HttpServletRequest httpRequest; + + @Before + public void initMocks() throws Exception { + setField(ConverterApi.class, "logger", logger); + } + + /** + */ + @Test + public void test() throws Exception { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + PrintStream actualOut = new PrintStream(bos, true); + when(systemFunctions.out()).thenReturn(actualOut); + when(systemFunctions.loadFile("cbam.pre.collectConnectionPoints.js")).thenCallRealMethod(); + when(systemFunctions.loadFile("cbam.collectConnectionPoints.js")).thenCallRealMethod(); + when(systemFunctions.loadFile("cbam.post.collectConnectionPoints.js")).thenCallRealMethod(); + when(systemFunctions.loadFile("TOSCA.meta")).thenCallRealMethod(); + when(systemFunctions.loadFile("MainServiceTemplate.meta")).thenCallRealMethod(); + when(httpResponse.getOutputStream()).thenReturn(new DelegatingServletOutputStream(actualOut)); + Part part = Mockito.mock(Part.class); + when(part.getInputStream()).thenReturn(new ByteArrayInputStream(TestUtil.loadFile("unittests/packageconverter/cbam.package.zip"))); + when(httpRequest.getParts()).thenReturn(Lists.newArrayList(part)); + //when + converterApi.convert(httpResponse, httpRequest); + //verify + verifyVnfPackageWritterToOutputStream(bos); + verify(httpResponse).addHeader(HttpHeaders.CONTENT_TYPE, ContentType.APPLICATION_OCTET_STREAM.getMimeType()); + verify(httpResponse).setStatus(HttpStatus.OK.value()); + verify(httpResponse).addHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(bos.toByteArray().length)); + verify(httpResponse).addHeader(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + "core.csar" + "\""); + } + + private void verifyVnfPackageWritterToOutputStream(ByteArrayOutputStream bos) throws Exception { + String cbamVnfd = new String(TestUtil.loadFile("unittests/packageconverter/cbam.package.zip.vnfd")); + String expectedOnapVnfd = new OnapVnfdBuilder().toOnapVnfd(cbamVnfd); + assertFileInZip(bos.toByteArray(), "TOSCA-Metadata/TOSCA.meta", TestUtil.loadFile("TOSCA.meta")); + assertFileInZip(bos.toByteArray(), "Definitions/MainServiceTemplate.yaml", expectedOnapVnfd.getBytes()); + assertFileInZip(bos.toByteArray(), "MainServiceTemplate.yaml", expectedOnapVnfd.getBytes()); + assertFileInZip(bos.toByteArray(), "MainServiceTemplate.meta", TestUtil.loadFile("MainServiceTemplate.meta")); + ByteArrayOutputStream actualModifiedCbamVnfPackage = getFileInZip(new ByteArrayInputStream(bos.toByteArray()), "Artifacts/Deployment/OTHER/cbam.package.zip"); + byte[] expectedModifiedCbamPackage = new CbamVnfPackageBuilder().toModifiedCbamVnfPackage(TestUtil.loadFile("unittests/packageconverter/cbam.package.zip"), "vnfdloc/a.yaml", new CbamVnfdBuilder().build(cbamVnfd)); + assertItenticalZips(expectedModifiedCbamPackage, actualModifiedCbamVnfPackage.toByteArray()); + } + + @Test + public void testDownloaderPage() throws Exception { + ByteArrayOutputStream bos = new ByteArrayOutputStream(); + PrintStream actualOut = new PrintStream(bos, true); + when(httpResponse.getOutputStream()).thenReturn(new DelegatingServletOutputStream(actualOut)); + when(systemFunctions.loadFile("upload.html")).thenCallRealMethod(); + //when + converterApi.getUploadPageForConvertingVnfd(httpResponse); + //verify + TestCase.assertTrue(Arrays.equals(TestUtil.loadFile("upload.html"), bos.toByteArray())); + verify(httpResponse).addHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(bos.toByteArray().length)); + + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestLcmApi.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestLcmApi.java new file mode 100644 index 00000000..1fdeb323 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestLcmApi.java @@ -0,0 +1,130 @@ +/* + * 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 org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +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.vnfmdriver.model.VnfHealRequest; +import org.onap.vnfmdriver.model.VnfInstantiateRequest; +import org.onap.vnfmdriver.model.VnfScaleRequest; +import org.onap.vnfmdriver.model.VnfTerminateRequest; + +import static org.apache.http.HttpStatus.SC_CREATED; +import static org.mockito.Mockito.verify; +import static org.springframework.test.util.ReflectionTestUtils.setField; + + +public class TestLcmApi extends TestBase { + + @Mock + private LifecycleManager lifecycleManager; + @Mock + private JobManager jobManager; + @InjectMocks + private LcmApi lcmApi; + + @Before + public void initMocks() throws Exception { + setField(LcmApi.class, "logger", logger); + } + + /** + * test instantiation handled by LCM + */ + @Test + public void testInstantiation() { + VnfInstantiateRequest req = new VnfInstantiateRequest(); + //when + lcmApi.instantiateVnf(req, VNFM_ID, httpResponse); + //verify + verify(lifecycleManager).instantiate(VNFM_ID, req, httpResponse); + verify(httpResponse).setStatus(SC_CREATED); + verify(logger).info("REST: Instantiate VNF"); + } + + /** + * test heal handled by LCM + */ + @Test + public void testHeal() { + VnfHealRequest req = new VnfHealRequest(); + //when + lcmApi.healVnf(req, VNFM_ID, VNF_ID, httpResponse); + //verify + verify(lifecycleManager).healVnf(VNFM_ID, VNF_ID, req, httpResponse); + verify(logger).info("REST: Heal VNF"); + } + + /** + * test query handled by LCM + */ + @Test + public void testQuery() { + //when + lcmApi.queryVnf(VNFM_ID, VNF_ID, httpResponse); + //verify + verify(lifecycleManager).queryVnf(VNFM_ID, VNF_ID); + verify(logger).info("REST: Query VNF"); + + } + + /** + * test scale handled by LCM + */ + @Test + public void testScale() { + VnfScaleRequest req = new VnfScaleRequest(); + //when + lcmApi.scaleVnf(req, VNFM_ID, VNF_ID, httpResponse); + //verify + verify(lifecycleManager).scaleVnf(VNFM_ID, VNF_ID, req, httpResponse); + verify(logger).info("REST: Scale VNF"); + + } + + /** + * test terminate handled by LCM + */ + @Test + public void testTerminate() { + VnfTerminateRequest req = new VnfTerminateRequest(); + //when + lcmApi.terminateVnf(req, VNFM_ID, VNF_ID, httpResponse); + //verify + verify(lifecycleManager).terminateVnf(VNFM_ID, VNF_ID, req, httpResponse); + verify(logger).info("REST: Terminate VNF"); + + } + + /** + * test job query handled by job manager + */ + @Test + public void testJob() { + //when + lcmApi.getJob(VNFM_ID, JOB_ID, httpResponse); + //verify + verify(jobManager).getJob(VNFM_ID, JOB_ID); + verify(logger).debug("REST: Query job"); + + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestLcnApi.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestLcnApi.java new file mode 100644 index 00000000..fc6b97b4 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestLcnApi.java @@ -0,0 +1,65 @@ +/* + * 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 com.nokia.cbam.lcm.v32.model.VnfLifecycleChangeNotification; +import org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.LifecycleChangeNotificationManager; + +import static org.mockito.Mockito.verify; +import static org.springframework.test.util.ReflectionTestUtils.setField; + + +public class TestLcnApi extends TestBase { + + @Mock + private VnfLifecycleChangeNotification lcn; + @Mock + private LifecycleChangeNotificationManager lcnManager; + @InjectMocks + private LcnApi lcnApi; + + @Before + public void initMocks() throws Exception { + setField(LcnApi.class, "logger", logger); + } + + /** + * test REST "ping" from CBAM to driver + */ + @Test + public void testPing() { + lcnApi.testLcnConnectivity(null); + //verify no exception is thrown + } + + /** + * test LCN is handled by LCN manager + */ + @Test + public void testHandleLcn() { + //when + lcnApi.handleLcn(lcn, httpResponse); + //verify + verify(lcnManager).handleLcn(lcn); + verify(logger).info("REST: handle LCN"); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerApi.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerApi.java new file mode 100644 index 00000000..638f7237 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerApi.java @@ -0,0 +1,62 @@ +/* + * 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 org.junit.Before; +import org.junit.Test; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.springframework.http.HttpHeaders; +import org.springframework.http.MediaType; + +import javax.servlet.ServletOutputStream; + +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.test.util.ReflectionTestUtils.setField; + + +public class TestSwaggerApi extends TestBase { + + @InjectMocks + private SwaggerApi swaggerApi; + + + @Before + public void initMocks() throws Exception { + setField(SwaggerApi.class, "logger", logger); + } + + /** + * test swagger definition get + */ + @Test + public void testSwaggerRetrieval() throws Exception { + byte[] bytes = new byte[]{1, 2}; + when(selfRegistrationManager.getSwaggerApiDefinition()).thenReturn(bytes); + ServletOutputStream os = Mockito.mock(ServletOutputStream.class); + when(httpResponse.getOutputStream()).thenReturn(os); + //when + swaggerApi.getSwaggerApiDefinition(httpResponse); + //verify + verify(httpResponse).addHeader(HttpHeaders.CONTENT_TYPE, MediaType.APPLICATION_JSON_VALUE); + verify(httpResponse).addHeader(HttpHeaders.CONTENT_LENGTH, Integer.toString(bytes.length)); + verify(os).write(bytes); + verify(logger).info("REST: get swagger definition"); + } +} 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 new file mode 100644 index 00000000..eeb79be8 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/restapi/TestSwaggerDefinitionConsistency.java @@ -0,0 +1,82 @@ +/* + * 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 com.google.common.collect.HashMultimap; +import com.google.common.collect.Sets; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import junit.framework.TestCase; +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestMethod; + +import java.lang.reflect.Method; +import java.util.HashSet; +import java.util.NoSuchElementException; +import java.util.Set; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.child; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil.loadFile; + +public class TestSwaggerDefinitionConsistency extends TestBase { + + public static final HashSet<Class<?>> CLASSES = Sets.newHashSet(LcmApi.class, LcnApi.class, SwaggerApi.class, ConverterApi.class); + + @Test + public void test() throws Exception { + JsonObject root = new JsonParser().parse(new String(loadFile("self.swagger.json"))).getAsJsonObject(); + String basePath = root.get("basePath").getAsString(); + HashMultimap<String, RequestMethod> expectedPaths = HashMultimap.create(); + for (String pathName : child(root, "paths").keySet()) { + JsonObject path = child(child(root, "paths"), pathName); + for (String method : path.keySet()) { + locate(basePath + pathName); + expectedPaths.put(basePath + pathName, RequestMethod.valueOf(method.toUpperCase())); + } + } + + for (Class<?> clazz : CLASSES) { + RequestMapping currentBasePath = clazz.getAnnotation(RequestMapping.class); + for (Method method : clazz.getMethods()) { + RequestMapping methodMapping = method.getAnnotation(RequestMapping.class); + if (methodMapping != null) { + String fPath = currentBasePath.value()[0] + methodMapping.value()[0]; + RequestMethod restMethod = methodMapping.method()[0]; + Set<RequestMethod> currentMethods = expectedPaths.get(fPath); + if (!currentMethods.contains(restMethod)) { + TestCase.fail("Not documented REST API" + fPath + " " + restMethod + " current " + currentMethods); + } + } + } + } + } + + private void locate(String path) { + 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; + } + } + } + throw new NoSuchElementException(path); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestConditions.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestConditions.java new file mode 100644 index 00000000..f716cad6 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestConditions.java @@ -0,0 +1,66 @@ +/* + * 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.spring; + +import junit.framework.TestCase; +import org.junit.Before; +import org.junit.Test; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.env.Environment; + +import static org.mockito.Mockito.when; + +public class TestConditions { + + @Mock + private ConditionContext conditionContext; + @Mock + private Environment environment; + + private String[] activeProfiles = new String[]{"a", "b"}; + + @Before + public void init() { + MockitoAnnotations.initMocks(this); + when(conditionContext.getEnvironment()).thenReturn(environment); + when(environment.getActiveProfiles()).thenReturn(activeProfiles); + } + + /** + * if direct integration is not specified VF-C based integration is used + */ + @Test + public void testVfcBased() throws Exception { + //verify + TestCase.assertTrue(new Conditions.UseForVfc().matches(conditionContext, null)); + TestCase.assertFalse(new Conditions.UseForDirect().matches(conditionContext, null)); + } + + /** + * if direct integration is not specified VF-C based integration is used + */ + @Test + public void testDirectBased() throws Exception { + activeProfiles[1] = "direct"; + //verify + TestCase.assertFalse(new Conditions.UseForVfc().matches(conditionContext, null)); + TestCase.assertTrue(new Conditions.UseForDirect().matches(conditionContext, null)); + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestRealConfig.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestRealConfig.java new file mode 100644 index 00000000..1c92a75a --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestRealConfig.java @@ -0,0 +1,43 @@ +/* + * 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.spring; + +import com.nokia.cbam.lcm.v32.model.VnfIdentifierCreationNotification; +import com.nokia.cbam.lcm.v32.model.VnfIdentifierDeletionNotification; +import com.nokia.cbam.lcm.v32.model.VnfInfoAttributeValueChangeNotification; +import com.nokia.cbam.lcm.v32.model.VnfLifecycleChangeNotification; +import org.junit.Test; +import org.springframework.boot.autoconfigure.web.HttpMessageConverters; +import org.springframework.http.MediaType; + +public class TestRealConfig { + + /** + * test that the converter can transform the inherited classes + */ + @Test + public void test() throws Exception { + HttpMessageConverters converters = new RealConfig().customConverters(); + //verify + converters.getConverters().get(0).canRead(VnfIdentifierCreationNotification.class, MediaType.APPLICATION_JSON); + converters.getConverters().get(0).canRead(VnfIdentifierDeletionNotification.class, MediaType.APPLICATION_JSON); + converters.getConverters().get(0).canRead(VnfInfoAttributeValueChangeNotification.class, MediaType.APPLICATION_JSON); + converters.getConverters().get(0).canRead(VnfLifecycleChangeNotification.class, MediaType.APPLICATION_JSON); + converters.getConverters().get(0).canRead(String.class, MediaType.APPLICATION_JSON); + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestServletInitializer.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestServletInitializer.java new file mode 100644 index 00000000..75c68959 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/spring/TestServletInitializer.java @@ -0,0 +1,40 @@ +/* + * 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.spring; + +import org.junit.Test; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.NokiaSvnfmApplication; +import org.springframework.boot.builder.SpringApplicationBuilder; + +import static org.mockito.Mockito.verify; + +public class TestServletInitializer { + + /** + * test that the Nokia application is added to the Spring context + */ + @Test + public void testSpringBootApplicationInit() throws Exception { + SpringApplicationBuilder springApplicationBuilder = Mockito.mock(SpringApplicationBuilder.class); + //when + new ServletInitializer().configure(springApplicationBuilder); + //verify + verify(springApplicationBuilder).sources(NokiaSvnfmApplication.class); + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestCbamUtils.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestCbamUtils.java new file mode 100644 index 00000000..7f544616 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestCbamUtils.java @@ -0,0 +1,136 @@ +/* + * 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.util; + +import com.google.gson.JsonObject; +import com.google.gson.JsonPrimitive; +import org.junit.Test; +import org.mockito.Mockito; +import org.slf4j.Logger; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.fail; +import static org.mockito.Mockito.verify; + +public class TestCbamUtils { + + /** + * test child of json object + */ + @Test + public void testChild() throws Exception { + JsonObject parent = new JsonObject(); + JsonObject child = new JsonObject(); + parent.add("x", child); + assertEquals(child, CbamUtils.child(parent, "x")); + } + + /** + * if child is not a json object error is propagated + */ + @Test + public void testNonJsonObjectChild() throws Exception { + JsonObject parent = new JsonObject(); + JsonPrimitive child = new JsonPrimitive("y"); + parent.add("x", child); + try { + CbamUtils.child(parent, "x"); + fail(); + } catch (RuntimeException e) { + assertEquals("Not a JSON Object: \"y\"", e.getMessage()); + } + } + + /** + * if no child is present error is propagated + */ + @Test + public void testMissingChild() throws Exception { + JsonObject parent = new JsonObject(); + try { + CbamUtils.child(parent, "z"); + fail(); + } catch (RuntimeException e) { + assertEquals("Missing child z", e.getMessage()); + } + } + + /** + * test child of json object + */ + @Test + public void testChildElement() throws Exception { + JsonObject parent = new JsonObject(); + JsonPrimitive child = new JsonPrimitive("y"); + parent.add("x", child); + assertEquals(child, CbamUtils.childElement(parent, "x")); + } + + /** + * if no child is present error is propagated + */ + @Test + public void testMissingChildElement() throws Exception { + JsonObject parent = new JsonObject(); + try { + CbamUtils.childElement(parent, "z"); + fail(); + } catch (RuntimeException e) { + assertEquals("Missing child z", e.getMessage()); + } + } + + + /** + * test fatal failure handling + */ + @Test + public void testFatalFailure() throws Exception { + Exception expectedException = new Exception(); + Logger logger = Mockito.mock(Logger.class); + try { + CbamUtils.fatalFailure(logger, "msg", expectedException); + fail(); + } catch (RuntimeException e) { + assertEquals("msg", e.getMessage()); + assertEquals(expectedException, e.getCause()); + verify(logger).error("msg", expectedException); + } + } + + /** + * test fatal failure handling with no wrapped exception + */ + @Test + public void testFatalFailureWithNoException() throws Exception { + Logger logger = Mockito.mock(Logger.class); + try { + CbamUtils.fatalFailure(logger, "msg"); + fail(); + } catch (RuntimeException e) { + assertEquals("msg", e.getMessage()); + verify(logger).error("msg"); + } + } + + @Test + public void useStaticWay() { + TestUtil.coveragePrivateConstructorForClassesWithStaticMethodsOnly(CbamUtils.class); + } + + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestStoreLoader.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestStoreLoader.java new file mode 100644 index 00000000..2dc33f3b --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestStoreLoader.java @@ -0,0 +1,346 @@ +/* + * 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.util; + +import org.junit.BeforeClass; +import org.junit.Test; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.net.URL; +import java.security.KeyStore; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateException; +import java.util.Arrays; +import java.util.HashSet; +import java.util.Set; + +import static com.google.common.collect.Sets.newHashSet; +import static org.junit.Assert.*; + +public class TestStoreLoader { + + private static final String PASSWORD = "password"; + private static final String SUN = "SUN"; + private static final String JKS = "JKS"; + private static final String TEST_JKS = "test.jks"; + private static final String PEM_WITHOUT_BEGIN = "" + + "INVALID\n" + + "-----END RSA PRIVATE KEY-----"; + private static final String PEM_WITHOUT_END = "-----BEGIN RSA PRIVATE KEY-----\n" + + "INVALID\n" + + ""; + private static final String PEMS_WITHOUT_PRIVATE_KEY = "-----BEGIN CERTIFICATE-----\n" + + "MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL\n" + + "MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC\n" + + "VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx\n" + + "NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD\n" + + "TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu\n" + + "ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j\n" + + "V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj\n" + + "gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA\n" + + "FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE\n" + + "CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS\n" + + "BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE\n" + + "BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju\n" + + "Wm7DCfrPNGVwFWUQOmsPue9rZBgO\n" + + "-----END CERTIFICATE-----\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL\n" + + "MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC\n" + + "VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx\n" + + "NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD\n" + + "TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu\n" + + "ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j\n" + + "V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj\n" + + "gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA\n" + + "FFXI70krXeQDxZgbaCQoR4tUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE\n" + + "CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS\n" + + "BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE\n" + + "BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju\n" + + "Wm7DCfrPNGVwFWUQOmsPue9rZBgO\n" + + "-----END CERTIFICATE-----"; + private static final String PEMS = "-----BEGIN CERTIFICATE-----\n" + + "MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL\n" + + "MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC\n" + + "VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx\n" + + "NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD\n" + + "TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu\n" + + "ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j\n" + + "V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj\n" + + "gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA\n" + + "FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE\n" + + "CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS\n" + + "BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE\n" + + "BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju\n" + + "Wm7DCfrPNGVwFWUQOmsPue9rZBgO\n" + + "-----END CERTIFICATE-----\n" + + "-----BEGIN CERTIFICATE-----\n" + + "MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL\n" + + "MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC\n" + + "VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx\n" + + "NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD\n" + + "TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu\n" + + "ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j\n" + + "V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj\n" + + "gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA\n" + + "FFXI70krXeQDxZgbaCQoR4tUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE\n" + + "CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS\n" + + "BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE\n" + + "BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju\n" + + "Wm7DCfrPNGVwFWUQOmsPue9rZBgO\n" + + "-----END CERTIFICATE-----\n" + + "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAF53wUbKmDHtvfOb8u1HPqEBFNNF\n" + + "csnOMjIcSEhAwIQMbgrOuQ+vH/YgXuuDJaURS85H8P4UTt6lYOJn+SFnXvS82E7LHJpVrWwQzbh2\n" + + "QKh13/akPe90DlNTUGEYO7rHaPLqTlld0jkLFSytwqfwqn9yrYpM1ncUOpCciK5j8t8MzO71LJoJ\n" + + "g24CFxpjIS0tBrJvKzrRNcxWSRDLmu2kNmtsh7yyJouE6XoizVmBmNVltHhFaDMmqjugMQA2CZfL\n" + + "rxiR1ep8TH8IBvPqysqZI1RIpB/e0engP4/1KLrOt+6gGS0JEDh1kG2fJObl+N4n3sCOtgaz5Uz8\n" + + "8jpwbmZ3Se8CAwEAAQKCAQAdOsSs2MbavAsIM3qo/GBehO0iqdxooMpbQvECmjZ3JTlvUqNkPPWQ\n" + + "vFdiW8PsHTvtackhdLsqnNUreKxXL5rr8vqi9qm0/0mXpGNi7gP3m/FeaVdYnfpIwgCe6lag5k6M\n" + + "yv7PG/6N8+XrWyBdwlOe96bGohvB4Jp2YFjSTM67QONQ8CdmfqokqJ8/3RyrpDvGN3iX3yzBqXGO\n" + + "jPkoJQv3I4lsYdR0nl4obHHnMSeWCQCYvJoZ7ZOliu/Dd0ksItlodG6s8r/ujkSa8VIhe0fnXTf0\n" + + "i7lqa55CAByGN4MOR0bAkJwIB7nZzQKurBPcTAYJFFvAc5hgMnWT0XW83TehAoGBALVPGnznScUw\n" + + "O50OXKI5yhxGf/XDT8g28L8Oc4bctRzI+8YfIFfLJ57uDGuojO/BpqtYmXmgORru0jYR8idEkZrx\n" + + "gf62czOiJrCWTkBCEMtrNfFHQJQCQrjfbHofp7ODnEHbHFm7zdlbfNnEBBaKXxd2rVv4UTEhgftv\n" + + "wsHcimbXAoGBAIViWrHWElMeQT0datqlThE/u51mcK4VlV7iRWXVa1/gAP85ZAu44VvvDlkpYVkF\n" + + "zSRR+lHSOzsubDMN45OBQW6UA3RPg4TCvrTOmhQUeF5XPuSdcD0R2At6pdaLwAKnOtILg13Ha6ym\n" + + "Igjv8glodvem3hWLmpHIhNBiaXtf8wqpAoGADH5a8OhvKOtd8EChGXyp9LDW+HRw9vbyN/gi9dQX\n" + + "ltgyoUBb1jDllgoJSRHgRFUvyvbb/ImR5c03JwqtiQ8siWTC9G5WGeS+jcSNt9fVmG7W1L14MbrG\n" + + "Jj8fFns/7xrOlasnlPdgA+5N+CONtI/sZY2D/KZr0drhPhZBcWJlFxkCgYAn+4SOPEo/6hjKNhA6\n" + + "vER7fSxDEVsDg+rDh3YgAWpvUdlaqBxqOyAqi600YugQZGHK2lv7vNYOdmrunuIx7BPuDqY+bjtR\n" + + "R4Mc9bVQAZbXSLXMl7j2RWwKfNhLSJbk9LX4EoVtTgLjvOUE4tAdq9fFgpqdwLwzqPTO9kECP4++\n" + + "CQKBgH6tO/xcNxG/uXUideluAn3H2KeyyznZMJ7oCvzf26/XpTAMI243OoeftiKVMgxuZ7hjwqfn\n" + + "/VHXABc4i5gchr9RzSb1hZ/IqFzq2YGmbppg5Ok2cgwalDoDBi21bRf8aDRweL62mO+7aPnCQZ58\n" + + "j5W72PB8BAr6xg0Oro25O4os\n" + + "-----END RSA PRIVATE KEY-----"; + private static final String PEM = "-----BEGIN CERTIFICATE-----\n" + + "MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL\n" + + "MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC\n" + + "VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx\n" + + "NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD\n" + + "TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu\n" + + "ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j\n" + + "V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj\n" + + "gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA\n" + + "FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE\n" + + "CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS\n" + + "BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE\n" + + "BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju\n" + + "Wm7DCfrPNGVwFWUQOmsPue9rZBgO\n" + + "-----END CERTIFICATE-----\n" + + "-----BEGIN RSA PRIVATE KEY-----\n" + + "MIIEuwIBADANBgkqhkiG9w0BAQEFAASCBKUwggShAgEAAoIBAF53wUbKmDHtvfOb8u1HPqEBFNNF\n" + + "csnOMjIcSEhAwIQMbgrOuQ+vH/YgXuuDJaURS85H8P4UTt6lYOJn+SFnXvS82E7LHJpVrWwQzbh2\n" + + "QKh13/akPe90DlNTUGEYO7rHaPLqTlld0jkLFSytwqfwqn9yrYpM1ncUOpCciK5j8t8MzO71LJoJ\n" + + "g24CFxpjIS0tBrJvKzrRNcxWSRDLmu2kNmtsh7yyJouE6XoizVmBmNVltHhFaDMmqjugMQA2CZfL\n" + + "rxiR1ep8TH8IBvPqysqZI1RIpB/e0engP4/1KLrOt+6gGS0JEDh1kG2fJObl+N4n3sCOtgaz5Uz8\n" + + "8jpwbmZ3Se8CAwEAAQKCAQAdOsSs2MbavAsIM3qo/GBehO0iqdxooMpbQvECmjZ3JTlvUqNkPPWQ\n" + + "vFdiW8PsHTvtackhdLsqnNUreKxXL5rr8vqi9qm0/0mXpGNi7gP3m/FeaVdYnfpIwgCe6lag5k6M\n" + + "yv7PG/6N8+XrWyBdwlOe96bGohvB4Jp2YFjSTM67QONQ8CdmfqokqJ8/3RyrpDvGN3iX3yzBqXGO\n" + + "jPkoJQv3I4lsYdR0nl4obHHnMSeWCQCYvJoZ7ZOliu/Dd0ksItlodG6s8r/ujkSa8VIhe0fnXTf0\n" + + "i7lqa55CAByGN4MOR0bAkJwIB7nZzQKurBPcTAYJFFvAc5hgMnWT0XW83TehAoGBALVPGnznScUw\n" + + "O50OXKI5yhxGf/XDT8g28L8Oc4bctRzI+8YfIFfLJ57uDGuojO/BpqtYmXmgORru0jYR8idEkZrx\n" + + "gf62czOiJrCWTkBCEMtrNfFHQJQCQrjfbHofp7ODnEHbHFm7zdlbfNnEBBaKXxd2rVv4UTEhgftv\n" + + "wsHcimbXAoGBAIViWrHWElMeQT0datqlThE/u51mcK4VlV7iRWXVa1/gAP85ZAu44VvvDlkpYVkF\n" + + "zSRR+lHSOzsubDMN45OBQW6UA3RPg4TCvrTOmhQUeF5XPuSdcD0R2At6pdaLwAKnOtILg13Ha6ym\n" + + "Igjv8glodvem3hWLmpHIhNBiaXtf8wqpAoGADH5a8OhvKOtd8EChGXyp9LDW+HRw9vbyN/gi9dQX\n" + + "ltgyoUBb1jDllgoJSRHgRFUvyvbb/ImR5c03JwqtiQ8siWTC9G5WGeS+jcSNt9fVmG7W1L14MbrG\n" + + "Jj8fFns/7xrOlasnlPdgA+5N+CONtI/sZY2D/KZr0drhPhZBcWJlFxkCgYAn+4SOPEo/6hjKNhA6\n" + + "vER7fSxDEVsDg+rDh3YgAWpvUdlaqBxqOyAqi600YugQZGHK2lv7vNYOdmrunuIx7BPuDqY+bjtR\n" + + "R4Mc9bVQAZbXSLXMl7j2RWwKfNhLSJbk9LX4EoVtTgLjvOUE4tAdq9fFgpqdwLwzqPTO9kECP4++\n" + + "CQKBgH6tO/xcNxG/uXUideluAn3H2KeyyznZMJ7oCvzf26/XpTAMI243OoeftiKVMgxuZ7hjwqfn\n" + + "/VHXABc4i5gchr9RzSb1hZ/IqFzq2YGmbppg5Ok2cgwalDoDBi21bRf8aDRweL62mO+7aPnCQZ58\n" + + "j5W72PB8BAr6xg0Oro25O4os\n" + + "-----END RSA PRIVATE KEY-----"; + private static final String PEM_WITHOUT_PRIVATE_KEY = + "-----BEGIN CERTIFICATE-----\n" + + "MIICUTCCAfugAwIBAgIBADANBgkqhkiG9w0BAQQFADBXMQswCQYDVQQGEwJDTjEL\n" + + "MAkGA1UECBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMC\n" + + "VU4xFDASBgNVBAMTC0hlcm9uZyBZYW5nMB4XDTA1MDcxNTIxMTk0N1oXDTA1MDgx\n" + + "NDIxMTk0N1owVzELMAkGA1UEBhMCQ04xCzAJBgNVBAgTAlBOMQswCQYDVQQHEwJD\n" + + "TjELMAkGA1UEChMCT04xCzAJBgNVBAsTAlVOMRQwEgYDVQQDEwtIZXJvbmcgWWFu\n" + + "ZzBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQCp5hnG7ogBhtlynpOS21cBewKE/B7j\n" + + "V14qeyslnr26xZUsSVko36ZnhiaO/zbMOoRcKK9vEcgMtcLFuQTWDl3RAgMBAAGj\n" + + "gbEwga4wHQYDVR0OBBYEFFXI70krXeQDxZgbaCQoR4jUDncEMH8GA1UdIwR4MHaA\n" + + "FFXI70krXeQDxZgbaCQoR4jUDncEoVukWTBXMQswCQYDVQQGEwJDTjELMAkGA1UE\n" + + "CBMCUE4xCzAJBgNVBAcTAkNOMQswCQYDVQQKEwJPTjELMAkGA1UECxMCVU4xFDAS\n" + + "BgNVBAMTC0hlcm9uZyBZYW5nggEAMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQEE\n" + + "BQADQQA/ugzBrjjK9jcWnDVfGHlk3icNRq0oV7Ri32z/+HQX67aRfgZu7KWdI+Ju\n" + + "Wm7DCfrPNGVwFWUQOmsPue9rZBgO\n" + + "-----END CERTIFICATE-----"; + private static final String INVALID_CERT = + "-----BEGIN CERTIFICATE-----\n" + + "MIIC" + + "-----END CERTIFICATE-----"; + private static final String PEM_WITH_INVALID_PRIVATE_KEY = "-----BEGIN RSA PRIVATE KEY-----\n" + + "INVALID\n" + + "-----END RSA PRIVATE KEY-----"; + private static final String EMPTY_PEM = ""; + private static KeyStore testStore; + + @BeforeClass + public static void setUpBefore() throws NoSuchProviderException, KeyStoreException, CertificateException, NoSuchAlgorithmException, IOException { + testStore = KeyStore.getInstance(JKS, SUN); + ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + URL url = classLoader.getResource(TEST_JKS); + String jksFileName = url.getFile(); + File jks = new File(jksFileName); + FileInputStream fos = new FileInputStream(jks); + testStore.load(fos, PASSWORD.toCharArray()); + } + + @Test + public void useInStaticWay() { + TestUtil.coveragePrivateConstructorForClassesWithStaticMethodsOnly(StoreLoader.class); + } + + /** + * test certificate extraction from PEM + */ + @Test + public void testCertifate() { + assertEquals(new HashSet<>(), StoreLoader.getCertifacates("")); + String pem = "-----BEGIN CERTIFICATE-----\ncontent1\n-----END CERTIFICATE-----\n-----BEGIN CERTIFICATE-----\ncontent2\n-----END CERTIFICATE-----"; + Set<String> certifacates = StoreLoader.getCertifacates(pem); + assertEquals(newHashSet("-----BEGIN CERTIFICATE-----\ncontent1\n-----END CERTIFICATE-----", "-----BEGIN CERTIFICATE-----\ncontent2\n-----END CERTIFICATE-----"), certifacates); + } + + /** + * test keystore loading from PEM with single certificate & key + */ + @Test + public void loadStrore() throws Exception { + //when + KeyStore ks = StoreLoader.loadStore(PEM, PASSWORD, PASSWORD); + + //then + assertNotNull(ks.getCertificate(PASSWORD)); + assertTrue(Arrays.equals(testStore.getCertificate(PASSWORD).getPublicKey().getEncoded(), ks.getCertificate(PASSWORD).getPublicKey().getEncoded())); + } + + /** + * test keystore loading from PEM with multiple certifcates + */ + @Test + public void loadStroreWithCerts() throws Exception { + //when + KeyStore ks = StoreLoader.loadStore(PEMS, PASSWORD, PASSWORD); + + //then + assertNotNull(ks.getCertificate(PASSWORD)); + assertTrue(Arrays.equals(testStore.getCertificate(PASSWORD).getPublicKey().getEncoded(), ks.getCertificate(PASSWORD).getPublicKey().getEncoded())); + } + + /** + * test keystore loading from PEM without a private key + */ + @Test + public void loadStroreWithCertsWithoutPrivateKey() throws Exception { + //when + KeyStore ks = StoreLoader.loadStore(PEMS_WITHOUT_PRIVATE_KEY, PASSWORD, PASSWORD); + + //then + assertNotNull(ks); + String alias = PASSWORD + "0"; + assertNotNull(ks.getCertificate(alias)); + assertTrue(Arrays.equals(testStore.getCertificate(PASSWORD).getPublicKey().getEncoded(), ks.getCertificate(alias).getPublicKey().getEncoded())); + } + + /** + * non closed BEGIN CERTIFICATE pattern results in empty keystore + */ + @Test + public void loadStroreWithPemWithoutBegin() throws Exception { + //when + KeyStore ks = StoreLoader.loadStore(PEM_WITHOUT_BEGIN, PASSWORD, PASSWORD); + + //then + assertNull(ks.getCertificate(PASSWORD)); + } + + /** + * non closed END CERTIFICATE pattern results in empty keystore + */ + @Test + public void loadStroreWithPemWithoutEnd() throws Exception { + //when + KeyStore ks = StoreLoader.loadStore(PEM_WITHOUT_END, PASSWORD, PASSWORD); + + //then + assertNull(ks.getCertificate(PASSWORD)); + } + + /** + * empty PEM results in empty keystore + */ + @Test + public void loadStroreWithPemWithoutBeginAndEnd() throws Exception { + //when + KeyStore ks = StoreLoader.loadStore(EMPTY_PEM, PASSWORD, PASSWORD); + + //then + assertNull(ks.getCertificate(PASSWORD)); + } + + /** + * invalid private key results in an error + */ + @Test + public void loadStroreWithPemWithInvalidKey() throws Exception { + //when + try { + StoreLoader.loadStore(PEM_WITH_INVALID_PRIVATE_KEY, PASSWORD, PASSWORD); + fail(); + } catch (Exception e) { + assertEquals("Unable to load key", e.getMessage()); + + } + } + + /** + * invalid password results in error + */ + @Test + public void testInvlaidPassword() throws Exception { + //when + try { + StoreLoader.loadStore(PEM, null, null); + fail(); + } catch (Exception e) { + assertEquals("Unable to create keystore", e.getMessage()); + } + } + + /** + * invalid certificate results in error + */ + @Test + public void testInvlaidCertificate() throws Exception { + //when + try { + StoreLoader.loadStore(INVALID_CERT, null, null); + fail(); + } catch (Exception e) { + assertEquals("Unable to load certificates", e.getMessage()); + + } + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestSystemFunctions.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestSystemFunctions.java new file mode 100644 index 00000000..ec1ebd78 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestSystemFunctions.java @@ -0,0 +1,118 @@ +/* + * 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.util; + +import org.junit.Test; + +import java.util.Base64; +import java.util.HashSet; +import java.util.Set; + +import static org.junit.Assert.*; + +public class TestSystemFunctions { + + /** + * test sleep + */ + @Test + public void testSleep() throws Exception { + long start = System.currentTimeMillis(); + SystemFunctions.systemFunctions().sleep(123); + long end = System.currentTimeMillis(); + assertTrue(end - start >= 123); + } + + /** + * test interrupted sleep + */ + @Test + public void testInterruptedSleep() throws Exception { + long start = System.currentTimeMillis(); + Set<RuntimeException> exceptions = new HashSet<>(); + class Inter extends Thread { + @Override + public void run() { + try { + SystemFunctions.systemFunctions().sleep(10000); + } catch (RuntimeException e) { + exceptions.add(e); + } + } + } + Inter inter = new Inter(); + inter.start(); + //when + inter.interrupt(); + + //verify + while (exceptions.size() != 1) { + + } + } + + /** + * test current time + */ + @Test + public void testCurrentTime() { + long now = System.currentTimeMillis(); + long now2 = SystemFunctions.systemFunctions().currentTimeMillis(); + assertTrue(Math.abs(now2 - now) < 1000); + } + + /** + * test file load + */ + @Test + public void testFileLoad() { + byte[] bytes = SystemFunctions.systemFunctions().loadFile("unittests/empty.zip"); + assertEquals("UEsFBgAAAAAAAAAAAAAAAAAAAAAAAA==", Base64.getEncoder().encodeToString(bytes)); + } + + /** + * missing file results in error + */ + @Test + public void testMissingFileLoad() { + try { + SystemFunctions.systemFunctions().loadFile("unittests/missing"); + fail(); + } catch (Exception e) { + assertEquals("Unable to load unittests/missing", e.getMessage()); + } + } + + /** + * Test standard stream wrapping + */ + @Test + public void testStandardStreams() { + assertEquals(System.err, SystemFunctions.systemFunctions().err()); + assertEquals(System.out, SystemFunctions.systemFunctions().out()); + assertEquals(System.in, SystemFunctions.systemFunctions().in()); + } + + /** + * Test HTTP client wrapping + * (semi useless test) + */ + @Test + public void testHttp() { + assertNotNull(SystemFunctions.systemFunctions().getHttpClient()); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestUtil.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestUtil.java new file mode 100644 index 00000000..f5d9cc41 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/util/TestUtil.java @@ -0,0 +1,57 @@ +/* + * 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.util; + +import com.google.common.io.ByteStreams; + +import java.io.InputStream; +import java.lang.reflect.Constructor; + +public class TestUtil { + /** + * Due to sonar issue you have to create a private constructor for classes + * that only have static methods to prevent the creation of instances. This + * constructor can not be coveraged / tested since it is private. + * + * @param clazz + */ + public static void coveragePrivateConstructorForClassesWithStaticMethodsOnly(Class<?> clazz) { + for (Constructor<?> constructor : clazz.getDeclaredConstructors()) { + if (constructor.getParameterTypes().length == 0) { + constructor.setAccessible(true); + try { + constructor.newInstance(); + } catch (Exception e) { + throw new IllegalStateException(e); + } + } else { + throw new IllegalStateException("This should only be used if the class has a singe private constructor"); + } + } + } + + public static byte[] loadFile(String url) { + try { + InputStream stream = SystemFunctions.class.getClassLoader().getResourceAsStream(url); + byte[] bytes = ByteStreams.toByteArray(stream); + return bytes; + } catch (Exception e) { + throw new RuntimeException("Unable to load " + url, e); + } + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestAdditionalParams.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestAdditionalParams.java new file mode 100644 index 00000000..e0e90000 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestAdditionalParams.java @@ -0,0 +1,61 @@ +/* + * 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.vnfm; + +import com.google.common.collect.Maps; +import com.nokia.cbam.lcm.v32.model.NetworkAddress; +import org.junit.Test; +import pl.pojo.tester.internal.field.AbstractFieldValueChanger; +import pl.pojo.tester.internal.field.DefaultFieldValueChanger; +import pl.pojo.tester.internal.field.collections.map.AbstractMapFieldValueChanger; + +import java.util.List; +import java.util.Map; +import java.util.UUID; + +import static pl.pojo.tester.api.assertion.Assertions.assertPojoMethodsFor; + + +public class TestAdditionalParams { + + /** + * Test basic POJO behaviour + */ + @Test + public void test() { + + class MapValueChanger extends AbstractMapFieldValueChanger<Map<String, List<NetworkAddress>>> { + @Override + protected Map<String, List<NetworkAddress>> increaseValue(Map<String, List<NetworkAddress>> stringListMap, Class<?> aClass) { + if (stringListMap == null) { + return Maps.newHashMap(); + } else { + stringListMap.put(UUID.randomUUID().toString(), null); + return stringListMap; + } + } + + @Override + protected boolean canChange(Class<?> type) { + return type.getCanonicalName().contains("Map"); + } + } + + final AbstractFieldValueChanger valueChanger = new MapValueChanger().attachNext(DefaultFieldValueChanger.INSTANCE); + assertPojoMethodsFor(AdditionalParams.class).using(valueChanger).areWellImplemented(); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestBase.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestBase.java new file mode 100644 index 00000000..be3ea0eb --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestBase.java @@ -0,0 +1,174 @@ +/* + * 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.vnfm; + +import com.google.common.io.ByteStreams; +import com.nokia.cbam.catalog.v1.api.DefaultApi; +import com.nokia.cbam.lcm.v32.api.OperationExecutionsApi; +import com.nokia.cbam.lcm.v32.api.VnfsApi; +import com.nokia.cbam.lcn.v32.api.SubscriptionsApi; +import org.apache.commons.lang3.ArrayUtils; +import org.apache.http.HttpEntity; +import org.apache.http.client.methods.CloseableHttpResponse; +import org.apache.http.client.methods.HttpUriRequest; +import org.apache.http.impl.client.CloseableHttpClient; +import org.assertj.core.util.Lists; +import org.junit.After; +import org.junit.Before; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.MockitoAnnotations; +import org.onap.msb.sdk.httpclient.msb.MSBServiceClient; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.INotificationSender; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VnfmInfoProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.MsbApiProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.vfc.VfcRestApiProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions; +import org.onap.vfccatalog.api.VnfpackageApi; +import org.onap.vnfmdriver.api.NslcmApi; +import org.slf4j.Logger; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.core.env.Environment; +import org.springframework.test.util.ReflectionTestUtils; + +import javax.servlet.http.HttpServletResponse; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.lang.reflect.Field; +import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; + +import static junit.framework.TestCase.assertEquals; +import static junit.framework.TestCase.assertTrue; +import static org.mockito.Mockito.when; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager.getFileInZip; + +public class TestBase { + public static final String VNF_ID = "myVnfId"; + public static final String VNFM_ID = "myVnfmId"; + public static final String ONAP_CSAR_ID = "myOnapCsarId"; + public static final String VIM_ID = "myVimId"; + public static final String JOB_ID = "myJobId"; + public static final String CBAM_VNFD_ID = "cbamVnfdId"; + @Mock + protected CbamRestApiProvider cbamRestApiProvider; + @Mock + protected VfcRestApiProvider vfcRestApiProvider; + @Mock + protected MsbApiProvider msbApiProvider; + @Mock + protected VnfmInfoProvider vnfmInfoProvider; + @Mock + protected VnfsApi vnfApi; + @Mock + protected OperationExecutionsApi operationExecutionApi; + @Mock + protected SelfRegistrationManager selfRegistrationManager; + @Mock + protected Logger logger; + @Mock + protected SubscriptionsApi lcnApi; + @Mock + protected MSBServiceClient msbClient; + @Mock + protected DriverProperties driverProperties; + @Mock + protected NslcmApi nsLcmApi; + @Mock + protected INotificationSender notificationSender; + @Mock + protected SystemFunctions systemFunctions; + @Mock + protected VnfpackageApi vfcCatalogApi; + @Mock + protected DefaultApi cbamCatalogApi; + @Mock + protected CloseableHttpClient httpClient; + @Mock + protected CloseableHttpResponse response; + protected ArgumentCaptor<HttpUriRequest> request = ArgumentCaptor.forClass(HttpUriRequest.class); + @Mock + protected HttpEntity entity; + @Mock + protected HttpServletResponse httpResponse; + @Mock + protected Environment environment; + + @Before + public void genericSetup() throws Exception { + MockitoAnnotations.initMocks(this); + ReflectionTestUtils.setField(SystemFunctions.class, "INSTANCE", systemFunctions); + when(cbamRestApiProvider.getCbamLcmApi(VNFM_ID)).thenReturn(vnfApi); + when(cbamRestApiProvider.getCbamOperationExecutionApi(VNFM_ID)).thenReturn(operationExecutionApi); + when(cbamRestApiProvider.getCbamLcnApi(VNFM_ID)).thenReturn(lcnApi); + when(cbamRestApiProvider.getCbamCatalogApi(VNFM_ID)).thenReturn(cbamCatalogApi); + when(msbApiProvider.getMsbClient()).thenReturn(msbClient); + when(vfcRestApiProvider.getNsLcmApi()).thenReturn(nsLcmApi); + when(vfcRestApiProvider.getOnapCatalogApi()).thenReturn(vfcCatalogApi); + when(systemFunctions.getHttpClient()).thenReturn(httpClient); + when(httpClient.execute(request.capture())).thenReturn(response); + when(response.getEntity()).thenReturn(entity); + when(driverProperties.getVnfmId()).thenReturn(VNFM_ID); + when(systemFunctions.getHttpClient()).thenReturn(httpClient); + } + + @After + public void tearGeneric() { + ReflectionTestUtils.setField(SystemFunctions.class, "INSTANCE", null); + } + + protected void assertFileInZip(byte[] zip, String path, byte[] expectedContent) throws Exception { + assertTrue(Arrays.equals(expectedContent, getFileInZip(new ByteArrayInputStream(zip), path).toByteArray())); + } + + protected void assertItenticalZips(byte[] expected, byte[] actual) throws Exception { + assertEquals(build(expected), build(actual)); + } + + private Map<String, List<Byte>> build(byte[] zip) throws Exception { + Map<String, List<Byte>> files = new HashMap<>(); + ZipInputStream zipInputStream = new ZipInputStream(new ByteArrayInputStream(zip)); + ZipEntry zipEntry; + while ((zipEntry = zipInputStream.getNextEntry()) != null) { + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + ByteStreams.copy(zipInputStream, byteArrayOutputStream); + files.put(zipEntry.getName(), Lists.newArrayList(ArrayUtils.toObject(byteArrayOutputStream.toByteArray()))); + } + zipInputStream.close(); + return files; + } + + protected void setFieldWithPropertyAnnotation(Object obj, String key, String value) { + for (Field field : obj.getClass().getDeclaredFields()) { + for (Value fieldValue : field.getAnnotationsByType(Value.class)) { + if (fieldValue.value().equals(key)) { + try { + field.setAccessible(true); + field.set(obj, value); + } catch (IllegalAccessException e) { + throw new RuntimeException(e); + } + } + } + } + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestCbamCatalogManager.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestCbamCatalogManager.java new file mode 100644 index 00000000..f38758f0 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestCbamCatalogManager.java @@ -0,0 +1,261 @@ +/* + * 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.vnfm; + +import com.nokia.cbam.catalog.v1.model.CatalogAdapterVnfpackage; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IPackageProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; + +import java.io.ByteArrayInputStream; +import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static junit.framework.TestCase.*; +import static org.junit.Assert.assertArrayEquals; +import static org.mockito.Mockito.*; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager.getFileInZip; +import static org.springframework.test.util.ReflectionTestUtils.setField; + +public class TestCbamCatalogManager extends TestBase { + + private static final String CSAR_ID = "csarId"; + private static final String CBAM_VNFD_ID = "CBAM_VNFD_ID"; + private CatalogManager cbamCatalogManager; + @Mock + private IPackageProvider packageProvider; + + private List<CatalogAdapterVnfpackage> existingVnfPackages = new ArrayList<>(); + private ArgumentCaptor<File> uploadedFile = ArgumentCaptor.forClass(File.class); + + @Before + public void initMocks() throws Exception { + setField(CatalogManager.class, "logger", logger); + when(cbamCatalogApi.list()).thenReturn(existingVnfPackages); + cbamCatalogManager = new CatalogManager(cbamRestApiProvider, packageProvider); + } + + /** + * the package is transferred from source to CBAM catalog + */ + @Test + public void testPackageTransfer() throws Exception { + CatalogAdapterVnfpackage existingPackage = new CatalogAdapterVnfpackage(); + existingPackage.setVnfdId("unknownId"); + existingVnfPackages.add(existingPackage); + CatalogAdapterVnfpackage createdPackage = new CatalogAdapterVnfpackage(); + createdPackage.setVnfdId(CBAM_VNFD_ID); + when(cbamCatalogApi.create(uploadedFile.capture())).thenAnswer(new Answer<CatalogAdapterVnfpackage>() { + @Override + public CatalogAdapterVnfpackage answer(InvocationOnMock invocationOnMock) throws Throwable { + return createdPackage; + } + }); + byte[] onapPackageContent = TestUtil.loadFile("unittests/TestCbamCatalogManager.sample.csar"); + when(packageProvider.getPackage(CSAR_ID)).thenReturn(onapPackageContent); + when(packageProvider.getCbamVnfdId(CSAR_ID)).thenReturn(CBAM_VNFD_ID); + //when + CatalogAdapterVnfpackage cbamPackage = cbamCatalogManager.preparePackageInCbam(VNFM_ID, CSAR_ID); + //verify + byte[] a2 = Files.readAllBytes(uploadedFile.getValue().toPath()); + assertArrayEquals(getFileInZip(new ByteArrayInputStream(onapPackageContent), "Artifacts/Deployment/OTHER/cbam.package.zip").toByteArray(), a2); + assertEquals(createdPackage, cbamPackage); + } + + /** + * the package is transfer fails, but the package has been uploaded (possibly by other thread / work flow) + * the transfer succeeds + */ + @Test + public void testPackageTransferConcurrency() throws Exception { + CatalogAdapterVnfpackage existingPackage = new CatalogAdapterVnfpackage(); + existingPackage.setVnfdId("unknownId"); + existingVnfPackages.add(existingPackage); + CatalogAdapterVnfpackage createdPackage = new CatalogAdapterVnfpackage(); + createdPackage.setVnfdId(CBAM_VNFD_ID); + byte[] onapPackageContent = TestUtil.loadFile("unittests/TestCbamCatalogManager.sample.csar"); + when(packageProvider.getPackage(CSAR_ID)).thenReturn(onapPackageContent); + when(packageProvider.getCbamVnfdId(CSAR_ID)).thenReturn(CBAM_VNFD_ID); + RuntimeException can_not_upload_package = new RuntimeException("Can not upload package"); + when(cbamCatalogApi.create(uploadedFile.capture())).thenAnswer(new Answer<CatalogAdapterVnfpackage>() { + @Override + public CatalogAdapterVnfpackage answer(InvocationOnMock invocationOnMock) throws Throwable { + //this is done by an other thread + existingVnfPackages.add(createdPackage); + when(cbamCatalogApi.getById(CBAM_VNFD_ID)).thenReturn(createdPackage); + throw can_not_upload_package; + } + }); + //when + CatalogAdapterVnfpackage cbamPackage = cbamCatalogManager.preparePackageInCbam(VNFM_ID, CSAR_ID); + //verify + //the correct portion of the package is extracted and uploaded to CBAM + byte[] expectedContentToUpload = getFileInZip(new ByteArrayInputStream(onapPackageContent), "Artifacts/Deployment/OTHER/cbam.package.zip").toByteArray(); + assertTrue(Arrays.equals(expectedContentToUpload, Files.readAllBytes(uploadedFile.getValue().toPath()))); + assertEquals(createdPackage, cbamPackage); + verify(logger).debug("Probably concurrent package uploads", can_not_upload_package); + } + + /** + * If the package already exists in CBAM catalog it is not re-uploaded + */ + @Test + public void testIdempotentPackageUpload() throws Exception { + CatalogAdapterVnfpackage createdPackage = new CatalogAdapterVnfpackage(); + createdPackage.setVnfdId(CBAM_VNFD_ID); + when(cbamCatalogApi.create(uploadedFile.capture())).thenAnswer(new Answer<CatalogAdapterVnfpackage>() { + @Override + public CatalogAdapterVnfpackage answer(InvocationOnMock invocationOnMock) throws Throwable { + return createdPackage; + } + }); + when(packageProvider.getCbamVnfdId(CSAR_ID)).thenReturn(CBAM_VNFD_ID); + CatalogAdapterVnfpackage existingPackage = new CatalogAdapterVnfpackage(); + existingPackage.setVnfdId(CBAM_VNFD_ID); + existingVnfPackages.add(existingPackage); + when(cbamCatalogApi.getById(CBAM_VNFD_ID)).thenReturn(existingPackage); + //when + CatalogAdapterVnfpackage cbamPackage = cbamCatalogManager.preparePackageInCbam(VNFM_ID, CSAR_ID); + //verify + verify(cbamCatalogApi, never()).create(Mockito.any()); + assertEquals(existingPackage, cbamPackage); + verify(packageProvider, never()).getPackage(CSAR_ID); + } + + /** + * failure to list package in CBAM results in error + */ + @Test + public void testFailureToListVnfPackagesInCbam() throws Exception { + when(packageProvider.getCbamVnfdId(CSAR_ID)).thenReturn(CBAM_VNFD_ID); + com.nokia.cbam.catalog.v1.ApiException expectedException = new com.nokia.cbam.catalog.v1.ApiException(); + when(cbamCatalogApi.list()).thenThrow(expectedException); + //when + try { + cbamCatalogManager.preparePackageInCbam(VNFM_ID, CSAR_ID); + fail(); + } catch (Exception e) { + verify(logger).error("Unable to determine if the VNF package has been replicated in CBAM", expectedException); + assertEquals(expectedException, e.getCause()); + } + } + + /** + * failure to query package from CBAM results in error + */ + @Test + public void testFailureToQueryVnfPackagesFromCbam() throws Exception { + when(packageProvider.getCbamVnfdId(CSAR_ID)).thenReturn(CBAM_VNFD_ID); + CatalogAdapterVnfpackage existingPackage = new CatalogAdapterVnfpackage(); + existingPackage.setVnfdId(CBAM_VNFD_ID); + existingVnfPackages.add(existingPackage); + com.nokia.cbam.catalog.v1.ApiException expectedException = new com.nokia.cbam.catalog.v1.ApiException(); + when(cbamCatalogApi.getById(CBAM_VNFD_ID)).thenThrow(expectedException); + //when + try { + cbamCatalogManager.preparePackageInCbam(VNFM_ID, CSAR_ID); + fail(); + } catch (Exception e) { + verify(logger).error("Unable to query VNF package with CBAM_VNFD_ID from CBAM", expectedException); + assertEquals(expectedException, e.getCause()); + } + } + + /** + * failure to create package in CBAM results in error + */ + @Test + public void testFailureToCreatePackageInCbam() throws Exception { + CatalogAdapterVnfpackage existingPackage = new CatalogAdapterVnfpackage(); + existingPackage.setVnfdId("unknownId"); + existingVnfPackages.add(existingPackage); + when(packageProvider.getCbamVnfdId(CSAR_ID)).thenReturn(CBAM_VNFD_ID); + byte[] onapPackageContent = TestUtil.loadFile("unittests/TestCbamCatalogManager.sample.csar"); + when(packageProvider.getPackage(CSAR_ID)).thenReturn(onapPackageContent); + com.nokia.cbam.catalog.v1.ApiException expectedException = new com.nokia.cbam.catalog.v1.ApiException(); + when(cbamCatalogApi.create(Mockito.any())).thenThrow(expectedException); + try { + cbamCatalogManager.preparePackageInCbam(VNFM_ID, CSAR_ID); + fail(); + } catch (Exception e) { + verify(logger).error("Unable to create VNF with csarId CSAR identifier in package in CBAM", expectedException); + assertEquals(expectedException, e.getCause()); + } + } + + /** + * the VNFD is extracted from zip + */ + @Test + public void testExtractVnfdFromPackage() throws Exception { + Path csar = Files.createTempFile(UUID.randomUUID().toString(), "csar"); + Files.write(csar, TestUtil.loadFile("unittests/cbam.package.zip")); + when(cbamCatalogApi.content(CBAM_VNFD_ID)).thenReturn(csar.toFile()); + //when + String content = cbamCatalogManager.getCbamVnfdContent(VNFM_ID, CBAM_VNFD_ID); + //verify + assertEquals("dummy vnfd\n", content); + } + + /** + * if VNFD the Tosca meta can not be extracted sensible error is returned + */ + @Test + public void testEmptyCbamPackage() throws Exception { + Path csar = Files.createTempFile(UUID.randomUUID().toString(), "csar"); + Files.write(csar, TestUtil.loadFile("unittests/empty.zip")); + when(cbamCatalogApi.content(CBAM_VNFD_ID)).thenReturn(csar.toFile()); + //when + try { + cbamCatalogManager.getCbamVnfdContent(VNFM_ID, CBAM_VNFD_ID); + fail(); + } catch (RuntimeException e) { + verify(logger).error("Unable to get package with (CBAM_VNFD_ID)", e.getCause()); + assertEquals("Unable to find the TOSCA-Metadata/TOSCA.meta in archive found: []", e.getCause().getMessage()); + } + } + + /** + * if VNFD can not be extracted sensible error is returned + */ + @Test + public void testMissingVnfdCbamPackage() throws Exception { + Path csar = Files.createTempFile(UUID.randomUUID().toString(), "csar"); + Files.write(csar, TestUtil.loadFile("unittests/missing.vnfd.zip")); + when(cbamCatalogApi.content(CBAM_VNFD_ID)).thenReturn(csar.toFile()); + //when + try { + cbamCatalogManager.getCbamVnfdContent(VNFM_ID, CBAM_VNFD_ID); + fail(); + } catch (RuntimeException e) { + verify(logger).error("Unable to get package with (" + CBAM_VNFD_ID + ")", e.getCause()); + assertTrue("Unable to find the vnfdloc/a.yaml in archive found: [TOSCA-Metadata/, TOSCA-Metadata/TOSCA.meta]".equals(e.getCause().getMessage()) + || "Unable to find the vnfdloc/a.yaml in archive found: [TOSCA-Metadata/TOSCA.meta, TOSCA-Metadata/]".equals(e.getCause().getMessage()) + ); + } + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestCbamTokenProvider.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestCbamTokenProvider.java new file mode 100644 index 00000000..670aa77f --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestCbamTokenProvider.java @@ -0,0 +1,438 @@ +/* + * 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.vnfm; + +import com.google.common.io.ByteStreams; +import org.eclipse.jetty.server.NetworkTrafficServerConnector; +import org.eclipse.jetty.server.Server; +import org.eclipse.jetty.server.handler.AbstractHandler; +import org.eclipse.jetty.util.ssl.SslContextFactory; +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VnfmInfoProvider; +import org.onap.vnfmdriver.model.VnfmInfo; +import org.springframework.http.HttpStatus; + +import javax.net.ssl.*; +import javax.servlet.ServletException; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import java.io.IOException; +import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.security.GeneralSecurityException; +import java.security.KeyStoreException; +import java.security.NoSuchAlgorithmException; +import java.security.NoSuchProviderException; +import java.security.cert.CertificateException; +import java.security.spec.InvalidKeySpecException; +import java.util.ArrayList; +import java.util.Base64; +import java.util.List; + +import static junit.framework.TestCase.*; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; +import static org.springframework.test.util.ReflectionTestUtils.setField; + +class HttpTestServer { + Server _server; + List<String> requests = new ArrayList<>(); + List<Integer> codes = new ArrayList<>(); + List<String> respones = new ArrayList<>(); + + public void start() throws Exception { + configureServer(); + startServer(); + } + + private void startServer() throws Exception { + requests.clear(); + codes.clear(); + _server.start(); + } + + protected void configureServer() throws Exception { + Path jksPath = Paths.get(TestCbamTokenProvider.class.getResource("/unittests/localhost.jks").toURI()); + String path = jksPath.normalize().toAbsolutePath().toUri().toString(); + _server = new Server(); + SslContextFactory factory = new SslContextFactory(path); + factory.setKeyStorePassword("changeit"); + NetworkTrafficServerConnector connector = new NetworkTrafficServerConnector(_server, factory); + connector.setHost("127.0.0.1"); + _server.addConnector(connector); + _server.setHandler(new AbstractHandler() { + @Override + public void handle(String target, org.eclipse.jetty.server.Request request, HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws IOException, ServletException { + requests.add(new String(ByteStreams.toByteArray(request.getInputStream()))); + httpServletResponse.getWriter().write(respones.remove(0)); + httpServletResponse.setStatus(codes.remove(0)); + request.setHandled(true); + } + }); + } + + public void stop() throws Exception { + _server.stop(); + } +} + +public class TestCbamTokenProvider extends TestBase { + + private static String GOOD_RESPONSE = "{ \"access_token\" : \"myToken\", \"expires_in\" : 1000 }"; + @InjectMocks + private CbamTokenProvider cbamTokenProvider; + private VnfmInfo vnfmInfo = new VnfmInfo(); + private ArgumentCaptor<SSLSocketFactory> sslSocketFactory = ArgumentCaptor.forClass(SSLSocketFactory.class); + private ArgumentCaptor<HostnameVerifier> hostnameVerifier = ArgumentCaptor.forClass(HostnameVerifier.class); + private HttpTestServer testServer; + + @Before + public void initMocks() throws Exception { + setField(CbamTokenProvider.class, "logger", logger); + setField(cbamTokenProvider, "username", "myUserName"); + setField(cbamTokenProvider, "password", "myPassword"); + setField(cbamTokenProvider, "skipCertificateVerification", true); + setField(cbamTokenProvider, "skipHostnameVerification", true); + when(vnfmInfoProvider.getVnfmInfo(VNFM_ID)).thenReturn(vnfmInfo); + vnfmInfo.setPassword("vnfmPassword"); + vnfmInfo.setUserName("vnfmUserName"); + vnfmInfo.setUrl("http://127.0.0.3:12345"); + testServer = new HttpTestServer(); + testServer.start(); + URI uri = testServer._server.getURI(); + setField(cbamTokenProvider, "cbamKeyCloakBaseUrl", uri.toString()); + } + + private void addGoodTokenResponse() { + testServer.respones.add(GOOD_RESPONSE); + testServer.codes.add(HttpStatus.OK.value()); + } + + @After + public void testServer() throws Exception { + testServer.stop(); + } + + /** + * a new token is requested no token has been requested before + */ + @Test + public void testBasicTokenRequest() throws Exception { + //given + addGoodTokenResponse(); + //when + String token = cbamTokenProvider.getToken(VNFM_ID); + //verify + assertEquals(1, testServer.requests.size()); + assertTokenRequest(testServer.requests.get(0)); + assertEquals("myToken", token); + + } + + /** + * a new token is requested if the previous token has expired + */ + @Test + public void testTokenIsRequestedIfPreviousExpired() throws Exception { + //given + addGoodTokenResponse(); + String firstToken = cbamTokenProvider.getToken(VNFM_ID); + testServer.respones.add("{ \"access_token\" : \"myToken2\", \"expires_in\" : 2000 }"); + testServer.codes.add(HttpStatus.OK.value()); + when(systemFunctions.currentTimeMillis()).thenReturn(500L * 1000 + 1L); + //when + String token = cbamTokenProvider.getToken(VNFM_ID); + //verify + assertEquals(2, testServer.requests.size()); + assertTokenRequest(testServer.requests.get(0)); + assertTokenRequest(testServer.requests.get(1)); + assertEquals("myToken2", token); + } + + /** + * a new token is not requested if the previous token has not expired + */ + @Test + public void testTokenIsNotRequestedIfPreviousHasNotExpired() throws Exception { + //given + addGoodTokenResponse(); + String firstToken = cbamTokenProvider.getToken(VNFM_ID); + testServer.respones.add("{ \"access_token\" : \"myToken2\", \"expires_in\" : 2000 }"); + testServer.codes.add(HttpStatus.OK.value()); + when(systemFunctions.currentTimeMillis()).thenReturn(500L * 1000); + //when + String token = cbamTokenProvider.getToken(VNFM_ID); + //verify + assertEquals(1, testServer.requests.size()); + assertTokenRequest(testServer.requests.get(0)); + assertEquals("myToken", token); + } + + /** + * failed token requests are retried for a fixed number amount of times + */ + @Test + public void testRetry() throws Exception { + //given + addFailedResponse(); + addFailedResponse(); + addFailedResponse(); + addFailedResponse(); + addGoodTokenResponse(); + //cbamTokenProvider.failOnRequestNumber = 5; + //when + String token = cbamTokenProvider.getToken(VNFM_ID); + //verify + assertEquals(5, testServer.requests.size()); + assertTokenRequest(testServer.requests.get(0)); + assertTokenRequest(testServer.requests.get(1)); + assertTokenRequest(testServer.requests.get(2)); + assertTokenRequest(testServer.requests.get(3)); + assertTokenRequest(testServer.requests.get(4)); + verify(logger).warn(eq("Unable to get token to access CBAM API (1/5)"), Mockito.<RuntimeException>any()); + verify(logger).warn(eq("Unable to get token to access CBAM API (2/5)"), Mockito.<RuntimeException>any()); + verify(logger).warn(eq("Unable to get token to access CBAM API (3/5)"), Mockito.<RuntimeException>any()); + verify(logger).warn(eq("Unable to get token to access CBAM API (4/5)"), Mockito.<RuntimeException>any()); + assertEquals("myToken", token); + } + + /** + * failed token requests are retried for a fixed number amount of times (reacing maximal number or retries) + */ + @Test + public void testNoMoreRetry() throws Exception { + //given + addFailedResponse(); + addFailedResponse(); + addFailedResponse(); + addFailedResponse(); + addFailedResponse(); + //when + try { + cbamTokenProvider.getToken(VNFM_ID); + fail(); + } catch (RuntimeException e) { + assertNotNull(e.getCause()); + } + //verify + assertEquals(5, testServer.requests.size()); + assertTokenRequest(testServer.requests.get(0)); + assertTokenRequest(testServer.requests.get(1)); + assertTokenRequest(testServer.requests.get(2)); + assertTokenRequest(testServer.requests.get(3)); + assertTokenRequest(testServer.requests.get(4)); + verify(logger).warn(eq("Unable to get token to access CBAM API (1/5)"), Mockito.<RuntimeException>any()); + verify(logger).warn(eq("Unable to get token to access CBAM API (2/5)"), Mockito.<RuntimeException>any()); + verify(logger).warn(eq("Unable to get token to access CBAM API (3/5)"), Mockito.<RuntimeException>any()); + verify(logger).warn(eq("Unable to get token to access CBAM API (4/5)"), Mockito.<RuntimeException>any()); + verify(logger).error(eq("Unable to get token to access CBAM API (giving up retries)"), Mockito.<RuntimeException>any()); + } + + private void addFailedResponse() { + testServer.codes.add(HttpStatus.UNAUTHORIZED.value()); + testServer.respones.add(new String()); + } + + /** + * the SSL connection is established without certificate & hostname verification + */ + @Test + public void noSslVerification() throws Exception { + //given + //the default settings is no SSL & hostname check + addGoodTokenResponse(); + //when + cbamTokenProvider.getToken(VNFM_ID); + //verify + //no exception is thrown + } + + /** + * if SSL is verified the certificates must be defined + */ + @Test + public void testInvalidCombinationOfSettings() throws Exception { + //given + setField(cbamTokenProvider, "skipCertificateVerification", false); + //when + try { + cbamTokenProvider.getToken(VNFM_ID); + //verify + fail(); + } catch (RuntimeException e) { + assertEquals("If the skipCertificateVerification is set to false (default) the trustedCertificates can not be empty", e.getMessage()); + } + } + + /** + * if SSL is verified the certificates must be defined + */ + @Test + public void testInvalidCombinationOfSettings2() throws Exception { + //given + setField(cbamTokenProvider, "skipCertificateVerification", false); + setField(cbamTokenProvider, "trustedCertificates", "xx\nxx"); + //when + try { + cbamTokenProvider.getToken(VNFM_ID); + //verify + fail(); + } catch (RuntimeException e) { + assertEquals("The trustedCertificates must be a base64 encoded collection of PEM certificates", e.getMessage()); + assertNotNull(e.getCause()); + } + } + + /** + * the SSL connection is established without certificate & hostname verification + */ + @Test + public void testNotTrustedSslConnection() throws Exception { + //given + setField(cbamTokenProvider, "skipCertificateVerification", false); + Path caPem = Paths.get(TestCbamTokenProvider.class.getResource("/unittests/sample.cert.pem").toURI()); + setField(cbamTokenProvider, "trustedCertificates", Base64.getEncoder().encodeToString(Files.readAllBytes(caPem))); + addGoodTokenResponse(); + //when + try { + cbamTokenProvider.getToken(VNFM_ID); + //verify + fail(); + } catch (RuntimeException e) { + assertTrue(e.getMessage().contains("unable to find valid certification path")); + assertTrue(e.getCause() instanceof SSLHandshakeException); + } + } + + /** + * the SSL connection is established with certificate & hostname verification + */ + @Test + public void testHostnameVerificationSucceeds() throws Exception { + //given + setField(cbamTokenProvider, "skipCertificateVerification", false); + Path caPem = Paths.get(TestCbamTokenProvider.class.getResource("/unittests/localhost.cert.pem").toURI()); + setField(cbamTokenProvider, "trustedCertificates", Base64.getEncoder().encodeToString(Files.readAllBytes(caPem))); + setField(cbamTokenProvider, "cbamKeyCloakBaseUrl", testServer._server.getURI().toString().replace("127.0.0.1", "localhost")); + setField(cbamTokenProvider, "skipHostnameVerification", false); + addGoodTokenResponse(); + //when + cbamTokenProvider.getToken(VNFM_ID); + //verify + //no seception is thrown + } + + /** + * the SSL connection is dropped with certificate & hostname verification due to invalid hostname + */ + @Test + public void testHostnameverifcationfail() throws Exception { + //given + setField(cbamTokenProvider, "skipCertificateVerification", false); + Path caPem = Paths.get(TestCbamTokenProvider.class.getResource("/unittests/localhost.cert.pem").toURI()); + setField(cbamTokenProvider, "trustedCertificates", Base64.getEncoder().encodeToString(Files.readAllBytes(caPem))); + setField(cbamTokenProvider, "skipHostnameVerification", false); + addGoodTokenResponse(); + //when + try { + cbamTokenProvider.getToken(VNFM_ID); + //verify + fail(); + } catch (RuntimeException e) { + assertTrue(e.getMessage().contains("Hostname 127.0.0.1 not verified")); + assertTrue(e.getCause() instanceof SSLPeerUnverifiedException); + } + } + + /** + * invalid certificate content + */ + @Test + public void testInvalidCerificateContent() throws Exception { + //given + setField(cbamTokenProvider, "skipCertificateVerification", false); + setField(cbamTokenProvider, "trustedCertificates", Base64.getEncoder().encodeToString("-----BEGIN CERTIFICATE-----\nkuku\n-----END CERTIFICATE-----\n".getBytes())); + setField(cbamTokenProvider, "skipHostnameVerification", false); + addGoodTokenResponse(); + //when + try { + cbamTokenProvider.getToken(VNFM_ID); + //verify + fail(); + } catch (RuntimeException e) { + assertTrue(e.getMessage().contains("Unable to load certificates")); + assertTrue(e.getCause() instanceof GeneralSecurityException); + } + } + + /** + * Verify client certificates are not verified + * \ + */ + @Test + public void testClientCertificates() throws Exception { + //when + new CbamTokenProvider.AllTrustedTrustManager().checkClientTrusted(null, null); + //verify + //no security exception is thrown + } + + /** + * Exception during keystore creation is logged (semi-useless) + */ + @Test + public void testKeystoreCreationFailure() { + KeyStoreException expectedException = new KeyStoreException(); + class X extends CbamTokenProvider { + X(VnfmInfoProvider vnfmInfoProvider) { + super(vnfmInfoProvider); + } + + @Override + TrustManager[] buildTrustManager() throws KeyStoreException, NoSuchProviderException, NoSuchAlgorithmException, InvalidKeySpecException, CertificateException { + throw expectedException; + } + } + try { + new X(null).buildSSLSocketFactory(); + fail(); + } catch (RuntimeException e) { + assertEquals(expectedException, e.getCause()); + verify(logger).error("Unable to create SSL socket factory", expectedException); + } + } + + private void assertTokenRequest(String body) { + assertContains(body, "grant_type", "password"); + assertContains(body, "client_id", "vnfmUserName"); + assertContains(body, "client_secret", "vnfmPassword"); + assertContains(body, "username", "myUserName"); + assertContains(body, "password", "myPassword"); + } + + private void assertContains(String content, String key, String value) { + assertTrue(content.contains(key + "=" + value)); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestDriverProperties.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestDriverProperties.java new file mode 100644 index 00000000..22db05b2 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestDriverProperties.java @@ -0,0 +1,35 @@ +/* + * 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.vnfm; + +import org.junit.Test; + +import static pl.pojo.tester.api.assertion.Assertions.assertPojoMethodsFor; + + +public class TestDriverProperties { + + /** + * Test basic POJO behaviour + */ + @Test + public void test() { + + + assertPojoMethodsFor(DriverProperties.class).areWellImplemented(); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestJobManager.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestJobManager.java new file mode 100644 index 00000000..1ba58abe --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestJobManager.java @@ -0,0 +1,544 @@ +/* + * 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.vnfm; + +import com.google.common.collect.Lists; +import com.google.gson.JsonElement; +import com.google.gson.JsonParser; +import com.nokia.cbam.lcm.v32.ApiException; +import com.nokia.cbam.lcm.v32.model.*; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.onap.vnfmdriver.model.JobDetailInfo; +import org.onap.vnfmdriver.model.JobResponseInfo; +import org.onap.vnfmdriver.model.JobStatus; +import org.springframework.test.util.ReflectionTestUtils; +import org.threeten.bp.OffsetDateTime; + +import javax.servlet.http.HttpServletResponse; +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static junit.framework.TestCase.*; +import static org.mockito.Mockito.*; +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.ILifecycleChangeNotificationManager.SEPARATOR; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.JobManager.extractOnapJobId; +import static org.onap.vnfmdriver.model.JobStatus.*; + +public class TestJobManager extends TestBase { + + @Mock + private HttpServletResponse httpResponse; + + @InjectMocks + private JobManager jobManager; + private List<VnfInfo> vnfs = new ArrayList<>(); + + @Before + public void initMocks() throws Exception { + ReflectionTestUtils.setField(JobManager.class, "logger", logger); + when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenReturn(vnfs); + when(selfRegistrationManager.isReady()).thenReturn(true); + } + + /** + * Only the _ can be used as separator + * . / % & handled specially in URLs + * - used in CBAM for separation + */ + @Test + public void testSeparator() { + assertEquals("_", SEPARATOR); + } + + /** + * The operation result must contain the ONAP job identifier under the jobId field + */ + @Test + public void testJobIdExtractionFromOperationResult() { + assertEquals("1234", extractOnapJobId(new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"1234\"}}"))); + try { + extractOnapJobId(new JsonParser().parse("{ }")); + fail(); + } catch (NoSuchElementException e) { + assertEquals("The operation result {} does not contain the mandatory additionalParams structure", e.getMessage()); + } + try { + extractOnapJobId(new JsonParser().parse("{ \"additionalParams\" : { } }")); + fail(); + } catch (NoSuchElementException e) { + assertEquals("The operation result {\"additionalParams\":{}} does not contain the mandatory jobId in the additionalParams structure", e.getMessage()); + } + } + + /** + * If the VNF does not exists but the job manager still runs the VNF manipulation process the job is reported to be running + */ + @Test + public void testJobForNonExistingVnfReportedRunningIfJobIsOngoing() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + //when + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, STARTED, "50", "Operation started"); + } + + /** + * If the VNF does not exists and the internal job is not running the job is reported to be finished + */ + @Test + public void testJobForExistingVnfReportedRunningIfJobIsFinished() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + jobManager.jobFinished(jobId); + //when + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, JobStatus.FINISHED, "100", "Operation finished"); + } + + /** + * Spawning jobs after preparing for shutdown results in error + */ + @Test + public void testNoMoreJobsAreAllowedAfterPrepareForShutdown() throws Exception { + jobManager.prepareForShutdown(); + //when + try { + jobManager.spawnJob(JOB_ID, httpResponse); + fail(); + } catch (Exception e) { + verify(logger).error("The service is preparing to shut down"); + } + } + + /** + * Verify if the jobId has valid format + */ + @Test + public void testJobIdValidation() throws Exception { + try { + //when + jobManager.getJob(VNFM_ID, "bad"); + //verify + fail(); + } catch (IllegalArgumentException e) { + assertEquals("The jobId should be in the <vnfId>_<UUID> format, but was bad", e.getMessage()); + } + try { + //when + jobManager.getJob(VNFM_ID, "vnfId_"); + //verify + fail(); + } catch (IllegalArgumentException e) { + assertEquals("The UUID in the jobId (vnfId_) can not be empty", e.getMessage()); + } + try { + //when + jobManager.getJob(VNFM_ID, "_UUID"); + //verify + fail(); + } catch (IllegalArgumentException e) { + assertEquals("The vnfId in the jobId (_UUID) can not be empty", e.getMessage()); + } + } + + /** + * If the VNF exists but no operation execution is present with given internalJobId, than the state of the + * job is ongoing if the internal job is ongoing + */ + @Test + public void testExistingVnfWithNotYetStartedOperation() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(detailedVnf); + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, STARTED, "50", "Operation started"); + assertTrue(jobManager.hasOngoingJobs()); + } + + /** + * If the VNF exists but no operation execution is present with given internalJobId, than the state of the + * job is failed if the internal job is finished (the operation on CBAM was not able to start) + */ + @Test + public void testExistingVnfWithNotUnableToStartOperation() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(detailedVnf); + jobManager.jobFinished(jobId); + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, ERROR, "100", "Operation failed due to The requested operation was not able to start on CBAM"); + assertFalse(jobManager.hasOngoingJobs()); + } + + /** + * If the VNF exists but and the operation execution is present with given internalJobId, than the state of the + * job is ongoing if the operation is ongoing + */ + @Test + public void testExistingVnfWithStartedOperation() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(detailedVnf); + OperationExecution operation = new OperationExecution(); + operation.setId(UUID.randomUUID().toString()); + operation.setStartTime(OffsetDateTime.now()); + operation.setStatus(OperationStatus.STARTED); + detailedVnf.setOperationExecutions(new ArrayList<>()); + detailedVnf.getOperationExecutions().add(operation); + JsonElement operationParams = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + jobId + "\"}}"); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(operationParams); + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, STARTED, "50", "Operation started"); + assertTrue(jobManager.hasOngoingJobs()); + } + + /** + * If the VNF does not exists till the time the job queries the status of the operation + */ + @Test + public void testTerminatedVnf() throws Exception { + //ddd + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + List<Integer> vnfQueryCallCounter = new ArrayList<>(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenAnswer(new Answer<VnfInfo>() { + @Override + public VnfInfo answer(InvocationOnMock invocation) throws Throwable { + vnfs.clear(); + return detailedVnf; + } + }); + + jobManager.jobFinished(jobId); + + OperationExecution operation = new OperationExecution(); + operation.setId(UUID.randomUUID().toString()); + operation.setStartTime(OffsetDateTime.now()); + operation.setStatus(OperationStatus.FINISHED); + operation.setOperationType(OperationType.TERMINATE); + detailedVnf.setOperationExecutions(new ArrayList<>()); + detailedVnf.getOperationExecutions().add(operation); + + JsonElement operationParams = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + jobId + "\"}}"); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(operationParams); + //when + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, FINISHED, "100", "Operation finished"); + } + + /** + * If the VNF exists but and the operation execution is present with given internalJobId, than the state of the + * job is error if the operation is failed + */ + @Test + public void testExistingVnfWithFailedOperation() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + List<Integer> vnfCounter = new ArrayList<>(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(detailedVnf); + OperationExecution operation = new OperationExecution(); + operation.setId(UUID.randomUUID().toString()); + operation.setStartTime(OffsetDateTime.now()); + operation.setStatus(OperationStatus.FAILED); + ProblemDetails errorDetails = new ProblemDetails(); + errorDetails.setTitle("Title"); + errorDetails.setDetail("detail"); + operation.setError(errorDetails); + detailedVnf.setOperationExecutions(new ArrayList<>()); + detailedVnf.getOperationExecutions().add(operation); + JsonElement operationParams = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + jobId + "\"}}"); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(operationParams); + //when + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, ERROR, "100", "Operation failed due to Title: detail"); + assertTrue(jobManager.hasOngoingJobs()); + } + + private void assertResult(String jobId, JobDetailInfo job, JobStatus status, String progress, String descriptor) { + assertEquals(jobId, job.getJobId()); + assertEquals(status, job.getResponseDescriptor().getStatus()); + assertEquals(progress, job.getResponseDescriptor().getProgress()); + assertNull(job.getResponseDescriptor().getErrorCode()); + boolean finalState = JobStatus.ERROR.equals(status) || JobStatus.FINISHED.equals(status); + if (finalState) { + assertEquals(2, job.getResponseDescriptor().getResponseHistoryList().size()); + JobResponseInfo startEvent = job.getResponseDescriptor().getResponseHistoryList().get(0); + JobResponseInfo endEvent = job.getResponseDescriptor().getResponseHistoryList().get(1); + assertNull(startEvent.getErrorCode()); + assertEquals("50", startEvent.getProgress()); + assertEquals(JobStatus.STARTED.name(), startEvent.getStatus()); + assertEquals("1", startEvent.getResponseId()); + assertEquals("Operation started", startEvent.getStatusDescription()); + + assertNull(endEvent.getErrorCode()); + assertEquals("100", endEvent.getProgress()); + assertEquals(job.getResponseDescriptor().getStatus().name(), endEvent.getStatus()); + assertEquals("2", endEvent.getResponseId()); + assertEquals(descriptor, endEvent.getStatusDescription()); + } else { + assertEquals(1, job.getResponseDescriptor().getResponseHistoryList().size()); + assertNull(job.getResponseDescriptor().getResponseHistoryList().get(0).getErrorCode()); + assertEquals(progress, job.getResponseDescriptor().getResponseHistoryList().get(0).getProgress()); + assertEquals(job.getResponseDescriptor().getStatus().name(), job.getResponseDescriptor().getResponseHistoryList().get(0).getStatus()); + assertEquals("1", job.getResponseDescriptor().getResponseHistoryList().get(0).getResponseId()); + assertEquals(descriptor, job.getResponseDescriptor().getResponseHistoryList().get(0).getStatusDescription()); + } + assertEquals(Integer.toString(job.getResponseDescriptor().getResponseHistoryList().size()), job.getResponseDescriptor().getResponseId()); + assertEquals(descriptor, job.getResponseDescriptor().getStatusDescription()); + } + + /** + * If the VNF exists but and the operation execution is present with given internalJobId, than the state of the + * job is finished if the operation is finished, but is not a termination + */ + @Test + public void testExistingVnfWithFinishedOperation() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(detailedVnf); + OperationExecution operation = new OperationExecution(); + operation.setId(UUID.randomUUID().toString()); + operation.setStartTime(OffsetDateTime.now()); + operation.setStatus(OperationStatus.FINISHED); + operation.setOperationType(OperationType.SCALE); + detailedVnf.setOperationExecutions(new ArrayList<>()); + detailedVnf.getOperationExecutions().add(operation); + JsonElement operationParams = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + jobId + "\"}}"); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(operationParams); + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, JobStatus.FINISHED, "100", "Operation finished"); + assertTrue(jobManager.hasOngoingJobs()); + } + + /** + * If the VNF exists but and the operation execution is present with given internalJobId, than the state of the + * job is ongoing if the termination operation is finished. In ONAP terminology the termination includes + * delete, so the ONAP operation is ongoing since the VNF is not yet deleted + */ + @Test + public void testExistingVnfWithFinishedTerminationOperation() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(detailedVnf); + OperationExecution operation = new OperationExecution(); + operation.setId(UUID.randomUUID().toString()); + operation.setStartTime(OffsetDateTime.now()); + operation.setStatus(OperationStatus.FINISHED); + operation.setOperationType(OperationType.TERMINATE); + detailedVnf.setOperationExecutions(new ArrayList<>()); + detailedVnf.getOperationExecutions().add(operation); + JsonElement operationParams = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + jobId + "\"}}"); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(operationParams); + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, STARTED, "50", "Operation started"); + //when + jobManager.jobFinished(jobId); + job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertResult(jobId, job, ERROR, "100", "Operation failed due to unable to delete VNF"); + assertFalse(jobManager.hasOngoingJobs()); + + } + + /** + * Failuire to retrieve operation parameters (CBAM REST API fail) is logged and propagated + */ + @Test + public void failuresDuringOperationExecutionRetrievalIsLoggedAndPropagated() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(detailedVnf); + OperationExecution operation = new OperationExecution(); + operation.setId(UUID.randomUUID().toString()); + detailedVnf.setOperationExecutions(new ArrayList<>()); + detailedVnf.getOperationExecutions().add(operation); + ApiException expectedException = new ApiException(); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(operation.getId(), NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //verify + try { + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + fail(); + } catch (RuntimeException e) { + assertEquals(expectedException, e.getCause()); + verify(logger).error("Unable to retrieve operation parameters", expectedException); + } + assertTrue(jobManager.hasOngoingJobs()); + } + + /** + * Failure to retrieve VNF (CBAM REST API fail) is logged and propagated + */ + @Test + public void failuresDuringVnfRetrievalIsLoggedAndPropagated() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //verify + try { + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + fail(); + } catch (RuntimeException e) { + assertEquals(expectedException, e.getCause()); + verify(logger).error("Unable to retrieve VNF", expectedException); + } + assertTrue(jobManager.hasOngoingJobs()); + } + + /** + * When searching for the ONAP job by iterating the operation executions. The newest jobs + * are inspected first (performance optimalization) + */ + @Test + public void testNewestOperationAreInspectedFirst() throws Exception { + String jobId = jobManager.spawnJob(VNF_ID, httpResponse); + VnfInfo vnf = new VnfInfo(); + vnf.setId(VNF_ID); + vnfs.add(vnf); + VnfInfo detailedVnf = new VnfInfo(); + detailedVnf.setId(VNF_ID); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(detailedVnf); + OperationExecution olderOperation = new OperationExecution(); + olderOperation.setId(UUID.randomUUID().toString()); + olderOperation.setStartTime(OffsetDateTime.now()); + olderOperation.setStatus(OperationStatus.FINISHED); + olderOperation.setOperationType(OperationType.TERMINATE); + OperationExecution newerOperation = new OperationExecution(); + newerOperation.setId(UUID.randomUUID().toString()); + newerOperation.setStartTime(OffsetDateTime.now().plusDays(1)); + newerOperation.setStatus(OperationStatus.FINISHED); + newerOperation.setOperationType(OperationType.TERMINATE); + detailedVnf.setOperationExecutions(new ArrayList<>()); + detailedVnf.getOperationExecutions().add(olderOperation); + detailedVnf.getOperationExecutions().add(newerOperation); + JsonElement operationParams = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + jobId + "\"}}"); + List<String> queriedOperaionsInOrder = new ArrayList<>(); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(Mockito.anyString(), Mockito.eq(NOKIA_LCM_API_VERSION))) + .then(new Answer<Object>() { + @Override + public Object answer(InvocationOnMock invocationOnMock) throws Throwable { + queriedOperaionsInOrder.add(invocationOnMock.getArguments()[0].toString()); + if (invocationOnMock.getArguments()[0].equals(olderOperation.getId())) { + return new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + jobId + "\"}}"); + } else { + return new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + "nonMatching" + "\"}}"); + } + } + }); + JobDetailInfo job = jobManager.getJob(VNFM_ID, jobId); + //verify + assertEquals(Lists.newArrayList(newerOperation.getId(), olderOperation.getId()), queriedOperaionsInOrder); + assertTrue(jobManager.hasOngoingJobs()); + } + + /** + * if the registration process has not finished it is prevented to spawn jobs + */ + @Test + public void noJobCanBeStartedIfRegistrationNotFinished() throws Exception { + //given + when(selfRegistrationManager.isReady()).thenReturn(false); + //when + try { + jobManager.spawnJob(VNF_ID, httpResponse); + fail(); + } catch (RuntimeException e) { + assertEquals("The service is not yet ready", e.getMessage()); + } + } + + /** + * Ongoing job are out waited during the the preparation for shutdown + */ + @Test + public void onGoingJobsAreOutwaitedDuringShutdown() throws Exception { + String firstJobId = jobManager.spawnJob(VNF_ID, httpResponse); + ExecutorService executorService = Executors.newCachedThreadPool(); + ArgumentCaptor<Integer> sleeps = ArgumentCaptor.forClass(Integer.class); + doNothing().when(systemFunctions).sleep(sleeps.capture()); + Future<?> shutDown = executorService.submit(new Runnable() { + @Override + public void run() { + jobManager.prepareForShutdown(); + } + }); + while (sleeps.getAllValues().size() == 0) { + try { + Thread.sleep(1); + } catch (InterruptedException e) { + } + } + assertFalse(shutDown.isDone()); + jobManager.jobFinished(firstJobId); + //verify + shutDown.get(); + verify(systemFunctions, times(sleeps.getAllValues().size())).sleep(500L); + } +} 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 new file mode 100644 index 00000000..64adaab1 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestLifecycleManager.java @@ -0,0 +1,1336 @@ +/* + * 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.vnfm; + +import com.google.gson.Gson; +import com.google.gson.JsonElement; +import com.google.gson.JsonObject; +import com.google.gson.JsonParser; +import com.nokia.cbam.catalog.v1.model.CatalogAdapterVnfpackage; +import com.nokia.cbam.lcm.v32.ApiException; +import com.nokia.cbam.lcm.v32.model.*; +import com.nokia.cbam.lcm.v32.model.OperationType; +import com.nokia.cbam.lcm.v32.model.VimInfo; +import com.nokia.cbam.lcm.v32.model.VnfInfo; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InOrder; +import org.mockito.Mock; +import org.mockito.Mockito; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VimInfoProvider; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.vfc.TestVfcGrantManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.vfc.VfcGrantManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.StoreLoader; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.LifecycleChangeNotificationManager; +import org.onap.vnfmdriver.model.ExtVirtualLinkInfo; +import org.onap.vnfmdriver.model.*; +import org.onap.vnfmdriver.model.ScaleDirection; +import org.threeten.bp.OffsetDateTime; + +import javax.servlet.http.HttpServletResponse; +import java.nio.file.Paths; +import java.util.*; + +import static java.lang.Boolean.parseBoolean; +import static java.nio.file.Files.readAllBytes; +import static junit.framework.TestCase.*; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.*; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions; +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 TestLifecycleManager extends TestBase { + public static final String JOB_ID = "myJobId"; + public static final String CBAM_VNFD_ID = "cbamVnfdId"; + public static final String TENANT = "myTenant"; + public static final String OPERATION_EXECUTION_ID = "operationExecutionId"; + private static final String ONAP_CSAR_ID = "myOnapCsarId"; + private static final String VIM_ID = "ownerId_regionId"; + private GrantVNFResponseVim vim = new GrantVNFResponseVim(); + @Mock + private CatalogManager catalogManager; + @Mock + private VfcGrantManager vfcGrantManager; + @Mock + private CbamTokenProvider tokenProvider; + @Mock + private JobManager jobManager; + @Mock + private LifecycleChangeNotificationManager notificationManager; + @Mock + private HttpServletResponse restResponse; + @Mock + private VimInfoProvider vimInfoProvider; + + private ArgumentCaptor<CreateVnfRequest> createRequest = ArgumentCaptor.forClass(CreateVnfRequest.class); + private AdditionalParams additionalParam = new AdditionalParams(); + private String INSTANTIATION_LEVEL = "level1"; + private GrantVNFResponseVim grantResponse = new GrantVNFResponseVim(); + private String cbamVnfdContent; + private OperationExecution instantiationOperationExecution = new OperationExecution(); + private OperationExecution modifyPropertyoperationExecution = new OperationExecution(); + private OperationExecution scaleOperationExecution = new OperationExecution(); + private OperationExecution healOperationExecution = new OperationExecution(); + + private VnfInfo vnfInfo = new VnfInfo(); + private List<OperationExecution> operationExecutions = new ArrayList<>(); + private org.onap.vnfmdriver.model.VimInfo vimInfo = new org.onap.vnfmdriver.model.VimInfo(); + private ExtVirtualLinkInfo externalVirtualLink = new ExtVirtualLinkInfo(); + private ExtManagedVirtualLinkData extManVl = new ExtManagedVirtualLinkData(); + private ArgumentCaptor<ModifyVnfInfoRequest> actualVnfModifyRequest = ArgumentCaptor.forClass(ModifyVnfInfoRequest.class); + private Set<Boolean> finished = new HashSet<>(); + private ArgumentCaptor<ScaleVnfRequest> actualScaleRequest = ArgumentCaptor.forClass(ScaleVnfRequest.class); + private ArgumentCaptor<HealVnfRequest> actualHealRequest = ArgumentCaptor.forClass(HealVnfRequest.class); + + private LifecycleManager lifecycleManager; + + @Before + public void initMocks() throws Exception { + vnfInfo.setExtensions(new ArrayList<>()); + vnfInfo.setOperationExecutions(new ArrayList<>()); + lifecycleManager = new LifecycleManager(catalogManager, vfcGrantManager, cbamRestApiProvider, vimInfoProvider, jobManager, notificationManager); + cbamVnfdContent = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/vnfd.full.yaml").toURI()))); + setField(LifecycleManager.class, "logger", logger); + CatalogAdapterVnfpackage cbamPackage = new CatalogAdapterVnfpackage(); + when(catalogManager.preparePackageInCbam(VNFM_ID, ONAP_CSAR_ID)).thenReturn(cbamPackage); + cbamPackage.setVnfdId(CBAM_VNFD_ID); + vnfInfo.setVnfdId(CBAM_VNFD_ID); + vnfInfo.setId(VNF_ID); + when(jobManager.spawnJob(VNF_ID, restResponse)).thenReturn(JOB_ID); + when(catalogManager.getCbamVnfdContent(VNFM_ID, CBAM_VNFD_ID)).thenReturn(cbamVnfdContent); + cbamPackage.setId(CBAM_VNFD_ID); + vimInfo.setUrl("cloudUrl"); + vimInfo.setPassword("vimPassword"); + vimInfo.setUserName("vimUsername"); + vimInfo.setSslInsecure("true"); + vimInfo.setVimId(VIM_ID); + vimInfo.setName("vimName"); + when(vimInfoProvider.getVimInfo((VIM_ID))).thenReturn(vimInfo); + instantiationOperationExecution.setId(OPERATION_EXECUTION_ID); + instantiationOperationExecution.setOperationType(OperationType.INSTANTIATE); + instantiationOperationExecution.setStartTime(OffsetDateTime.now()); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(operationExecutions); + operationExecutions.add(modifyPropertyoperationExecution); + modifyPropertyoperationExecution.setStartTime(OffsetDateTime.now()); + modifyPropertyoperationExecution.setOperationType(OperationType.MODIFY_INFO); + operationExecutions.add(instantiationOperationExecution); + instantiationOperationExecution.setStatus(OperationStatus.FINISHED); + modifyPropertyoperationExecution.setStatus(OperationStatus.FINISHED); + modifyPropertyoperationExecution.setId(UUID.randomUUID().toString()); + scaleOperationExecution.setId(UUID.randomUUID().toString()); + healOperationExecution.setId(UUID.randomUUID().toString()); + when(vnfApi.vnfsVnfInstanceIdPatch(eq(VNF_ID), actualVnfModifyRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(modifyPropertyoperationExecution); + doAnswer(new Answer() { + @Override + public Object answer(InvocationOnMock invocation) throws Throwable { + finished.add(Boolean.TRUE); + return null; + } + }).when(jobManager).jobFinished(JOB_ID); + when(vnfApi.vnfsVnfInstanceIdScalePost(eq(VNF_ID), actualScaleRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + operationExecutions.add(scaleOperationExecution); + return scaleOperationExecution; + } + }); + when(vnfApi.vnfsVnfInstanceIdHealPost(eq(VNF_ID), actualHealRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + operationExecutions.add(healOperationExecution); + return healOperationExecution; + } + }); + } + + /** + * test instantiation + */ + @Test + public void testInstantiation() throws Exception { + //given + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(instantiationOperationExecution); + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + waitForJobToFinishInJobManager(finished); + //verify + assertEquals(VNF_ID, response.getVnfInstanceId()); + assertEquals(JOB_ID, response.getJobId()); + assertEquals(createRequest.getAllValues().size(), 1); + assertEquals("myDescription", createRequest.getValue().getDescription()); + assertEquals("vnfName", createRequest.getValue().getName()); + assertEquals(CBAM_VNFD_ID, createRequest.getValue().getVnfdId()); + assertEquals(1, actualInstantiationRequest.getAllValues().size()); + assertEquals(1, actualInstantiationRequest.getValue().getVims().size()); + OPENSTACKV2INFO actualVim = (OPENSTACKV2INFO) actualInstantiationRequest.getValue().getVims().get(0); + assertEquals(VIM_ID, actualVim.getId()); + assertEquals(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO, actualVim.getVimInfoType()); + assertEquals(Boolean.valueOf(parseBoolean(vimInfo.getSslInsecure())), actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertEquals("cloudUrl", actualVim.getInterfaceInfo().getEndpoint()); + //FIXME assertEquals();actualVim.getInterfaceInfo().getTrustedCertificates()); + assertEquals("vimPassword", actualVim.getAccessInfo().getPassword()); + assertEquals("regionId", actualVim.getAccessInfo().getRegion()); + assertEquals("myTenant", actualVim.getAccessInfo().getTenant()); + assertEquals("vimUsername", actualVim.getAccessInfo().getUsername()); + assertEquals(1, actualInstantiationRequest.getValue().getComputeResourceFlavours().size()); + assertEquals("flavourProviderId", actualInstantiationRequest.getValue().getComputeResourceFlavours().get(0).getResourceId()); + assertEquals(VIM_ID, actualInstantiationRequest.getValue().getComputeResourceFlavours().get(0).getVimId()); + assertEquals("virtualComputeDescId", actualInstantiationRequest.getValue().getComputeResourceFlavours().get(0).getVnfdVirtualComputeDescId()); + assertEquals(1, actualInstantiationRequest.getValue().getExtManagedVirtualLinks().size()); + assertEquals(extManVl, actualInstantiationRequest.getValue().getExtManagedVirtualLinks().get(0)); + assertEquals(2, actualInstantiationRequest.getValue().getExtVirtualLinks().size()); + + assertEquals("myNetworkProviderId", actualInstantiationRequest.getValue().getExtVirtualLinks().get(0).getResourceId()); + assertEquals("myEVlId", actualInstantiationRequest.getValue().getExtVirtualLinks().get(0).getExtVirtualLinkId()); + assertEquals(1, actualInstantiationRequest.getValue().getExtVirtualLinks().get(0).getExtCps().size()); + assertEquals("myCpdId", actualInstantiationRequest.getValue().getExtVirtualLinks().get(0).getExtCps().get(0).getCpdId()); + + assertEquals(VIM_ID, actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getVimId()); + assertEquals("evlId1", actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getExtVirtualLinkId()); + assertEquals("networkProviderId1", actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getResourceId()); + assertEquals(1, actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getExtCps().size()); + + + assertEquals(Integer.valueOf(2), actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getExtCps().get(0).getNumDynamicAddresses()); + assertEquals("cpdId3", actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getExtCps().get(0).getCpdId()); + assertEquals(1, actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getExtCps().get(0).getAddresses().size()); + assertEquals("1.2.3.4", actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getExtCps().get(0).getAddresses().get(0).getIp()); + assertEquals("mac", actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getExtCps().get(0).getAddresses().get(0).getMac()); + assertEquals("subnetId", actualInstantiationRequest.getValue().getExtVirtualLinks().get(1).getExtCps().get(0).getAddresses().get(0).getSubnetId()); + + assertEquals("myFlavorId", actualInstantiationRequest.getValue().getFlavourId()); + assertEquals(Boolean.TRUE, actualInstantiationRequest.getValue().isGrantlessMode()); + assertEquals("level1", actualInstantiationRequest.getValue().getInstantiationLevelId()); + assertEquals(1, actualInstantiationRequest.getValue().getZones().size()); + assertEquals(VIM_ID, actualInstantiationRequest.getValue().getZones().get(0).getVimId()); + assertEquals("zoneProviderId", actualInstantiationRequest.getValue().getZones().get(0).getResourceId()); + assertEquals("zoneId", actualInstantiationRequest.getValue().getZones().get(0).getId()); + assertEquals(1, actualInstantiationRequest.getValue().getSoftwareImages().size()); + assertEquals(VIM_ID, actualInstantiationRequest.getValue().getSoftwareImages().get(0).getVimId()); + assertEquals("imageProviderId", actualInstantiationRequest.getValue().getSoftwareImages().get(0).getResourceId()); + assertEquals("imageId", actualInstantiationRequest.getValue().getSoftwareImages().get(0).getVnfdSoftwareImageId()); + String actualEmbeddedAdditionParams = new Gson().toJson(actualInstantiationRequest.getValue().getAdditionalParams()); + assertTrue("{\"jobId\":\"myJobId\",\"a\":\"b\"}".equals(actualEmbeddedAdditionParams) || "{\"a\":\"b\",\"jobId\":\"myJobId\"}".equals(actualEmbeddedAdditionParams)); + assertTrue(actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertTrue(actualVim.getInterfaceInfo().isSkipCertificateHostnameCheck()); + + assertEquals(1, actualVnfModifyRequest.getAllValues().size()); + assertEquals(2, actualVnfModifyRequest.getValue().getExtensions().size()); + assertEquals(LifecycleManager.ONAP_CSAR_ID, actualVnfModifyRequest.getValue().getExtensions().get(0).getName()); + assertEquals(ONAP_CSAR_ID, actualVnfModifyRequest.getValue().getExtensions().get(0).getValue()); + assertEquals(ILifecycleChangeNotificationManager.EXTERNAL_VNFM_ID, actualVnfModifyRequest.getValue().getExtensions().get(1).getName()); + assertEquals(VNFM_ID, actualVnfModifyRequest.getValue().getExtensions().get(1).getValue()); + + //the 3.2 API does not accept empty array + assertNull(actualVnfModifyRequest.getValue().getVnfConfigurableProperties()); + verify(jobManager).spawnJob(VNF_ID, restResponse); + } + + /** + * invalid VIM type results in failure + */ + @Test + public void testInstantiationWithInvalidVimType() throws Exception { + //given + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OTHER_VIM_INFO); + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + //when + try { + lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + //verify + fail(); + } catch (Exception e) { + assertEquals("Only OPENSTACK_V2_INFO, OPENSTACK_V3_INFO and VMWARE_VCLOUD_INFO is the supported VIM types", e.getMessage()); + } + verify(vnfApi, never()).vnfsPost(Mockito.any(), Mockito.any()); + verify(logger).error("Only OPENSTACK_V2_INFO, OPENSTACK_V3_INFO and VMWARE_VCLOUD_INFO is the supported VIM types"); + } + + /** + * test instantiation with KeyStone V2 based with SSL + */ + @Test + public void testInstantiationV2WithSsl() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + String caCert = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/localhost.cert.pem").toURI()))); + vimInfo.setSslInsecure("false"); + vimInfo.setSslCacert(caCert); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(instantiationOperationExecution); + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualInstantiationRequest.getValue().getVims().size()); + //verify + OPENSTACKV2INFO actualVim = (OPENSTACKV2INFO) actualInstantiationRequest.getValue().getVims().get(0); + assertEquals(StoreLoader.getCertifacates(caCert).iterator().next(), new String(actualVim.getInterfaceInfo().getTrustedCertificates().get(0))); + assertTrue(!actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertTrue(!actualVim.getInterfaceInfo().isSkipCertificateHostnameCheck()); + } + + /** + * test instantiation with KeyStone V3 based + */ + @Test + public void testInstantiationV3() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V3_INFO); + + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(instantiationOperationExecution); + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualInstantiationRequest.getValue().getVims().size()); + //verify + OPENSTACKV3INFO actualVim = (OPENSTACKV3INFO) actualInstantiationRequest.getValue().getVims().get(0); + assertEquals(VIM_ID, actualVim.getId()); + assertEquals(VimInfo.VimInfoTypeEnum.OPENSTACK_V3_INFO, actualVim.getVimInfoType()); + assertEquals(Boolean.valueOf(parseBoolean(vimInfo.getSslInsecure())), actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertEquals("cloudUrl", actualVim.getInterfaceInfo().getEndpoint()); + //FIXME assertEquals();actualVim.getInterfaceInfo().getTrustedCertificates()); + assertEquals("vimPassword", actualVim.getAccessInfo().getPassword()); + assertEquals("regionId", actualVim.getAccessInfo().getRegion()); + assertEquals("myTenant", actualVim.getAccessInfo().getProject()); + assertEquals("myDomain", actualVim.getAccessInfo().getDomain()); + assertEquals("vimUsername", actualVim.getAccessInfo().getUsername()); + assertTrue(actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertTrue(actualVim.getInterfaceInfo().isSkipCertificateHostnameCheck()); + } + + /** + * test instantiation with KeyStone V3 based with SSL + */ + @Test + public void testInstantiationV3WithSsl() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V3_INFO); + + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + String caCert = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/localhost.cert.pem").toURI()))); + vimInfo.setSslInsecure("false"); + vimInfo.setSslCacert(caCert); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(instantiationOperationExecution); + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualInstantiationRequest.getValue().getVims().size()); + //verify + OPENSTACKV3INFO actualVim = (OPENSTACKV3INFO) actualInstantiationRequest.getValue().getVims().get(0); + assertEquals(VIM_ID, actualVim.getId()); + assertEquals(VimInfo.VimInfoTypeEnum.OPENSTACK_V3_INFO, actualVim.getVimInfoType()); + assertEquals(Boolean.valueOf(parseBoolean(vimInfo.getSslInsecure())), actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertEquals("cloudUrl", actualVim.getInterfaceInfo().getEndpoint()); + //FIXME assertEquals();actualVim.getInterfaceInfo().getTrustedCertificates()); + assertEquals("vimPassword", actualVim.getAccessInfo().getPassword()); + assertEquals("regionId", actualVim.getAccessInfo().getRegion()); + assertEquals("myTenant", actualVim.getAccessInfo().getProject()); + assertEquals("myDomain", actualVim.getAccessInfo().getDomain()); + assertEquals("vimUsername", actualVim.getAccessInfo().getUsername()); + assertEquals(StoreLoader.getCertifacates(caCert).iterator().next(), new String(actualVim.getInterfaceInfo().getTrustedCertificates().get(0))); + assertTrue(!actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertTrue(!actualVim.getInterfaceInfo().isSkipCertificateHostnameCheck()); + } + + /** + * test instantiation with vcloud + */ + @Test + public void testInstantiationVcloud() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.VMWARE_VCLOUD_INFO); + + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(instantiationOperationExecution); + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualInstantiationRequest.getValue().getVims().size()); + //verify + VMWAREVCLOUDINFO actualVim = (VMWAREVCLOUDINFO) actualInstantiationRequest.getValue().getVims().get(0); + assertEquals(VIM_ID, actualVim.getId()); + assertEquals(VimInfo.VimInfoTypeEnum.VMWARE_VCLOUD_INFO, actualVim.getVimInfoType()); + assertEquals(Boolean.valueOf(parseBoolean(vimInfo.getSslInsecure())), actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertEquals("cloudUrl", actualVim.getInterfaceInfo().getEndpoint()); + //FIXME assertEquals();actualVim.getInterfaceInfo().getTrustedCertificates()); + assertEquals("vimPassword", actualVim.getAccessInfo().getPassword()); + assertEquals("regionId", actualVim.getAccessInfo().getOrganization()); + assertEquals("vimUsername", actualVim.getAccessInfo().getUsername()); + assertTrue(actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertTrue(actualVim.getInterfaceInfo().isSkipCertificateHostnameCheck()); + } + + /** + * test instantiation with vCloud with SSL + */ + @Test + public void testInstantiationVcloudWithSsl() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.VMWARE_VCLOUD_INFO); + + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + String caCert = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/localhost.cert.pem").toURI()))); + vimInfo.setSslInsecure("false"); + vimInfo.setSslCacert(caCert); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(instantiationOperationExecution); + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualInstantiationRequest.getValue().getVims().size()); + //verify + VMWAREVCLOUDINFO actualVim = (VMWAREVCLOUDINFO) actualInstantiationRequest.getValue().getVims().get(0); + assertEquals(VIM_ID, actualVim.getId()); + assertEquals(VimInfo.VimInfoTypeEnum.VMWARE_VCLOUD_INFO, actualVim.getVimInfoType()); + assertEquals(Boolean.valueOf(parseBoolean(vimInfo.getSslInsecure())), actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertEquals("cloudUrl", actualVim.getInterfaceInfo().getEndpoint()); + //FIXME assertEquals();actualVim.getInterfaceInfo().getTrustedCertificates()); + assertEquals("vimPassword", actualVim.getAccessInfo().getPassword()); + assertEquals("regionId", actualVim.getAccessInfo().getOrganization()); + assertEquals("vimUsername", actualVim.getAccessInfo().getUsername()); + assertEquals(StoreLoader.getCertifacates(caCert).iterator().next(), new String(actualVim.getInterfaceInfo().getTrustedCertificates().get(0))); + assertTrue(!actualVim.getInterfaceInfo().isSkipCertificateVerification()); + assertTrue(!actualVim.getInterfaceInfo().isSkipCertificateHostnameCheck()); + } + + /** + * test failure in the instantiation request marks the job to be finished in job manager + */ + @Test + public void testFailureInTheInstantiationRequest() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenThrow(expectedException); + + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + //verfiy + waitForJobToFinishInJobManager(finished); + assertEquals(VNF_ID, response.getVnfInstanceId()); + assertEquals(JOB_ID, response.getJobId()); + verify(logger).error("Unable to instantiate VNF with myVnfId identifier", expectedException); + } + + /** + * instantiation fails if VF-C does not send vim identifier in grant response + */ + @Test + public void testVfcFailsToSendVimId() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + //grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + String caCert = new String(readAllBytes(Paths.get(TestVfcGrantManager.class.getResource("/unittests/localhost.cert.pem").toURI()))); + vimInfo.setSslInsecure("false"); + vimInfo.setSslCacert(caCert); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(instantiationOperationExecution); + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + waitForJobToFinishInJobManager(finished); + assertEquals(0, actualInstantiationRequest.getAllValues().size()); + //verify + verify(logger).error("VF-C did not send VIM identifier in grant response"); + + } + + /** + * test operation execution polling is retried in case of failures + */ + @Test + public void testFailureInTheOperationExecutionPollingDuringInstantiationRequest() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + additionalParam.setInstantiationLevel(INSTANTIATION_LEVEL); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + grantResponse.setAccessInfo(accessInfo); + ArgumentCaptor<InstantiateVnfRequest> actualInstantiationRequest = ArgumentCaptor.forClass(InstantiateVnfRequest.class); + ApiException expectedException = new ApiException(); + List<ApiException> polling = new ArrayList<>(); + when(vnfApi.vnfsVnfInstanceIdInstantiatePost(eq(VNF_ID), actualInstantiationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(instantiationOperationExecution); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).then(new Answer<List<OperationExecution>>() { + @Override + public List<OperationExecution> answer(InvocationOnMock invocation) throws Throwable { + if (polling.size() > 2) { + return operationExecutions; + } + ApiException apiException = new ApiException(); + polling.add(apiException); + throw apiException; + } + }); + //when + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + //verfiy + waitForJobToFinishInJobManager(finished); + assertEquals(VNF_ID, response.getVnfInstanceId()); + assertEquals(JOB_ID, response.getJobId()); + assertEquals(3, polling.size()); + for (ApiException e : polling) { + verify(logger).warn("Unable to retrieve operations details", e); + } + verify(systemFunctions, Mockito.times(3)).sleep(5000); + } + + /** + * failure in VNF creation is logged an proagated + */ + @Test + public void failureInVnfCreationIsPropagated() throws Exception { + //given + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenThrow(expectedException); + //when + try { + lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + //verify + fail(); + } catch (RuntimeException e) { + assertEquals(expectedException, e.getCause()); + verify(logger).error("Unable to create the VNF", expectedException); + } + } + + /** + * failure in updating the modifyable attributes of the VNF is logged an proagated + */ + @Test + public void failureInVnfModificationIsPropagated() throws Exception { + //given + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + when(vnfApi.vnfsVnfInstanceIdPatch(eq(VNF_ID), actualVnfModifyRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenThrow(expectedException); + + //when + try { + lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + //verify + fail(); + } catch (RuntimeException e) { + assertEquals(expectedException, e.getCause().getCause()); + verify(logger).error("Unable to set the onapCsarId property on the VNF", expectedException); + } + } + + /** + * if the VIM info can not be queried the VNF is not instantiated and + * error propagated through job + */ + @Test + public void testFailureInQueryVimInfo() throws Exception { + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + when(vnfApi.vnfsPost(createRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenReturn(vnfInfo); + when(vfcGrantManager.requestGrantForInstantiate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, INSTANTIATION_LEVEL, cbamVnfdContent, JOB_ID)).thenReturn(grantResponse); + grantResponse.setVimId(VIM_ID); + GrantVNFResponseVimAccessInfo accessInfo = new GrantVNFResponseVimAccessInfo(); + accessInfo.setTenant(TENANT); + grantResponse.setAccessInfo(accessInfo); + + when(vimInfoProvider.getVimInfo(VIM_ID)).thenThrow(new RuntimeException()); + //when + lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + verify(vnfApi, never()).vnfsVnfInstanceIdInstantiatePost(Mockito.any(), Mockito.any(), Mockito.any()); + } + + /** + * 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(vnfInfo); + vnfInfo.setInstantiationState(InstantiationState.INSTANTIATED); + vnfInfo.setOperationExecutions(operationExecutions); + VnfProperty vnfdId = new VnfProperty(); + vnfdId.setName(LifecycleManager.ONAP_CSAR_ID); + vnfdId.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(vnfdId); + ArgumentCaptor<TerminateVnfRequest> actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + OperationExecution terminationOperation = new OperationExecution(); + terminationOperation.setId("terminationId"); + operationExecutions.add(terminationOperation); + terminationOperation.setStatus(OperationStatus.FINISHED); + return terminationOperation; + } + }); + JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } "); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(instantiationParameters); + //when + JobInfo jobInfo = lifecycleManager.terminateVnf(VNFM_ID, VNF_ID, terminationRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualTerminationRequest.getAllValues().size()); + assertEquals(TerminationType.FORCEFUL, actualTerminationRequest.getValue().getTerminationType()); + 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"); + notificationIsProcessedBeforeDeletingTheVnf.verify(vnfApi).vnfsVnfInstanceIdDelete(VNF_ID, NOKIA_LCM_API_VERSION); + verify(jobManager).spawnJob(VNF_ID, restResponse); + } + + /** + * test termination of a non instantiated VNF + * - the VNF is not terminated (only deleted) + */ + @Test + public void testTerminationOfNonInstantiated() throws Exception { + //given + VnfTerminateRequest terminationRequest = new VnfTerminateRequest(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + vnfInfo.setInstantiationState(InstantiationState.NOT_INSTANTIATED); + vnfInfo.setOperationExecutions(operationExecutions); + VnfProperty vnfdId = new VnfProperty(); + vnfdId.setName(LifecycleManager.ONAP_CSAR_ID); + vnfdId.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(vnfdId); + JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } "); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(instantiationParameters); + //when + JobInfo jobInfo = lifecycleManager.terminateVnf(VNFM_ID, VNF_ID, terminationRequest, restResponse); + //verify + boolean deleted = false; + while (!deleted) { + try { + Mockito. + verify(vnfApi).vnfsVnfInstanceIdDelete(VNF_ID, NOKIA_LCM_API_VERSION); + deleted = true; + } catch (Error e) { + } + } + verify(vfcGrantManager, never()).requestGrantForTerminate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, vnfInfo, JOB_ID); + verify(notificationManager, never()).waitForTerminationToBeProcessed("terminationId"); + } + + /** + * test that the VNF deletion is not started before the termination finishes + */ + @Test + public void testTerminationOperationIsOutwaited() throws Exception { + //given + VnfTerminateRequest terminationRequest = new VnfTerminateRequest(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + vnfInfo.setInstantiationState(InstantiationState.INSTANTIATED); + vnfInfo.setOperationExecutions(operationExecutions); + VnfProperty vnfdId = new VnfProperty(); + vnfdId.setName(LifecycleManager.ONAP_CSAR_ID); + vnfdId.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(vnfdId); + ArgumentCaptor<TerminateVnfRequest> actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class); + OperationExecution terminationOperation = new OperationExecution(); + when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + terminationOperation.setId("terminationId"); + operationExecutions.add(terminationOperation); + terminationOperation.setStatus(OperationStatus.STARTED); + return terminationOperation; + } + }); + JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } "); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(instantiationParameters); + Set<Integer> calls = new HashSet<>(); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenAnswer(new Answer<List<OperationExecution>>() { + @Override + public List<OperationExecution> answer(InvocationOnMock invocation) throws Throwable { + if (calls.size() == 1000) { + terminationOperation.setStatus(OperationStatus.FINISHED); + } + calls.add(calls.size()); + return operationExecutions; + } + }); + //when + JobInfo jobInfo = lifecycleManager.terminateVnf(VNFM_ID, VNF_ID, terminationRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + verify(vnfApi, times(1001)).vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION); + verify(systemFunctions, times(1000)).sleep(5000); + } + + + /** + * test that failured during waiting for the operation to finish is tolerated (idefineiatelly) + */ + @Test + public void testTerminationOperationIsOutwaitedWithErrors() throws Exception { + //given + VnfTerminateRequest terminationRequest = new VnfTerminateRequest(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + vnfInfo.setInstantiationState(InstantiationState.INSTANTIATED); + vnfInfo.setOperationExecutions(operationExecutions); + VnfProperty vnfdId = new VnfProperty(); + vnfdId.setName(LifecycleManager.ONAP_CSAR_ID); + vnfdId.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(vnfdId); + ArgumentCaptor<TerminateVnfRequest> actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class); + OperationExecution terminationOperation = new OperationExecution(); + when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + terminationOperation.setId("terminationId"); + operationExecutions.add(terminationOperation); + terminationOperation.setStatus(OperationStatus.STARTED); + return terminationOperation; + } + }); + JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } "); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(instantiationParameters); + Set<Integer> calls = new HashSet<>(); + List<ApiException> expectedExceptions = new ArrayList<>(); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenAnswer(new Answer<List<OperationExecution>>() { + @Override + public List<OperationExecution> answer(InvocationOnMock invocation) throws Throwable { + if (calls.size() >= 100) { + terminationOperation.setStatus(OperationStatus.FINISHED); + return operationExecutions; + } + calls.add(calls.size()); + ApiException apiException = new ApiException(); + expectedExceptions.add(apiException); + throw apiException; + } + }); + //when + JobInfo jobInfo = lifecycleManager.terminateVnf(VNFM_ID, VNF_ID, terminationRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + verify(vnfApi, times(101)).vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION); + verify(systemFunctions, times(100)).sleep(5000); + for (ApiException expectedException : expectedExceptions) { + verify(logger).warn("Unable to retrieve operations details", expectedException); + } + } + + /** + * test gracefull termination + */ + @Test + public void testGracefullTermination() throws Exception { + //given + VnfTerminateRequest terminationRequest = new VnfTerminateRequest(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + terminationRequest.setTerminationType(VnfTerminationType.GRACEFUL); + terminationRequest.setGracefulTerminationTimeout("1234"); + vnfInfo.setInstantiationState(InstantiationState.INSTANTIATED); + vnfInfo.setOperationExecutions(operationExecutions); + VnfProperty vnfdId = new VnfProperty(); + vnfdId.setName(LifecycleManager.ONAP_CSAR_ID); + vnfdId.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(vnfdId); + ArgumentCaptor<TerminateVnfRequest> actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + OperationExecution terminationOperation = new OperationExecution(); + terminationOperation.setId("terminationId"); + operationExecutions.add(terminationOperation); + terminationOperation.setStatus(OperationStatus.FINISHED); + return terminationOperation; + } + }); + doAnswer(invocation -> { + verify(jobManager, Mockito.never()).jobFinished(JOB_ID); + return null; + }).when(vnfApi).vnfsVnfInstanceIdDelete(VNF_ID, NOKIA_LCM_API_VERSION); + JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } "); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(instantiationParameters); + //when + JobInfo jobInfo = lifecycleManager.terminateVnf(VNFM_ID, VNF_ID, terminationRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualTerminationRequest.getAllValues().size()); + assertEquals(TerminationType.GRACEFUL, actualTerminationRequest.getValue().getTerminationType()); + assertEquals(Integer.valueOf(1234), actualTerminationRequest.getValue().getGracefulTerminationTimeout()); + 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"); + notificationIsProcessedBeforeDeletingTheVnf.verify(vnfApi).vnfsVnfInstanceIdDelete(VNF_ID, NOKIA_LCM_API_VERSION); + } + + /** + * instantiation with missing ONAP csarId to instantiation extra param result in failure + */ + @Test + public void testMissingVnfParameters() throws Exception { + //given + VnfInstantiateRequest instantiationRequest = prepareInstantiationRequest(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + String src = "{ \"inputs\" : { \"vnfs\" : { \"" + ONAP_CSAR_ID + "invalid" + "\" : {}}}, \"vimId\" : \"" + VIM_ID + "\"}"; + instantiationRequest.setAdditionalParam(new JsonParser().parse(src)); + //when + try { + VnfInstantiateResponse response = lifecycleManager.instantiate(VNFM_ID, instantiationRequest, restResponse); + fail(); + } catch (Exception e) { + assertEquals("The additional parameter section does not contain setting for VNF with myOnapCsarId CSAR id", e.getMessage()); + verify(logger).error("The additional parameter section does not contain setting for VNF with myOnapCsarId CSAR id"); + } + } + + /** + * test explicit forceful termination + */ + @Test + public void testExplicitForcefulTermination() throws Exception { + //given + VnfTerminateRequest terminationRequest = new VnfTerminateRequest(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + terminationRequest.setTerminationType(VnfTerminationType.FORCEFUL); + terminationRequest.setGracefulTerminationTimeout("1234"); + vnfInfo.setInstantiationState(InstantiationState.INSTANTIATED); + vnfInfo.setOperationExecutions(operationExecutions); + VnfProperty vnfdId = new VnfProperty(); + vnfdId.setName(LifecycleManager.ONAP_CSAR_ID); + vnfdId.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(vnfdId); + ArgumentCaptor<TerminateVnfRequest> actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + OperationExecution terminationOperation = new OperationExecution(); + terminationOperation.setId("terminationId"); + operationExecutions.add(terminationOperation); + terminationOperation.setStatus(OperationStatus.FINISHED); + return terminationOperation; + } + }); + doAnswer(invocation -> { + verify(jobManager, Mockito.never()).jobFinished(JOB_ID); + return null; + }).when(vnfApi).vnfsVnfInstanceIdDelete(VNF_ID, NOKIA_LCM_API_VERSION); + JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } "); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(instantiationParameters); + //when + JobInfo jobInfo = lifecycleManager.terminateVnf(VNFM_ID, VNF_ID, terminationRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualTerminationRequest.getAllValues().size()); + assertEquals(TerminationType.FORCEFUL, actualTerminationRequest.getValue().getTerminationType()); + assertNull(actualTerminationRequest.getValue().getGracefulTerminationTimeout()); + 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"); + notificationIsProcessedBeforeDeletingTheVnf.verify(vnfApi).vnfsVnfInstanceIdDelete(VNF_ID, NOKIA_LCM_API_VERSION); + } + + /** + * test failure in the termination workflow finishes the job + */ + @Test + public void testFailureInTheTerminationFinishesTheManagedJob() throws Exception { + //given + VnfTerminateRequest terminationRequest = new VnfTerminateRequest(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + terminationRequest.setTerminationType(VnfTerminationType.FORCEFUL); + terminationRequest.setGracefulTerminationTimeout("1234"); + vnfInfo.setInstantiationState(InstantiationState.INSTANTIATED); + vnfInfo.setOperationExecutions(operationExecutions); + VnfProperty vnfdId = new VnfProperty(); + vnfdId.setName(LifecycleManager.ONAP_CSAR_ID); + vnfdId.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(vnfdId); + ArgumentCaptor<TerminateVnfRequest> actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + OperationExecution terminationOperation = new OperationExecution(); + terminationOperation.setId("terminationId"); + operationExecutions.add(terminationOperation); + terminationOperation.setStatus(OperationStatus.FINISHED); + return terminationOperation; + } + }); + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } "); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(instantiationParameters); + //when + JobInfo jobInfo = lifecycleManager.terminateVnf(VNFM_ID, VNF_ID, terminationRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(0, actualTerminationRequest.getAllValues().size()); + Mockito.verifyZeroInteractions(vfcGrantManager); + } + + /** + * if termination fails the VNF is not deleted + */ + @Test + public void testFailedTerminationAbortsTerminationWorkflow() throws Exception { + //given + VnfTerminateRequest terminationRequest = new VnfTerminateRequest(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + vnfInfo.setInstantiationState(InstantiationState.INSTANTIATED); + vnfInfo.setOperationExecutions(operationExecutions); + VnfProperty vnfdId = new VnfProperty(); + vnfdId.setName(LifecycleManager.ONAP_CSAR_ID); + vnfdId.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(vnfdId); + ArgumentCaptor<TerminateVnfRequest> actualTerminationRequest = ArgumentCaptor.forClass(TerminateVnfRequest.class); + when(vnfApi.vnfsVnfInstanceIdTerminatePost(eq(VNF_ID), actualTerminationRequest.capture(), eq(NOKIA_LCM_API_VERSION))).thenAnswer(new Answer<OperationExecution>() { + @Override + public OperationExecution answer(InvocationOnMock invocation) throws Throwable { + OperationExecution terminationOperation = new OperationExecution(); + terminationOperation.setId("terminationId"); + operationExecutions.add(terminationOperation); + terminationOperation.setStatus(OperationStatus.FAILED); + return terminationOperation; + } + }); + JsonElement instantiationParameters = new JsonParser().parse("{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] } "); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet("operationExecutionId", NOKIA_LCM_API_VERSION)).thenReturn(instantiationParameters); + //when + JobInfo jobInfo = lifecycleManager.terminateVnf(VNFM_ID, VNF_ID, terminationRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualTerminationRequest.getAllValues().size()); + assertEquals(TerminationType.FORCEFUL, actualTerminationRequest.getValue().getTerminationType()); + verify(vfcGrantManager).requestGrantForTerminate(VNFM_ID, VNF_ID, VIM_ID, ONAP_CSAR_ID, vnfInfo, JOB_ID); + verify(vnfApi, never()).vnfsVnfInstanceIdDelete(VNF_ID, NOKIA_LCM_API_VERSION); + verify(logger).error("Unable to terminate VNF the operation did not finish with success"); + } + + /** + * test VNF query basic success scenario + */ + @Test + public void testQuery() throws Exception { + vnfInfo.setDescription("myDescription"); + vnfInfo.setName("myName"); + vnfInfo.setVnfSoftwareVersion("vnfSoftwareVersion"); + vnfInfo.setVnfProvider("myProvider"); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + VnfProperty prop = new VnfProperty(); + prop.setName(LifecycleManager.ONAP_CSAR_ID); + prop.setValue(ONAP_CSAR_ID); + vnfInfo.getExtensions().add(prop); + //when + org.onap.vnfmdriver.model.VnfInfo vnf = lifecycleManager.queryVnf(VNFM_ID, VNF_ID); + //verify + assertEquals(VNF_ID, vnf.getVnfInstanceId()); + //FIXME ? (do not know what exactly the vnf version mean in core terminology) + assertEquals("vnfSoftwareVersion", vnf.getVersion()); + assertEquals(ONAP_CSAR_ID, vnf.getVnfdId()); + assertEquals("myDescription", vnf.getVnfInstanceDescription()); + assertEquals("myName", vnf.getVnfInstanceName()); + assertEquals(ONAP_CSAR_ID, vnf.getVnfPackageId()); + assertEquals("myProvider", vnf.getVnfProvider()); + //FIXME (in swagger schema ) + assertEquals("ACTIVE", vnf.getVnfStatus()); + assertEquals("Kuku", vnf.getVnfType()); + } + + /** + * error is propagated and logged if the queried VNF does not exist + */ + @Test + public void testQueryForNonExistingVnf() throws Exception { + + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //when + try { + lifecycleManager.queryVnf(VNFM_ID, VNF_ID); + //verify + fail(); + } catch (Exception e) { + verify(logger).error("Unable to query VNF (myVnfId)", expectedException); + assertEquals(expectedException, e.getCause()); + } + } + + /** + * test scale basic scenario + */ + @Test + public void testScale() throws Exception { + VnfScaleRequest scaleRequest = new VnfScaleRequest(); + scaleRequest.setNumberOfSteps("2"); + scaleRequest.setAspectId("myAspect"); + scaleRequest.setType(ScaleDirection.IN); + scaleRequest.setAdditionalParam(new JsonParser().parse("{ \"a\" : \"b\", \"c\" : \"d\" }")); + scaleOperationExecution.setStatus(OperationStatus.FINISHED); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + VnfProperty prop = new VnfProperty(); + prop.setValue(ONAP_CSAR_ID); + prop.setName(LifecycleManager.ONAP_CSAR_ID); + vnfInfo.getExtensions().add(prop); + vnfInfo.getOperationExecutions().add(instantiationOperationExecution); + String instantiationParams = "{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] }"; + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(new JsonParser().parse(instantiationParams)); + //when + JobInfo job = lifecycleManager.scaleVnf(VNFM_ID, VNF_ID, scaleRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualScaleRequest.getAllValues().size()); + ScaleVnfRequest sRequest = actualScaleRequest.getValue(); + InOrder workflowOrder = Mockito.inOrder(vfcGrantManager, vnfApi); + workflowOrder.verify(vfcGrantManager).requestGrantForScale(eq(VNFM_ID), eq(VNF_ID), eq(VIM_ID), eq(ONAP_CSAR_ID), eq(scaleRequest), eq(JOB_ID)); + workflowOrder.verify(vnfApi).vnfsVnfInstanceIdScalePost(VNF_ID, sRequest, NOKIA_LCM_API_VERSION); + assertEquals("myAspect", sRequest.getAspectId()); + assertEquals(com.nokia.cbam.lcm.v32.model.ScaleDirection.IN, sRequest.getType()); + assertEquals(Integer.valueOf(2), sRequest.getNumberOfSteps()); + assertTrue("{\"jobId\":\"myJobId\",\"a\":\"b\"}".equals(new Gson().toJson(sRequest.getAdditionalParams())) || "{\"a\":\"b\",\"jobId\":\"myJobId\"}".equals(new Gson().toJson(sRequest.getAdditionalParams()))); + verify(jobManager).spawnJob(VNF_ID, restResponse); + } + + /** + * test scale out basic scenario + */ + @Test + public void testScaleOut() throws Exception { + VnfScaleRequest scaleRequest = new VnfScaleRequest(); + scaleRequest.setNumberOfSteps("2"); + scaleRequest.setAspectId("myAspect"); + scaleRequest.setType(ScaleDirection.OUT); + scaleRequest.setAdditionalParam(new JsonParser().parse("{ \"a\" : \"b\" }")); + scaleOperationExecution.setStatus(OperationStatus.FINISHED); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + VnfProperty prop = new VnfProperty(); + prop.setValue(ONAP_CSAR_ID); + prop.setName(LifecycleManager.ONAP_CSAR_ID); + vnfInfo.getExtensions().add(prop); + vnfInfo.getOperationExecutions().add(instantiationOperationExecution); + String instantiationParams = "{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] }"; + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(new JsonParser().parse(instantiationParams)); + //when + JobInfo job = lifecycleManager.scaleVnf(VNFM_ID, VNF_ID, scaleRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualScaleRequest.getAllValues().size()); + ScaleVnfRequest sRequest = actualScaleRequest.getValue(); + InOrder workflowOrder = Mockito.inOrder(vfcGrantManager, vnfApi); + workflowOrder.verify(vfcGrantManager).requestGrantForScale(eq(VNFM_ID), eq(VNF_ID), eq(VIM_ID), eq(ONAP_CSAR_ID), eq(scaleRequest), eq(JOB_ID)); + workflowOrder.verify(vnfApi).vnfsVnfInstanceIdScalePost(VNF_ID, sRequest, NOKIA_LCM_API_VERSION); + assertEquals("myAspect", sRequest.getAspectId()); + assertEquals(com.nokia.cbam.lcm.v32.model.ScaleDirection.OUT, sRequest.getType()); + assertEquals(Integer.valueOf(2), sRequest.getNumberOfSteps()); + assertTrue("{\"jobId\":\"myJobId\",\"a\":\"b\"}".equals(new Gson().toJson(sRequest.getAdditionalParams())) || "{\"a\":\"b\",\"jobId\":\"myJobId\"}".equals(new Gson().toJson(sRequest.getAdditionalParams()))); + } + + /** + * test scale operation is out waited + */ + @Test + public void testScaleOutwait() throws Exception { + VnfScaleRequest scaleRequest = new VnfScaleRequest(); + scaleRequest.setNumberOfSteps("2"); + scaleRequest.setAspectId("myAspect"); + scaleRequest.setType(ScaleDirection.IN); + scaleRequest.setAdditionalParam(new JsonParser().parse("{ \"a\" : \"b\" }")); + scaleOperationExecution.setStatus(OperationStatus.STARTED); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + VnfProperty prop = new VnfProperty(); + prop.setValue(ONAP_CSAR_ID); + prop.setName(LifecycleManager.ONAP_CSAR_ID); + vnfInfo.getExtensions().add(prop); + vnfInfo.getOperationExecutions().add(instantiationOperationExecution); + String instantiationParams = "{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] }"; + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(new JsonParser().parse(instantiationParams)); + List<ApiException> expectedExceptions = new ArrayList<>(); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenAnswer((Answer<List<OperationExecution>>) invocation -> { + if (expectedExceptions.size() >= 100) { + scaleOperationExecution.setStatus(OperationStatus.FINISHED); + return operationExecutions; + } + ApiException apiException = new ApiException(); + expectedExceptions.add(apiException); + // when(operationExecutionApi.operationExecutionsOperationExecutionIdGet(scaleOperationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(scaleOperationExecution); + throw apiException; + }); + + //when + JobInfo job = lifecycleManager.scaleVnf(VNFM_ID, VNF_ID, scaleRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(100, expectedExceptions.size()); + for (ApiException expectedException : expectedExceptions) { + verify(logger).warn("Unable to retrieve operations details", expectedException); + } + verify(systemFunctions, times(100)).sleep(5000); + } + + /** + * test scale failure propagation + */ + @Test + public void testScaleFailurePropagation() throws Exception { + ApiException expectedException = new ApiException(); + VnfScaleRequest scaleRequest = new VnfScaleRequest(); + scaleRequest.setNumberOfSteps("2"); + scaleRequest.setAspectId("myAspect"); + scaleRequest.setType(ScaleDirection.IN); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //when + lifecycleManager.scaleVnf(VNFM_ID, VNF_ID, scaleRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + verify(logger).error("Unable to scale VNF with myVnfId identifier", expectedException); + } + + /** + * test heal basic scenario + */ + @Test + public void testHeal() throws Exception { + VnfHealRequest healRequest = new VnfHealRequest(); + healRequest.setAction("myAction"); + VnfHealRequestAffectedvm affectedVm = new VnfHealRequestAffectedvm(); + affectedVm.setVmname("vmName"); + healRequest.setAffectedvm(affectedVm); + healOperationExecution.setStatus(OperationStatus.FINISHED); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + VnfProperty prop = new VnfProperty(); + prop.setValue(ONAP_CSAR_ID); + prop.setName(LifecycleManager.ONAP_CSAR_ID); + vnfInfo.getExtensions().add(prop); + vnfInfo.getOperationExecutions().add(instantiationOperationExecution); + String instantiationParams = "{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] }"; + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(new JsonParser().parse(instantiationParams)); + //when + JobInfo job = lifecycleManager.healVnf(VNFM_ID, VNF_ID, healRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(1, actualHealRequest.getAllValues().size()); + HealVnfRequest sRequest = actualHealRequest.getValue(); + InOrder workflowOrder = Mockito.inOrder(vfcGrantManager, vnfApi); + workflowOrder.verify(vfcGrantManager).requestGrantForHeal(eq(VNFM_ID), eq(VNF_ID), eq(VIM_ID), eq(ONAP_CSAR_ID), eq(healRequest), eq(JOB_ID)); + workflowOrder.verify(vnfApi).vnfsVnfInstanceIdHealPost(VNF_ID, sRequest, NOKIA_LCM_API_VERSION); + JsonObject root = new Gson().toJsonTree(sRequest.getAdditionalParams()).getAsJsonObject(); + assertEquals("myAction", root.get("action").getAsString()); + assertEquals("vmName", root.get("vmName").getAsString()); + assertEquals(JOB_ID, root.get("jobId").getAsString()); + verify(jobManager).spawnJob(VNF_ID, restResponse); + } + + /** + * test heal operation is out waited + */ + @Test + public void testHealOutwait() throws Exception { + VnfHealRequest healRequest = new VnfHealRequest(); + healRequest.setAction("myAction"); + VnfHealRequestAffectedvm affectedVm = new VnfHealRequestAffectedvm(); + affectedVm.setVmname("vmName"); + healRequest.setAffectedvm(affectedVm); + healOperationExecution.setStatus(OperationStatus.FINISHED); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnfInfo); + VnfProperty prop = new VnfProperty(); + prop.setValue(ONAP_CSAR_ID); + prop.setName(LifecycleManager.ONAP_CSAR_ID); + vnfInfo.getExtensions().add(prop); + vnfInfo.getOperationExecutions().add(instantiationOperationExecution); + String instantiationParams = "{ \"vims\" : [ { \"id\" : \"" + VIM_ID + "\" } ] }"; + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(new JsonParser().parse(instantiationParams)); + List<ApiException> expectedExceptions = new ArrayList<>(); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenAnswer(new Answer<List<OperationExecution>>() { + @Override + public List<OperationExecution> answer(InvocationOnMock invocation) throws Throwable { + if (expectedExceptions.size() >= 100) { + scaleOperationExecution.setStatus(OperationStatus.FINISHED); + return operationExecutions; + } + ApiException apiException = new ApiException(); + expectedExceptions.add(apiException); + throw apiException; + } + }); + //when + JobInfo job = lifecycleManager.healVnf(VNFM_ID, VNF_ID, healRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + assertEquals(100, expectedExceptions.size()); + for (ApiException expectedException : expectedExceptions) { + verify(logger).warn("Unable to retrieve operations details", expectedException); + } + verify(systemFunctions, times(100)).sleep(5000); + } + + /** + * failure in heal propagates in error + */ + @Test + public void testHealFailurePropagation() throws Exception { + ApiException expectedException = new ApiException(); + VnfHealRequest healRequest = new VnfHealRequest(); + healRequest.setAction("myAction"); + VnfHealRequestAffectedvm affectedVm = new VnfHealRequestAffectedvm(); + affectedVm.setVmname("vmName"); + healRequest.setAffectedvm(affectedVm); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //when + JobInfo job = lifecycleManager.healVnf(VNFM_ID, VNF_ID, healRequest, restResponse); + //verify + waitForJobToFinishInJobManager(finished); + verify(logger).error("Unable to heal VNF with myVnfId identifier", expectedException); + } + + private void waitForJobToFinishInJobManager(Set<Boolean> finished) throws InterruptedException { + while (finished.size() == 0) { + systemFunctions().sleep(100); + } + } + + private VnfInstantiateRequest prepareInstantiationRequest(VimInfo.VimInfoTypeEnum cloudType) { + VnfInstantiateRequest instantiationRequest = new VnfInstantiateRequest(); + instantiationRequest.setVnfPackageId(ONAP_CSAR_ID); + instantiationRequest.setVnfDescriptorId(ONAP_CSAR_ID); + instantiationRequest.setVnfInstanceDescription("myDescription"); + instantiationRequest.setVnfInstanceName("vnfName"); + additionalParam.setInstantiationLevel("level1"); + switch (cloudType) { + case OPENSTACK_V2_INFO: + additionalParam.setVimType(VimInfo.VimInfoTypeEnum.OPENSTACK_V2_INFO); + break; + case OPENSTACK_V3_INFO: + additionalParam.setVimType(VimInfo.VimInfoTypeEnum.OPENSTACK_V3_INFO); + additionalParam.setDomain("myDomain"); + break; + case VMWARE_VCLOUD_INFO: + additionalParam.setVimType(VimInfo.VimInfoTypeEnum.VMWARE_VCLOUD_INFO); + break; + default: + additionalParam.setVimType(VimInfo.VimInfoTypeEnum.OTHER_VIM_INFO); + } + + Map<String, List<NetworkAddress>> exteranalConnectionPointAddresses = new HashMap<>(); + exteranalConnectionPointAddresses.put("ecp1", new ArrayList<>()); + NetworkAddress networkAddress = new NetworkAddress(); + networkAddress.setIp("1.2.3.4"); + networkAddress.setMac("mac"); + networkAddress.setSubnetId("subnetId"); + exteranalConnectionPointAddresses.get("ecp1").add(networkAddress); + additionalParam.setExternalConnectionPointAddresses(exteranalConnectionPointAddresses); + VimComputeResourceFlavour flavor = new VimComputeResourceFlavour(); + flavor.setResourceId("flavourProviderId"); + flavor.setVimId(VIM_ID); + flavor.setVnfdVirtualComputeDescId("virtualComputeDescId"); + additionalParam.getComputeResourceFlavours().add(flavor); + ExtVirtualLinkData evl = new ExtVirtualLinkData(); + evl.setResourceId("networkProviderId1"); + evl.setVimId(VIM_ID); + evl.setExtVirtualLinkId("evlId1"); + VnfExtCpData ecp2 = new VnfExtCpData(); + ecp2.setCpdId("cpdId3"); + ecp2.setAddresses(new ArrayList<>()); + ecp2.getAddresses().add(networkAddress); + ecp2.setNumDynamicAddresses(2); + evl.getExtCps().add(ecp2); + additionalParam.getExtVirtualLinks().add(evl); + externalVirtualLink.setCpdId("myCpdId"); + externalVirtualLink.setResourceId("myNetworkProviderId"); + externalVirtualLink.setVlInstanceId("myEVlId"); + externalVirtualLink.setResourceSubnetId("notUsedSubnetId"); + instantiationRequest.setExtVirtualLink(new ArrayList<>()); + instantiationRequest.getExtVirtualLink().add(externalVirtualLink); + additionalParam.getExtManagedVirtualLinks().add(extManVl); + ZoneInfo zone = new ZoneInfo(); + zone.setId("zoneId"); + zone.setResourceId("zoneProviderId"); + zone.setVimId(VIM_ID); + additionalParam.getZones().add(zone); + VimSoftwareImage image = new VimSoftwareImage(); + image.setResourceId("imageProviderId"); + image.setVimId(VIM_ID); + image.setVnfdSoftwareImageId("imageId"); + additionalParam.getSoftwareImages().add(image); + additionalParam.setAdditionalParams(new JsonParser().parse("{ \"a\" : \"b\" }")); + String params = new Gson().toJson(additionalParam); + String src = "{ \"inputs\" : { \"vnfs\" : { \"" + ONAP_CSAR_ID + "\" : " + params + "}}, \"vimId\" : \"" + VIM_ID + "\"}"; + instantiationRequest.setAdditionalParam(new JsonParser().parse(src)); + return instantiationRequest; + } + + /** + * Test vimId decomposition + */ + @Test + public void testVimIdSplitting() { + assertEquals("regionId", LifecycleManager.getRegionName("cloudOwner_regionId")); + assertEquals("cloudOwner", LifecycleManager.getCloudOwner("cloudOwner_regionId")); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestSelfRegistrationManager.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestSelfRegistrationManager.java new file mode 100644 index 00000000..79ec1a83 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/TestSelfRegistrationManager.java @@ -0,0 +1,345 @@ +/* + * 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.vnfm; + +import com.google.common.collect.Lists; +import com.nokia.cbam.lcn.v32.ApiException; +import com.nokia.cbam.lcn.v32.model.CreateSubscriptionRequest; +import com.nokia.cbam.lcn.v32.model.Subscription; +import com.nokia.cbam.lcn.v32.model.SubscriptionAuthentication; +import com.nokia.cbam.lcn.v32.model.VnfNotificationType; +import org.junit.Before; +import org.junit.Test; +import org.mockito.*; +import org.mockito.invocation.InvocationOnMock; +import org.mockito.stubbing.Answer; +import org.onap.msb.sdk.discovery.common.RouteException; +import org.onap.msb.sdk.discovery.entity.MicroServiceFullInfo; +import org.onap.msb.sdk.discovery.entity.MicroServiceInfo; +import org.onap.msb.sdk.discovery.entity.Node; +import org.onap.msb.sdk.discovery.entity.RouteResult; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.onap.core.SelfRegistrationManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.TestUtil; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.UUID; + +import static com.nokia.cbam.lcn.v32.model.OperationType.*; +import static junit.framework.TestCase.*; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.*; +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCN_API_VERSION; +import static org.springframework.test.util.ReflectionTestUtils.setField; + +public class TestSelfRegistrationManager extends TestBase { + @Mock + private JobManager jobManager; + private List<Subscription> subscriptions = new ArrayList<>(); + private ArgumentCaptor<MicroServiceInfo> registeredMicroservice = ArgumentCaptor.forClass(MicroServiceInfo.class); + private ArgumentCaptor<CreateSubscriptionRequest> subscriptionToCreate = ArgumentCaptor.forClass(CreateSubscriptionRequest.class); + @InjectMocks + private SelfRegistrationManager selfRegistrationManager; + + @Before + public void initMocks() throws Exception { + setField(SelfRegistrationManager.class, "logger", logger); + when(lcnApi.subscriptionsGet(NOKIA_LCN_API_VERSION)).thenReturn(subscriptions); + when(driverProperties.getVnfmId()).thenReturn(VNFM_ID); + setField(selfRegistrationManager, "driverMsbExternalIp", "1.2.3.4"); + setField(selfRegistrationManager, "driverVnfmExternalIp", "5.6.7.8"); + setField(selfRegistrationManager, "driverPort", "12345"); + Subscription unknownSubscription = new Subscription(); + unknownSubscription.setId(UUID.randomUUID().toString()); + unknownSubscription.setCallbackUrl("unknown"); + subscriptions.add(unknownSubscription); + } + + /** + * test the basic registration process + * - first subscribe to CBAM LCNs + * - second publish it's existence on MSB + */ + @Test + public void testRegistration() throws Exception { + //given + Subscription subscription = new Subscription(); + when(lcnApi.subscriptionsPost(subscriptionToCreate.capture(), Mockito.eq(NOKIA_LCN_API_VERSION))).thenReturn(subscription); + MicroServiceFullInfo returnedMicroService = new MicroServiceFullInfo(); + when(msbClient.registerMicroServiceInfo(registeredMicroservice.capture())).thenReturn(returnedMicroService); + //when + selfRegistrationManager.register(); + //verify + InOrder registrationOrder = Mockito.inOrder(lcnApi, msbClient); + registrationOrder.verify(lcnApi).subscriptionsPost(any(), any()); + registrationOrder.verify(msbClient).registerMicroServiceInfo(any()); + + assertMicroserviceRegistered(); + assertNewLcnSubscription(); + assertServiceUp(); + } + + private void assertNewLcnSubscription() { + CreateSubscriptionRequest subscriptionCreation = subscriptionToCreate.getValue(); + assertEquals("http://5.6.7.8:12345/api/NokiaSVNFM/v1/lcn", subscriptionCreation.getCallbackUrl()); + assertEquals(SubscriptionAuthentication.TypeEnum.NONE, subscriptionCreation.getAuthentication().getType()); + assertNull(subscriptionCreation.getAuthentication().getUserName()); + assertNull(subscriptionCreation.getAuthentication().getClientName()); + assertNull(subscriptionCreation.getAuthentication().getClientPassword()); + assertNull(subscriptionCreation.getAuthentication().getPassword()); + assertNull(subscriptionCreation.getAuthentication().getTokenUrl()); + assertNull(subscriptionCreation.getFilter().getVnfdId()); + assertNull(subscriptionCreation.getFilter().getVnfInstanceId()); + assertNull(subscriptionCreation.getFilter().getVnfProductName()); + assertNull(subscriptionCreation.getFilter().getVnfSoftwareVersion()); + assertEquals(Lists.newArrayList(VnfNotificationType.VNFLIFECYCLECHANGENOTIFICATION), subscriptionCreation.getFilter().getNotificationTypes()); + assertTrue(subscriptionCreation.getFilter().getOperationTypes().contains(HEAL)); + assertTrue(subscriptionCreation.getFilter().getOperationTypes().contains(SCALE)); + assertTrue(subscriptionCreation.getFilter().getOperationTypes().contains(TERMINATE)); + assertTrue(subscriptionCreation.getFilter().getOperationTypes().contains(INSTANTIATE)); + assertEquals(4, subscriptionCreation.getFilter().getOperationTypes().size()); + } + + private void assertMicroserviceRegistered() { + MicroServiceInfo microserviceRequest = registeredMicroservice.getValue(); + assertEquals(1, microserviceRequest.getNodes().size()); + Node node = microserviceRequest.getNodes().iterator().next(); + assertEquals("0", node.getTtl()); + assertEquals("1.2.3.4", node.getIp()); + assertEquals("12345", node.getPort()); + assertEquals("REST", microserviceRequest.getProtocol()); + assertNull(microserviceRequest.getMetadata()); + //very strange, but it should be null for ONAP to work + assertEquals("", microserviceRequest.getPath()); + assertEquals(SelfRegistrationManager.SERVICE_NAME, microserviceRequest.getServiceName()); + assertEquals("/api/NokiaSVNFM/v1", microserviceRequest.getUrl()); + assertEquals("v1", microserviceRequest.getVersion()); + //1 means internal service to ONAP + assertEquals("1", microserviceRequest.getVisualRange()); + } + + /** + * If the subscription already exists the subscription is not recreated + */ + @Test + public void testResubscription() throws Exception { + //given + MicroServiceFullInfo returnedMicroService = new MicroServiceFullInfo(); + when(msbClient.registerMicroServiceInfo(registeredMicroservice.capture())).thenReturn(returnedMicroService); + Subscription existingSubscription = new Subscription(); + existingSubscription.setId(UUID.randomUUID().toString()); + existingSubscription.setCallbackUrl("http://5.6.7.8:12345/api/NokiaSVNFM/v1/lcn"); + subscriptions.add(existingSubscription); + //when + selfRegistrationManager.register(); + //verify + assertMicroserviceRegistered(); + verify(lcnApi, never()).subscriptionsPost(any(), any()); + assertServiceUp(); + } + + /** + * If the LCN subscription fails the microservice is not registered + */ + @Test + public void testFailedLcnSubscription() throws Exception { + //given + ApiException expectedException = new ApiException(); + when(lcnApi.subscriptionsPost(any(), any())).thenThrow(expectedException); + //when + try { + selfRegistrationManager.register(); + fail(); + } catch (RuntimeException e) { + assertEquals(expectedException, e.getCause()); + } + //verify + verify(msbClient, never()).registerMicroServiceInfo(any()); + verify(logger).error("Unable to subscribe to CBAM LCN", expectedException); + assertServiceDown(); + } + + /** + * If the registration to MSB fails the subscription is deleted + */ + @Test + public void testFailedMsbPublish() throws Exception { + //given + Subscription subscription = new Subscription(); + when(lcnApi.subscriptionsPost(subscriptionToCreate.capture(), Mockito.eq(NOKIA_LCN_API_VERSION))).thenAnswer(new Answer<Subscription>() { + @Override + public Subscription answer(InvocationOnMock invocationOnMock) throws Throwable { + subscription.setCallbackUrl("http://5.6.7.8:12345/api/NokiaSVNFM/v1/lcn"); + subscription.setId(UUID.randomUUID().toString()); + subscriptions.add(subscription); + return subscription; + } + }); + MicroServiceFullInfo returnedMicroService = new MicroServiceFullInfo(); + RouteException expectedException = new RouteException(); + when(msbClient.registerMicroServiceInfo(registeredMicroservice.capture())).thenThrow(expectedException); + //when + try { + selfRegistrationManager.register(); + //verify + fail(); + } catch (RuntimeException e) { + assertEquals(expectedException, e.getCause()); + } + assertNewLcnSubscription(); + verify(lcnApi).subscriptionsSubscriptionIdDelete(subscription.getId(), NOKIA_LCN_API_VERSION); + assertServiceDown(); + } + + /** + * basic service unregistration + * - ongoing jobs are outwaited + * - first the service is removed from MSB + * - second unregistration + */ + @Test + public void testUnregistration() throws Exception { + //given + Subscription subscription = new Subscription(); + subscription.setCallbackUrl("http://5.6.7.8:12345/api/NokiaSVNFM/v1/lcn"); + subscription.setId(UUID.randomUUID().toString()); + subscriptions.add(subscription); + when(jobManager.hasOngoingJobs()).thenReturn(false); + MicroServiceFullInfo returnedMicroService = new MicroServiceFullInfo(); + //when + selfRegistrationManager.deRegister(); + //verify + InOrder inOrder = Mockito.inOrder(jobManager, msbClient, lcnApi); + inOrder.verify(msbClient).cancelMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION); + inOrder.verify(lcnApi).subscriptionsSubscriptionIdDelete(subscription.getId(), NOKIA_LCN_API_VERSION); + assertServiceDown(); + } + + /** + * if the MSB reports that it could not cancel the service, but the service has + * disappeared from MSB the cancellation is considered to be successful + */ + @Test + public void testPartiallyFailedMsbCancel() throws Exception { + //given + Subscription subscription = new Subscription(); + subscription.setCallbackUrl("http://5.6.7.8:12345/api/NokiaSVNFM/v1/lcn"); + subscription.setId(UUID.randomUUID().toString()); + subscriptions.add(subscription); + when(jobManager.hasOngoingJobs()).thenReturn(false); + when(msbClient.cancelMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION)).then(new Answer<RouteResult>() { + @Override + public RouteResult answer(InvocationOnMock invocationOnMock) throws Throwable { + when(msbClient.queryMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION)).thenThrow(new RouteException()); + throw new RouteException(); + } + }); + MicroServiceFullInfo returnedMicroService = new MicroServiceFullInfo(); + //when + selfRegistrationManager.deRegister(); + //verify + InOrder inOrder = Mockito.inOrder(jobManager, msbClient, lcnApi); + inOrder.verify(msbClient).cancelMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION); + inOrder.verify(msbClient).queryMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION); + inOrder.verify(lcnApi).subscriptionsSubscriptionIdDelete(subscription.getId(), NOKIA_LCN_API_VERSION); + assertServiceDown(); + } + + /** + * failure of unregistration from MSB should be propagated + */ + @Test + public void testUnregistrationFailure() throws Exception { + //given + Subscription subscription = new Subscription(); + subscription.setCallbackUrl("http://5.6.7.8:12345/api/NokiaSVNFM/v1/lcn"); + subscription.setId(UUID.randomUUID().toString()); + subscriptions.add(subscription); + when(msbClient.cancelMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION)).then(new Answer<RouteResult>() { + @Override + public RouteResult answer(InvocationOnMock invocationOnMock) throws Throwable { + throw new RouteException(); + } + }); + MicroServiceFullInfo returnedMicroService = new MicroServiceFullInfo(); + //when + try { + selfRegistrationManager.deRegister(); + fail(); + } catch (RuntimeException e) { + + } + //verify + InOrder inOrder = Mockito.inOrder(jobManager, msbClient, lcnApi); + inOrder.verify(msbClient).cancelMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION); + inOrder.verify(msbClient).queryMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION); + verify(lcnApi, Mockito.never()).subscriptionsSubscriptionIdDelete(subscription.getId(), NOKIA_LCN_API_VERSION); + assertServiceDown(); + } + + /** + * failure of subscription deletion from MSB should be propagated + */ + @Test + public void testSubscriptionFailure() throws Exception { + //given + Subscription subscription = new Subscription(); + subscription.setCallbackUrl("http://5.6.7.8:12345/api/NokiaSVNFM/v1/lcn"); + subscription.setId(UUID.randomUUID().toString()); + subscriptions.add(subscription); + when(jobManager.hasOngoingJobs()).thenReturn(false); + ApiException expectedException = new ApiException(); + doThrow(expectedException).when(lcnApi).subscriptionsSubscriptionIdDelete(subscription.getId(), NOKIA_LCN_API_VERSION); + //when + try { + selfRegistrationManager.deRegister(); + fail(); + } catch (RuntimeException e) { + + } + //verify + InOrder inOrder = Mockito.inOrder(jobManager, msbClient, lcnApi); + inOrder.verify(msbClient).cancelMicroServiceInfo(SelfRegistrationManager.SERVICE_NAME, SelfRegistrationManager.DRIVER_VERSION); + inOrder.verify(lcnApi).subscriptionsSubscriptionIdDelete(subscription.getId(), NOKIA_LCN_API_VERSION); + assertServiceDown(); + } + + /** + * the swagger API definitions embedded in the code + */ + @Test + public void testSwaggerApi() throws Exception { + //no idea how to test this except repeat implementation + byte[] a = TestUtil.loadFile(SelfRegistrationManager.SWAGGER_API_DEFINITION); + tearGeneric(); + //when + assertTrue(Arrays.equals(a, selfRegistrationManager.getSwaggerApiDefinition())); + } + + public void assertServiceUp() throws Exception { + assertTrue(selfRegistrationManager.isReady()); + } + + /** + * if there are ongoing jobs then the guard thros exception + */ + public void assertServiceDown() { + assertFalse(selfRegistrationManager.isReady()); + + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestLifecycleChangeNotificationManager.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestLifecycleChangeNotificationManager.java new file mode 100644 index 00000000..ed009b97 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestLifecycleChangeNotificationManager.java @@ -0,0 +1,457 @@ +/* + * 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.vnfm.notification; + +import com.google.gson.*; +import com.nokia.cbam.lcm.v32.ApiException; +import com.nokia.cbam.lcm.v32.model.*; +import org.joda.time.DateTime; +import org.junit.Before; +import org.junit.Test; +import org.mockito.ArgumentCaptor; +import org.mockito.InjectMocks; +import org.mockito.Mockito; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.ILifecycleChangeNotificationManager; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; +import org.threeten.bp.OffsetDateTime; + +import java.util.ArrayList; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.concurrent.Callable; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.Future; + +import static com.nokia.cbam.lcm.v32.model.OperationType.*; +import static junit.framework.TestCase.*; +import static org.mockito.Mockito.*; +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 TestLifecycleChangeNotificationManager extends TestBase { + + public static final String OPERATION_EXECUTION_ID = "myOperationExecutionId"; + + @InjectMocks + private LifecycleChangeNotificationManager lifecycleChangeNotificationManager; + private VnfLifecycleChangeNotification recievedLcn = new VnfLifecycleChangeNotification(); + private List<OperationExecution> operationExecutions = new ArrayList<>(); + private OperationExecution instantiationOperation = new OperationExecution(); + private OperationExecution scaleOperation = new OperationExecution(); + private OperationExecution healOperation = new OperationExecution(); + private OperationExecution terminationOperation = new OperationExecution(); + + private ArgumentCaptor<OperationExecution> currentOperationExecution = ArgumentCaptor.forClass(OperationExecution.class); + private ArgumentCaptor<ReportedAffectedConnectionPoints> affectedConnectionPoints = ArgumentCaptor.forClass(ReportedAffectedConnectionPoints.class); + + private List<VnfInfo> vnfs = new ArrayList<>(); + private VnfInfo vnf = new VnfInfo(); + + @Before + public void initMocks() throws Exception { + setField(LifecycleChangeNotificationManager.class, "logger", logger); + instantiationOperation.setId("instantiationOperationExecutionId"); + instantiationOperation.setStartTime(OffsetDateTime.now()); + instantiationOperation.setOperationType(OperationType.INSTANTIATE); + scaleOperation.setId("scaleOperationExecutionId"); + scaleOperation.setStartTime(OffsetDateTime.now().plusDays(1)); + scaleOperation.setOperationType(OperationType.SCALE); + terminationOperation.setId("terminationExecutionId"); + terminationOperation.setStartTime(OffsetDateTime.now().plusDays(1)); + terminationOperation.setOperationType(OperationType.TERMINATE); + healOperation.setId("healOperaitonExecutionId"); + healOperation.setOperationType(OperationType.HEAL); + recievedLcn.setLifecycleOperationOccurrenceId("instantiationOperationExecutionId"); + healOperation.setStartTime(OffsetDateTime.now().plusDays(1)); + recievedLcn.setVnfInstanceId(VNF_ID); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(operationExecutions); + prepOperation(instantiationOperation); + prepOperation(scaleOperation); + prepOperation(healOperation); + prepOperation(terminationOperation); + doNothing().when(notificationSender).processNotification(eq(recievedLcn), currentOperationExecution.capture(), affectedConnectionPoints.capture(), eq(VIM_ID)); + InstantiateVnfRequest instantiateVnfRequest = new InstantiateVnfRequest(); + VimInfo vimInfo = new VimInfo(); + vimInfo.setId(VIM_ID); + instantiateVnfRequest.getVims().add(vimInfo); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperation.getId(), NOKIA_LCM_API_VERSION)).thenReturn(new Gson().toJsonTree(instantiateVnfRequest)); + when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenReturn(vnfs); + vnfs.add(vnf); + vnf.setId(VNF_ID); + VnfProperty prop = new VnfProperty(); + prop.setName(ILifecycleChangeNotificationManager.EXTERNAL_VNFM_ID); + prop.setValue(VNFM_ID); + vnf.setExtensions(new ArrayList<>()); + vnf.getExtensions().add(prop); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenReturn(vnf); + } + + private void prepOperation(OperationExecution operationExecution) throws ApiException { + addEmptyModifiedConnectionPoints(operationExecution); + JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}"); + operationExecution.setOperationParams(root); + switch (operationExecution.getOperationType()) { + case TERMINATE: + root.getAsJsonObject().addProperty("terminationType", "GRACEFULL"); + } + when(operationExecutionApi.operationExecutionsOperationExecutionIdGet(operationExecution.getId(), NOKIA_LCM_API_VERSION)).thenReturn(operationExecution); + operationExecutions.add(operationExecution); + } + + private void addEmptyModifiedConnectionPoints(OperationExecution operationExecution) { + OperationResult operationResult = new OperationResult(); + operationResult.operationResult = new ReportedAffectedConnectionPoints(); + JsonElement additionalData = new Gson().toJsonTree(operationResult); + operationExecution.setAdditionalData(additionalData); + } + + /** + * The first instantiation before the current operation is selected + */ + @Test + public void testLastInstantiationSelection() { + List<OperationExecution> operations = new ArrayList<>(); + + OperationExecution operation = buildOperation(OffsetDateTime.now(), TERMINATE); + OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE); + OperationExecution operationClosestInstantiate = buildOperation(OffsetDateTime.now().minusDays(2), INSTANTIATE); + OperationExecution operationFurthers = buildOperation(OffsetDateTime.now().minusDays(3), INSTANTIATE); + + operations.add(operation); + operations.add(operationScale); + operations.add(operationClosestInstantiate); + operations.add(operationFurthers); + assertEquals(operationClosestInstantiate, LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation)); + } + + /** + * The instantiation operation itself is valid as the last instantiation operation + */ + @Test + public void testInstantiationSufficesTheLastInstantiation() { + DateTime baseTime = DateTime.now(); + List<OperationExecution> operations = new ArrayList<>(); + + OperationExecution operation = buildOperation(OffsetDateTime.now(), INSTANTIATE); + OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE); + OperationExecution operationFurthers = buildOperation(OffsetDateTime.now().minusDays(2), INSTANTIATE); + + operations.add(operation); + operations.add(operationScale); + operations.add(operationFurthers); + assertEquals(operation, LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation)); + } + + /** + * If no instantiation operation is found for before the selected operation + */ + @Test + public void testNoInstantiation() { + DateTime baseTime = DateTime.now(); + List<OperationExecution> operations = new ArrayList<>(); + + OperationExecution operation = buildOperation(OffsetDateTime.now(), TERMINATE); + OperationExecution operationScale = buildOperation(OffsetDateTime.now().minusDays(1), SCALE); + + operations.add(operation); + operations.add(operationScale); + try { + LifecycleChangeNotificationManager.findLastInstantiationBefore(operations, operation); + fail(); + } catch (NoSuchElementException e) { + + } + } + + /** + * the operations are ordered from newest (first) to oldest (last) + */ + @Test + public void testOperationOrdering() { + List<OperationExecution> operationExecutions = new ArrayList<>(); + OperationExecution before = buildOperation(OffsetDateTime.now(), OperationType.INSTANTIATE); + operationExecutions.add(before); + OperationExecution after = buildOperation(OffsetDateTime.now().plusDays(1), OperationType.SCALE); + operationExecutions.add(after); + List<OperationExecution> sorted1 = LifecycleChangeNotificationManager.NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions); + assertEquals(after, sorted1.get(0)); + assertEquals(before, sorted1.get(1)); + } + + /** + * if VNF listing fails the processing of the notifications is aborted + */ + @Test + public void testUnableToListVnfs() throws Exception { + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsGet(NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //when + try { + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + fail(); + } catch (Exception e) { + assertEquals(expectedException, e.getCause()); + verify(logger).error("Unable to list VNFs / query VNF", expectedException); + } + } + + /** + * if VNF query fails the processing of the notifications is aborted + */ + @Test + public void testUnableToQueryVnf() throws Exception { + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsVnfInstanceIdGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //when + try { + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + fail(); + } catch (Exception e) { + assertEquals(expectedException, e.getCause()); + verify(logger).error("Unable to list VNFs / query VNF", expectedException); + } + } + + /** + * if the VNF is not managed by this VNFM the LCN is dropped + */ + @Test + public void testNonManagedVnf() throws Exception { + vnf.getExtensions().clear(); + //when + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + //verify + Mockito.verifyZeroInteractions(operationExecutionApi); + verify(logger).warn("The VNF with " + VNF_ID + " identifier is not a managed VNF"); + } + + /** + * if the VNF is not managed by this VNFM the LCN is dropped + */ + @Test + public void testManagedByOtherVnf() throws Exception { + vnf.getExtensions().get(0).setValue("unknownVnfmId"); + //when + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + //verify + Mockito.verifyZeroInteractions(operationExecutionApi); + verify(logger).warn("The VNF with " + VNF_ID + " identifier is not a managed by the VNFM with id unknownVnfmId"); + } + + /** + * if the VNF disappeared before processing the LCN + */ + @Test + public void testDisappearedVnf() throws Exception { + vnfs.clear(); + //when + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + //verify + Mockito.verifyZeroInteractions(operationExecutionApi); + verify(logger).warn("The VNF with " + VNF_ID + " disappeared before being able to process the LCN"); + } + + /** + * if the operation parameters of the last instantiation is non querieable error is propagated + */ + @Test + public void testUnableToQueryOperationParams() throws Exception { + recievedLcn.setOperation(OperationType.TERMINATE); + recievedLcn.setStatus(OperationStatus.FINISHED); + RuntimeException expectedException = new RuntimeException(); + when(operationExecutionApi.operationExecutionsOperationExecutionIdOperationParamsGet(instantiationOperation.getId(), NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //when + try { + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + fail(); + } catch (Exception e) { + //verify + Mockito.verifyZeroInteractions(nsLcmApi); + assertEquals(expectedException, e.getCause()); + verify(logger).error("Unable to detect last instantiation operation", e.getCause()); + } + } + + /** + * if unable to send LCN to VF-C the error is propagated + */ + @Test + public void testUnableToQueryCurrentOperation() throws Exception { + recievedLcn.setOperation(OperationType.TERMINATE); + recievedLcn.setStatus(OperationStatus.FINISHED); + ApiException expectedException = new ApiException(); + when(vnfApi.vnfsVnfInstanceIdOperationExecutionsGet(VNF_ID, NOKIA_LCM_API_VERSION)).thenThrow(expectedException); + //when + try { + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + fail(); + } catch (Exception e) { + //verify + assertEquals(expectedException, e.getCause()); + verify(logger).error("Unable to retrieve the current VNF myVnfId", e.getCause()); + } + } + + /** + * test that waitForTerminationToBeProcessed outwaits the successfull processing of the termination notification + */ + @Test + public void testWaitForTermination() throws Exception { + //given + //add an non processed notification + VnfLifecycleChangeNotification nonProcessedEvent = new VnfLifecycleChangeNotification(); + nonProcessedEvent.setStatus(OperationStatus.FINISHED); + nonProcessedEvent.setOperation(OperationType.TERMINATE); + OperationExecution secondTerminationOperationExecution = new OperationExecution(); + secondTerminationOperationExecution.setOperationType(OperationType.TERMINATE); + secondTerminationOperationExecution.setId("secondId"); + secondTerminationOperationExecution.setOperationParams(buildTerminationParams()); + nonProcessedEvent.setLifecycleOperationOccurrenceId(secondTerminationOperationExecution.getId()); + lifecycleChangeNotificationManager.handleLcn(nonProcessedEvent); + //add second termination + recievedLcn.setOperation(OperationType.TERMINATE); + recievedLcn.setStatus(OperationStatus.FINISHED); + recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId()); + ExecutorService executorService = Executors.newCachedThreadPool(); + Future<Boolean> waitExitedWithSuccess = executorService.submit(new Callable<Boolean>() { + @Override + public Boolean call() throws Exception { + try { + lifecycleChangeNotificationManager.waitForTerminationToBeProcessed(terminationOperation.getId()); + return true; + } catch (Exception e) { + return false; + } + } + }); + //when + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + //verify + assertTrue(waitExitedWithSuccess.get()); + } + + /** + * Forceful termination results in an empty affected connection points + */ + @Test + public void testMissingPreResultForForcefullTermination() { + //given + recievedLcn.setOperation(OperationType.INSTANTIATE); + recievedLcn.setStatus(OperationStatus.FINISHED); + recievedLcn.setLifecycleOperationOccurrenceId(terminationOperation.getId()); + JsonObject additionalData = new JsonObject(); + additionalData.add("operationResult", new JsonObject()); + ((JsonObject) terminationOperation.getOperationParams()).addProperty("terminationType", "FORCEFUL"); + terminationOperation.setAdditionalData(additionalData); + terminationOperation.setStatus(OperationStatus.FINISHED); + terminationOperation.setOperationType(OperationType.TERMINATE); + //when + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + assertNull(affectedConnectionPoints.getValue()); + verify(logger).warn("Unable to send information related to affected connection points during forceful termination"); + } + + /** + * test end notification scenario for failed scale-out + * - LCN is sent to VF-C, but the + */ + @Test + public void testMissingPreResultForFailedOperation() { + //given + recievedLcn.setOperation(OperationType.SCALE); + recievedLcn.setStatus(OperationStatus.FAILED); + recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId()); + ScaleVnfRequest request = new ScaleVnfRequest(); + request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }")); + request.setType(ScaleDirection.OUT); + scaleOperation.setOperationParams(request); + scaleOperation.setAdditionalData(null); + scaleOperation.setStatus(OperationStatus.FAILED); + scaleOperation.setOperationType(OperationType.SCALE); + //when + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + assertEquals(0, affectedConnectionPoints.getValue().getPost().size()); + assertEquals(0, affectedConnectionPoints.getValue().getPre().size()); + verify(logger).warn("The operation failed and the affected connection points were not reported"); + } + + /** + * test end notification success scenario for scale-out + * - LCN is sent to VF-C + */ + @Test + public void testMissingPreResult() { + //given + recievedLcn.setOperation(OperationType.SCALE); + recievedLcn.setStatus(OperationStatus.FINISHED); + recievedLcn.setLifecycleOperationOccurrenceId(scaleOperation.getId()); + ScaleVnfRequest request = new ScaleVnfRequest(); + request.setAdditionalParams(new JsonParser().parse("{ \"type\" : \"IN\", \"jobId\" : \"" + JOB_ID + "\" }")); + request.setType(ScaleDirection.OUT); + scaleOperation.setOperationParams(request); + JsonObject additionalData = new JsonObject(); + additionalData.add("operationResult", new JsonObject()); + scaleOperation.setAdditionalData(additionalData); + scaleOperation.setStatus(OperationStatus.FINISHED); + scaleOperation.setOperationType(OperationType.SCALE); + JsonElement root = new JsonParser().parse("{ \"additionalParams\" : { \"jobId\" : \"" + JOB_ID + "\"}}"); + JsonObject operationParams = new JsonObject(); + //when + try { + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + fail(); + } catch (Exception e) { + assertEquals("All operations must return the { \"operationResult\" : { \"cbam_pre\" : [<fillMeOut>], \"cbam_post\" : [<fillMeOut>] } } structure", e.getMessage()); + } + } + + /** + * missing connection points are tolerated in case of failed operations + */ + @Test + public void testMissingConnectionPoints() { + //given + recievedLcn.setOperation(OperationType.INSTANTIATE); + recievedLcn.setStatus(OperationStatus.FAILED); + recievedLcn.setLifecycleOperationOccurrenceId(instantiationOperation.getId()); + instantiationOperation.setAdditionalData(null); + instantiationOperation.setStatus(OperationStatus.FAILED); + //when + lifecycleChangeNotificationManager.handleLcn(recievedLcn); + assertEquals(0, affectedConnectionPoints.getValue().getPost().size()); + assertEquals(0, affectedConnectionPoints.getValue().getPre().size()); + verify(logger).warn("The operation failed and the affected connection points were not reported"); + } + + private JsonObject buildTerminationParams() { + JsonObject root = new JsonObject(); + root.add("terminationType", new JsonPrimitive("GRACEFULL")); + return root; + } + + private OperationExecution buildOperation(OffsetDateTime baseTime, OperationType operationType) { + OperationExecution operation = new OperationExecution(); + operation.setStartTime(baseTime); + operation.setOperationType(operationType); + return operation; + } + + class OperationResult { + ReportedAffectedConnectionPoints operationResult; + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestProcessedNotification.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestProcessedNotification.java new file mode 100644 index 00000000..bbe660a0 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestProcessedNotification.java @@ -0,0 +1,28 @@ +/* + * 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.vnfm.notification; + +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; + +import static pl.pojo.tester.api.assertion.Assertions.assertPojoMethodsFor; + +public class TestProcessedNotification extends TestBase { + @Test + public void testPojo() { + assertPojoMethodsFor(ProcessedNotification.class).areWellImplemented(); + } +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestReportedAffectedConnectionPoints.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestReportedAffectedConnectionPoints.java new file mode 100644 index 00000000..83699723 --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestReportedAffectedConnectionPoints.java @@ -0,0 +1,30 @@ +/* + * 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.vnfm.notification; + +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; + +import static pl.pojo.tester.api.assertion.Assertions.assertPojoMethodsFor; + +public class TestReportedAffectedConnectionPoints extends TestBase { + @Test + public void testPojo() { + assertPojoMethodsFor(ReportedAffectedConnectionPoints.class).areWellImplemented(); + + } + +} diff --git a/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestReportedAffectedCp.java b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestReportedAffectedCp.java new file mode 100644 index 00000000..cb4d7e1c --- /dev/null +++ b/nokiav2/driver/src/test/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/vnfm/notification/TestReportedAffectedCp.java @@ -0,0 +1,30 @@ +/* + * 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.vnfm.notification; + +import org.junit.Test; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.TestBase; + +import static pl.pojo.tester.api.assertion.Assertions.assertPojoMethodsFor; + +public class TestReportedAffectedCp extends TestBase { + @Test + public void testPojo() { + assertPojoMethodsFor(ReportedAffectedCp.class).areWellImplemented(); + + } + +} diff --git a/nokiav2/driver/src/test/resources/.gitignore b/nokiav2/driver/src/test/resources/.gitignore new file mode 100644 index 00000000..03941911 --- /dev/null +++ b/nokiav2/driver/src/test/resources/.gitignore @@ -0,0 +1 @@ +application-real.properties diff --git a/nokiav2/driver/src/test/resources/application.properties b/nokiav2/driver/src/test/resources/application.properties new file mode 100644 index 00000000..f5c42fc0 --- /dev/null +++ b/nokiav2/driver/src/test/resources/application.properties @@ -0,0 +1,66 @@ +############################################################################### +# Copyright 2016, 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. +############################################################################### +server.error.whitelabel.enabled=false +############################################################################### +# Beginning of mandatory properties # +############################################################################### +# The TCP port of the server +server.port=8089 +# the base path of the server +server.context-path= +# the IP address to which the server binds to +server.address=127.0.0.1 +# the IP address of the server reported to the micro service bus +driverMsbExternalIp=127.0.0.1 +# the IP address of the server reported to VNFM +driverVnfmExternalIp=127.0.0.1 +# the IP address of the message bus +messageBusIp=127.0.0.1 +# the TCP port of the message bus +messageBusPort=8089 +# the URL of the CBAM catalog service +cbamCatalogUrl=https://127.0.0.1:443/api/catalog/adapter +# the URL of the CBAM LCN service +cbamLcnUrl=https://127.0.0.0.1:443/vnfm/lcn/v3 +# the URL of the CBAM authentication service +cbamKeyCloakBaseUrl=https://127.0.0.0.1:443/auth +# skip hostname verification during SSL on CBAM LCN, LCM and authorization interface +skipHostnameVerification=true +# skip certificate verification during SSL on CBAM LCN, LCM and authorization interface +skipCertificateVerification=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 +trustedCertificates= +# the username to be used for requesting a token on CBAM authorization interface +cbamUsername=onap +# the password to be used for requesting a token on CBAM authorization interface +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 # +############################################################################### + + +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 +logging.level.org.springframework.web=TRACE +logging.level.org.hibernate=OFF +## for logging end ## diff --git a/nokiav2/driver/src/test/resources/test.jks b/nokiav2/driver/src/test/resources/test.jks Binary files differnew file mode 100644 index 00000000..5506b9a8 --- /dev/null +++ b/nokiav2/driver/src/test/resources/test.jks diff --git a/nokiav2/driver/src/test/resources/unittests/TestCbamCatalogManager.sample.csar b/nokiav2/driver/src/test/resources/unittests/TestCbamCatalogManager.sample.csar Binary files differnew file mode 100644 index 00000000..94f476f4 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/TestCbamCatalogManager.sample.csar diff --git a/nokiav2/driver/src/test/resources/unittests/cbam.package.zip b/nokiav2/driver/src/test/resources/unittests/cbam.package.zip Binary files differnew file mode 100644 index 00000000..d7c6a673 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/cbam.package.zip diff --git a/nokiav2/driver/src/test/resources/unittests/empty.zip b/nokiav2/driver/src/test/resources/unittests/empty.zip Binary files differnew file mode 100644 index 00000000..15cb0ecb --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/empty.zip diff --git a/nokiav2/driver/src/test/resources/unittests/lcn.json b/nokiav2/driver/src/test/resources/unittests/lcn.json new file mode 100644 index 00000000..1ed3f5f4 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/lcn.json @@ -0,0 +1,9 @@ +{ + "status": "STARTED", + "vnfInstanceId": "CBAM-d59f413228af4a35b00eb168d636f567", + "timestamp": "2018-01-02T10:50:54.903260Z", + "notificationType": "VnfLifecycleChangeNotification", + "lifecycleOperationOccurrenceId": "CBAM-9b7dd0c2591d463b890021c38ead3f24", + "subscriptionId": "CBAM-1b89306bcd494879b7cb02369d2b2503", + "operation": "TERMINATE" +}
\ No newline at end of file diff --git a/nokiav2/driver/src/test/resources/unittests/localhost.cert.pem b/nokiav2/driver/src/test/resources/unittests/localhost.cert.pem new file mode 100644 index 00000000..879a6a5a --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/localhost.cert.pem @@ -0,0 +1,73 @@ +Certificate: + Data: + Version: 3 (0x2) + Serial Number: 878178886 (0x3457f246) + Signature Algorithm: sha256WithRSAEncryption + Issuer: C=Unknown, ST=Unknown, L=Unknown, O=Unknown, OU=Unknown, CN=localhost + Validity + Not Before: Dec 16 01:51:53 2017 GMT + Not After : Mar 16 01:51:53 2018 GMT + Subject: C=Unknown, ST=Unknown, L=Unknown, O=Unknown, OU=Unknown, CN=localhost + Subject Public Key Info: + Public Key Algorithm: rsaEncryption + Public-Key: (2048 bit) + Modulus: + 00:85:90:1e:2e:d5:b6:55:c4:56:ac:f7:3d:fb:12: + c3:a5:be:30:bb:56:03:e7:b2:cb:0e:e5:27:d2:82: + 41:11:09:ff:3b:1c:aa:bc:3d:97:0e:2f:c1:b5:bf: + de:ed:fe:36:e9:71:d6:3d:3d:ca:00:b0:3b:69:b0: + b8:0a:ef:e3:df:91:2e:8f:f7:92:9d:29:0c:5d:15: + ad:47:10:db:34:8c:10:01:ad:68:dc:df:80:d5:42: + 1f:55:be:06:7c:b0:c7:0a:04:87:9a:0a:57:ba:67: + 43:39:a4:91:09:91:bb:6f:00:dc:ff:ff:4c:53:e0: + 38:37:de:50:2f:a7:04:e7:c3:bc:a8:56:cd:d6:a7: + 99:51:43:14:00:32:85:46:3d:92:31:f6:5b:de:74: + de:11:4f:23:c2:0d:c6:65:0d:1d:d5:66:d8:bb:79: + 21:0e:b8:b9:0c:75:6e:7b:35:de:1e:a1:35:00:2e: + 74:84:7d:a9:b6:55:f8:58:c4:a9:8e:cf:ae:3e:17: + 12:71:05:b8:8a:50:05:7a:e9:55:db:68:26:e9:02: + 0c:1d:43:7f:bd:00:ab:4b:6e:cf:3f:1a:68:a8:52: + a2:b8:36:19:ca:fb:37:f8:79:54:6a:b4:7b:41:54: + af:bc:6a:49:2d:15:6d:14:95:18:b1:37:b2:9a:52: + 21:47 + Exponent: 65537 (0x10001) + X509v3 extensions: + X509v3 Subject Key Identifier: + B4:A1:34:DA:34:7F:52:3E:76:AB:81:A4:5C:7E:10:3E:FD:84:9A:3E + Signature Algorithm: sha256WithRSAEncryption + 6b:9f:d7:de:1b:38:f0:46:7a:40:df:47:b1:1c:5c:05:2c:9a: + 4a:ad:5e:81:84:d1:ac:d4:8d:27:4b:8f:92:2e:02:18:7a:84: + 2f:bb:68:f5:ea:2b:ae:cc:3f:21:f7:d0:47:ea:6d:21:73:db: + 35:f0:e4:27:ba:95:db:2b:99:93:aa:a1:ab:23:bd:78:4f:7c: + e1:63:cb:2b:e8:2c:fb:e1:ad:af:2d:01:1d:67:d8:7c:bb:82: + 00:30:1a:de:b2:1c:d3:25:b0:de:b1:b5:3c:dc:42:4b:ae:b9: + 1c:e2:f4:dd:45:6c:87:75:d8:9e:bd:1d:27:05:e7:8c:63:ec: + de:87:aa:95:d7:65:64:80:42:95:88:14:16:6b:43:22:0f:e7: + c0:06:36:0d:93:14:be:d6:22:24:c0:43:c4:fa:83:bd:6c:5b: + 24:7f:ac:a5:f5:ea:a7:61:fd:5d:67:e3:9d:d1:59:b5:e6:d6: + 9b:20:ca:23:44:44:b7:65:a7:f9:74:34:de:68:87:fd:1c:2f: + 32:d7:48:c0:10:ba:7e:83:06:a4:21:05:d5:6b:b0:9e:9c:dc: + 12:5a:5a:45:b7:84:94:96:a4:29:e6:05:47:1f:f5:a5:93:db: + 21:fc:2e:2a:4d:55:09:54:38:0c:56:ba:59:5b:b2:36:85:c6: + 63:78:93:0c +-----BEGIN CERTIFICATE----- +MIIDezCCAmOgAwIBAgIENFfyRjANBgkqhkiG9w0BAQsFADBuMRAwDgYDVQQGEwdV +bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD +VQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRIwEAYDVQQDEwlsb2NhbGhv +c3QwHhcNMTcxMjE2MDE1MTUzWhcNMTgwMzE2MDE1MTUzWjBuMRAwDgYDVQQGEwdV +bmtub3duMRAwDgYDVQQIEwdVbmtub3duMRAwDgYDVQQHEwdVbmtub3duMRAwDgYD +VQQKEwdVbmtub3duMRAwDgYDVQQLEwdVbmtub3duMRIwEAYDVQQDEwlsb2NhbGhv +c3QwggEiMA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQCFkB4u1bZVxFas9z37 +EsOlvjC7VgPnsssO5SfSgkERCf87HKq8PZcOL8G1v97t/jbpcdY9PcoAsDtpsLgK +7+PfkS6P95KdKQxdFa1HENs0jBABrWjc34DVQh9VvgZ8sMcKBIeaCle6Z0M5pJEJ +kbtvANz//0xT4Dg33lAvpwTnw7yoVs3Wp5lRQxQAMoVGPZIx9lvedN4RTyPCDcZl +DR3VZti7eSEOuLkMdW57Nd4eoTUALnSEfam2VfhYxKmOz64+FxJxBbiKUAV66VXb +aCbpAgwdQ3+9AKtLbs8/GmioUqK4NhnK+zf4eVRqtHtBVK+8akktFW0UlRixN7Ka +UiFHAgMBAAGjITAfMB0GA1UdDgQWBBS0oTTaNH9SPnargaRcfhA+/YSaPjANBgkq +hkiG9w0BAQsFAAOCAQEAa5/X3hs48EZ6QN9HsRxcBSyaSq1egYTRrNSNJ0uPki4C +GHqEL7to9eorrsw/IffQR+ptIXPbNfDkJ7qV2yuZk6qhqyO9eE984WPLK+gs++Gt +ry0BHWfYfLuCADAa3rIc0yWw3rG1PNxCS665HOL03UVsh3XYnr0dJwXnjGPs3oeq +lddlZIBClYgUFmtDIg/nwAY2DZMUvtYiJMBDxPqDvWxbJH+spfXqp2H9XWfjndFZ +tebWmyDKI0REt2Wn+XQ03miH/RwvMtdIwBC6foMGpCEF1WuwnpzcElpaRbeElJak +KeYFRx/1pZPbIfwuKk1VCVQ4DFa6WVuyNoXGY3iTDA== +-----END CERTIFICATE----- diff --git a/nokiav2/driver/src/test/resources/unittests/localhost.jks b/nokiav2/driver/src/test/resources/unittests/localhost.jks Binary files differnew file mode 100644 index 00000000..80b72992 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/localhost.jks diff --git a/nokiav2/driver/src/test/resources/unittests/maria.vnfd.scalable.tosca.nated.yaml b/nokiav2/driver/src/test/resources/unittests/maria.vnfd.scalable.tosca.nated.yaml new file mode 100644 index 00000000..76ed67ce --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/maria.vnfd.scalable.tosca.nated.yaml @@ -0,0 +1,593 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0_nokia + +topology_template: + substitution_mappings: + node_type: tosca.nodes.nfv.VNF + properties: + descriptor_id: Nokia~Maria DB~1.0~1.0 + descriptor_version: '1.0' + provider: Nokia + product_name: Maria DB + software_version: '1.0' + product_info_name: Maria DB + product_info_description: Relational database, non-scalable + vnfm_info: + - CBAM + requirements: + - virtual_link: [ dbBackendIpv4, external_virtual_link ] # IPv4 for SQL + - virtual_link: [ dbBackendIpv6, external_virtual_link ] # IPv6 for SQL + - virtual_link: [ serviceNodeIpv4, external_virtual_link ] # IPv4 for SSH + - virtual_link: [ loadBalancer, external_virtual_link ] # IPv4 for SQL (load balanced) + capabilities: + deployment_flavour: + properties: + flavour_id: scalable + description: .. + scaling_aspects: + dbBackendAspect: + name: .. + description: .. + associated_group: dbBackendScalingGroup + max_scale_level: 8 + serviceNodeAspect: + name: .. + description: .. + associated_group: serviceNodeScalingGroup + max_scale_level: 3 + instantiation_levels: + small: + description: .. + vdu_levels: + dbBackend: + number_of_instances: 3 + serviceNode: + number_of_instances: 2 + scale_info: + dbBackendAspect: + scale_level: 0 + serviceNodeAspect: + scale_level: 1 + medium: + description: .. + vdu_levels: + dbBackend: + number_of_instances: 4 + serviceNode: + number_of_instances: 2 + scale_info: + dbBackendAspect: + scale_level: 1 + serviceNodeAspect: + scale_level: 1 + large: + description: .. + vdu_levels: + dbBackend: + number_of_instances: 5 + serviceNode: + number_of_instances: 4 + scale_info: + dbBackendAspect: + scale_level: 2 + serviceNodeAspect: + scale_level: 2 + default_instantiation_level_id: small + vdu_profile: + dbBackend: + min_number_of_instances: 3 + max_number_of_instances: 11 + serviceNode: + min_number_of_instances: 0 + max_number_of_instances: 6 + vnf: + properties: + modifiable_attributes: + extensions: + http_proxy: + default: "http://87.254.212.120:8080" + https_proxy: + default: "https://87.254.212.120:8080" + no_proxy: + default: "10.41.49.231,10.41.49.5" + mysqlPassword: + default: "password" + mysqlUsername: + default: "mysql" + loginUsername: + default: "ubuntu" + rhel_yum_repository_host: + default: "http://10.41.49.231/mirror/rhel-7-server-rpms/" + ubuntu_repository_host: + default: "deb [arch=amd64] http://10.41.49.5/cobbler/repo_mirror/ubuntu-16.04-x86_64/ xenial main universe" + mariadb_rhel_repo_host: +# default: "http://yum.mariadb.org/10.0/rhel7-amd64" + default: "http://10.41.49.5/cobbler/repo_mirror/mariadb-10.0-el7-x86_64/" + mariadb_ubuntu_repo_host: +# default: "deb http://mirror.netinch.com/pub/mariadb/repo/10.0/ubuntu trusty main" + default: "deb [arch=amd64] http://10.41.49.5/cobbler/repo_mirror/ubuntu-mariadb-10.0-x86_64/ xenial main" + custom_backend_root_volume_size: + default: "10" + dry_run: + default: "false" + interfaces: + Basic: + instantiate: + inputs: + extensions: + pre_actions: + - javascript: javascript/scalable_instantiate_hot_params.js + include: + - javascript/scalable_prepare_cbam_include.js + output: stack_parameters + - javascript: javascript/cbam.pre.collectConnectionPoints.js + include: + - javascript/cbam.collectConnectionPoints.js + output: operation_result + post_actions: + - javascript: javascript/workaround_inventory_on_kilo.js + output: ansible_inventory + - ansible: ansible/playbook-scalable.yml + - javascript: javascript/cbam.post.collectConnectionPoints.js + include: + - javascript/cbam.collectConnectionPoints.js + output: operation_result + additional_parameters: + jobId: onapJobId + terminate: + inputs: + extensions: + pre_actions: + - javascript: javascript/cbam.pre.collectConnectionPoints.js + include: + - javascript/cbam.collectConnectionPoints.js + output: operation_result + post_actions: + - javascript: javascript/cbam.post.collectConnectionPoints.js + include: + - javascript/cbam.collectConnectionPoints.js + output: operation_result + additional_parameters: + jobId: onapJobId + Scalable: + scale: + inputs: + extensions: + pre_actions: + - javascript: javascript/scalable_instantiate_hot_params.js + include: + - javascript/scalable_prepare_cbam_include.js + output: stack_parameters + - ansible: ansible/playbook-scalable-scale-in.yml + - javascript: javascript/cbam.pre.collectConnectionPoints.js + include: + - javascript/cbam.collectConnectionPoints.js + output: operation_result + post_actions: + - javascript: javascript/workaround_inventory_on_kilo.js + output: ansible_inventory + - ansible: ansible/playbook-scalable.yml + - javascript: javascript/cbam.post.collectConnectionPoints.js + include: + - javascript/cbam.collectConnectionPoints.js + output: operation_result + additional_parameters: + jobId: onapJobId + Healable: + heal: + implementation: mistral-workbooks/heal_workbook.yaml + inputs: + extensions: + pre_actions: + - javascript: javascript/cbam.pre.collectConnectionPoints.js + include: + - javascript/cbam.collectConnectionPoints.js + output: operation_result + post_actions: + - javascript: javascript/cbam.post.collectConnectionPoints.js + include: + - javascript/cbam.collectConnectionPoints.js + output: operation_result + additional_parameters: + vmName: null + action: null + jobId: onapJobId + Custom: + upgrade: + implementation: mistral-workbooks/upgrade_workbook.yaml + inputs: + additional_parameters: + imageId: ubuntu.16.04 + jobId: onapJobId + node_templates: + dbBackend: + type: tosca.nodes.nfv.VDU + properties: + description: .. + configurable_properties: + additional_vnfc_configurable_properties: {} + boot_order: + - rootVolume + requirements: + - virtual_compute: dbBackendCompute + - virtual_storage: rootVolume + - virtual_storage: dataVolume + - sw_image: mariaDbImage #FIXME + + serviceNode: + type: tosca.nodes.nfv.VDU + properties: + description: .. + configurable_properties: + additional_vnfc_configurable_properties: {} + requirements: + - virtual_compute: serviceNodeCompute + - sw_image: mariaDbImage + + dbBackendCompute: + type: tosca.nodes.nfv.VirtualCompute + properties: + virtual_memory: + virtual_mem_size: 8096 MB + virtual_cpu: + cpu_architecture: x86 + num_virtual_cpu: 2 + virtual_cpu_clock: 1800 MHz + + serviceNodeCompute: + type: tosca.nodes.nfv.VirtualCompute + properties: + virtual_memory: + virtual_mem_size: 8096 MB + virtual_cpu: + cpu_architecture: x86 + num_virtual_cpu: 2 + virtual_cpu_clock: 1800 MHz + + rootVolume: + type: tosca.nodes.nfv.VirtualStorage + properties: + type_of_storage: volume + size_of_storage: 10 GB + #rdma_enabled: false + requirements: + - sw_image: mariaDbImage + + dataVolume: + type: tosca.nodes.nfv.VirtualStorage + properties: + type_of_storage: volume + size_of_storage: 1 GB + #rdma_enabled: false + requirements: + - sw_image: mariaDbImage + + mariaDbImage: + type: tosca.nodes.nfv.SwImage + properties: + name: Software of Maria Db + version: 1.0 + checksum: 9af30fce37a4c5c831e095745744d6d2 + container_format: qcow2 + disk_format: bare + # the ubuntu image is minimum 4GB the Centos is minimum 8 GB ? + min_disk: 10 GB + min_ram: 8096 MB + size: 10 GB + sw_image: maria.db.image.v1.0.qcow2 + operating_system: Linux + supported_virtualisation_environments: + - KVM + + dbBackendCpOnIpv4: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + role: leaf + description: Connection point to access the DB on IPv4 externally + requirements: + - virtual_binding: dbBackend + - virtual_link: internalNetworkForFloatingIp + + dbBackendCpOnIpv6: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv6 + role: leaf + description: Connection point to access the DB on IPv6 externally + requirements: + - virtual_binding: dbBackend + #- virtual_link: the CP is connected to the core network (IPv6) + + dbBackendCpOnIpv4Redundancy1: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + role: leaf + description: Connection point for DB replication + requirements: + - virtual_binding: dbBackend + - virtual_link: internalReplicationNetwork1 + + dbBackendCpOnIpv4Redundancy2: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + role: leaf + description: Connection point for DB replication + requirements: + - virtual_binding: dbBackend + - virtual_link: internalReplicationNetwork2 + + dbBackendExternallyManagedCp: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv6 + role: leaf + description: Connection point to access the DB on IPv6 externally + requirements: + - virtual_binding: dbBackend + - virtual_link: extManagedVl + + serviceNodeCp: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + role: leaf + description: Connection point to access the DB on IPv4 externally + requirements: + - virtual_binding: serviceNode + - virtual_link: internalNetworkForFloatingIp + + serviceNodeExternallyManagedCp: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + role: leaf + description: External connection point to access the DB on IPv4 + requirements: + - virtual_binding: dbBackend + - virtual_link: extManagedVl + + movingIpCp: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + role: leaf + description: Moving IP + requirements: + #- virtual_binding: # no corresponding VDU + - virtual_link: internalNetworkForFloatingIp + internalNetworkForFloatingIp: + type: tosca.nodes.nfv.VL + properties: + connectivity_type: + layer_protocol: ipv4 + flow_pattern: mesh + vl_flavours: {} + + internalReplicationNetwork1: + type: tosca.nodes.nfv.VL + properties: + connectivity_type: + layer_protocol: ipv4 + flow_pattern: mesh + test_access: [] + description: .. + vl_flavours: {} + + internalReplicationNetwork2: + type: tosca.nodes.nfv.VL + properties: + connectivity_type: + layer_protocol: ipv4 + flow_pattern: mesh + test_access: [] + description: .. + vl_flavours: {} + + extManagedVl: + type: tosca.nodes.nfv.VL + properties: + connectivity_type: + layer_protocol: ipv4 + flow_pattern: mesh + test_access: [] + description: .. + vl_flavours: {} + + dbBackendIpv4: + type: tosca.nodes.nfv.ECP + properties: + layer_protocol: ipv4 + requirements: + - internal_connection_point: dbBackendCpOnIpv4 + #- external_virtual_link: # exposed on VNF boundary + + dbBackendIpv6: + type: tosca.nodes.nfv.ECP + properties: + layer_protocol: ipv6 + requirements: + - internal_connection_point: dbBackendCpOnIpv6 + #- external_virtual_link: # exposed on VNF boundary + + serviceNodeIpv4: + type: tosca.nodes.nfv.ECP + properties: + layer_protocol: ipv4 + requirements: + - internal_connection_point: serviceNodeCp + #- external_virtual_link: # exposed on VNF boundary + + loadBalancer: + type: tosca.nodes.nfv.ECP + properties: + layer_protocol: ipv4 + requirements: + - internal_connection_point: movingIpCp + #- external_virtual_link: # exposed on VNF boundary + + groups: + dbBackendScalingGroup: + type: tosca.groups.nfv.ElementGroup + description: .. + members: [ dbBackend ] + + serviceNodeScalingGroup: + type: tosca.groups.nfv.ElementGroup + description: .. + members: [ serviceNode ] + + policies: + - service_node_anti_affinity: + type: tosca.policies.nfv.ScalingStepLocalAntiAffinity + targets: [ serviceNode ] + properties: + scope: nfvi_node + + - backend_node_anti_affinity: + type: tosca.policies.nfv.LocalAntiAffinity + targets: [ dbBackend ] + properties: + scope: nfvi_node + + - nfvi_affinity: + type: tosca.policies.nfv.LocalAffinity + targets: [ dbBackend ] + properties: + scope: nfvi + + - zone_affinity: + type: tosca.policies.nfv.LocalAffinity + targets: [ dbBackend ] + properties: + scope: resource_zone_group + + - commissioning: + type: tosca.policies.nfv.Commissioning #FIXME + properties: + connection_points: + - dbBackendIpv6 + - serviceNodeIpv4 + + - heat_mapping: + type: tosca.policies.nfv.HeatMapping + properties: + template: + hotPath: hot/ + main: maria.hot.scalable.main.nated.yaml + nested: + - maria.hot.common.nated.yaml + - maria.hot.scalable.service.scaling.nated.yaml + - maria.hot.scalable.service.static.nated.yaml + - maria.hot.scalable.service.nated.yaml + - maria.hot.scalable.backend.static.nated.yaml + - maria.hot.scalable.backend.single.nated.yaml + - maria.hot.scalable.backend.nated.yaml + - maria.hot.scalable.backend.single.wrapper.nated.yaml + - maria.hot.scalable.backend.wrapper.nated.yaml +# environment: + static: + virtualLinks: + internalReplicationNetwork1: db_backend_static.replication_network_1 + internalReplicationNetwork2: db_backend_static.replication_network_2 + internalNetworkForFloatingIp: common_resources.internal_network_for_floatingip + vdus: + dbBackend: + - heatResource: db_backend_static.static_node_0.wrapper_rg.0.server + connectionPoints: + dbBackendCpOnIpv4: db_backend_static.static_node_0.wrapper_rg.0.port_ipv4_nated + dbBackendCpOnIpv6: db_backend_static.static_node_0.wrapper_rg.0.port_ipv6 + dbBackendCpOnIpv4Redundancy1: db_backend_static.static_node_0.wrapper_rg.0.port_replication_1 + dbBackendCpOnIpv4Redundancy2: db_backend_static.static_node_0.wrapper_rg.0.port_replication_2 + dbBackendExternallyManagedCp: db_backend_static.static_node_0.wrapper_rg.0.port_internal_ext_managed + virtualStorages: + rootVolume: db_backend_static.static_node_0.wrapper_rg.0.volume_root + dataVolume: db_backend_static.static_node_0.wrapper_rg.0.volume_data + externalConnectionPoints: + dbBackendIpv4: + - db_backend_static.static_node_0.wrapper_rg.0.floating_ip + dbBackendIpv6: + - db_backend_static.static_node_0.wrapper_rg.0.port_ipv6 + - heatResource: db_backend_static.static_node_1.wrapper_rg.0.server + connectionPoints: + dbBackendCpOnIpv4: db_backend_static.static_node_1.wrapper_rg.0.port_ipv4_nated + dbBackendCpOnIpv6: db_backend_static.static_node_1.wrapper_rg.0.port_ipv6 + dbBackendCpOnIpv4Redundancy1: db_backend_static.static_node_1.wrapper_rg.0.port_replication_1 + dbBackendCpOnIpv4Redundancy2: db_backend_static.static_node_1.wrapper_rg.0.port_replication_2 + dbBackendExternallyManagedCp: db_backend_static.static_node_1.wrapper_rg.0.port_internal_ext_managed + virtualStorages: + rootVolume: db_backend_static.static_node_1.wrapper_rg.0.volume_root + dataVolume: db_backend_static.static_node_1.wrapper_rg.0.volume_data + externalConnectionPoints: + dbBackendIpv4: + - db_backend_static.static_node_1.wrapper_rg.0.floating_ip + dbBackendIpv6: + - db_backend_static.static_node_1.wrapper_rg.0.port_ipv6 + - heatResource: db_backend_static.static_node_2.wrapper_rg.0.server + connectionPoints: + dbBackendCpOnIpv4: db_backend_static.static_node_2.wrapper_rg.0.port_ipv4_nated + dbBackendCpOnIpv6: db_backend_static.static_node_2.wrapper_rg.0.port_ipv6 + dbBackendCpOnIpv4Redundancy1: db_backend_static.static_node_2.wrapper_rg.0.port_replication_1 + dbBackendCpOnIpv4Redundancy2: db_backend_static.static_node_2.wrapper_rg.0.port_replication_2 + dbBackendExternallyManagedCp: db_backend_static.static_node_2.wrapper_rg.0.port_internal_ext_managed + virtualStorages: + rootVolume: db_backend_static.static_node_2.wrapper_rg.0.volume_root + dataVolume: db_backend_static.static_node_2.wrapper_rg.0.volume_data + externalConnectionPoints: + dbBackendIpv4: + - db_backend_static.static_node_2.wrapper_rg.0.floating_ip + dbBackendIpv6: + - db_backend_static.static_node_2.wrapper_rg.0.port_ipv6 + externalConnectionPoints: + loadBalancer: + - service_node_static.moving_ip_floating_ip + aspects: + dbBackendAspect: + heatResource: db_backend_aspect_group + vdus: + dbBackend: + - heatResource: wrapper_rg.0.server + connectionPoints: + dbBackendCpOnIpv4: wrapper_rg.0.port_ipv4_nated + dbBackendCpOnIpv6: wrapper_rg.0.port_ipv6 + dbBackendCpOnIpv4Redundancy1: wrapper_rg.0.port_replication_1 + dbBackendCpOnIpv4Redundancy2: wrapper_rg.0.port_replication_2 + dbBackendExternallyManagedCp: wrapper_rg.0.port_internal_ext_managed + virtualStorages: + rootVolume: wrapper_rg.0.volume_root + dataVolume: wrapper_rg.0.volume_data + externalConnectionPoints: + dbBackendIpv4: + - wrapper_rg.0.floating_ip + dbBackendIpv6: + - wrapper_rg.0.port_ipv6 + serviceNodeAspect: + heatResource: service_node_aspect_group + affinity: + local: + - type: same + place: vim + resources: [node_a.server, node_b.server] + - type: same + place: zone + resources: [node_a.server, node_b.server] + - type: different + place: host + resources: [node_a.server, node_b.server] + vdus: + serviceNode: + - heatResource: node_a.server + connectionPoints: + serviceNodeCp: node_a.port_ipv4_nated + serviceNodeExternallyManagedCp: node_a.port_internal_ext_managed + externalConnectionPoints: + serviceNodeIpv4: + - node_a.floating_ip + - heatResource: node_b.server + connectionPoints: + serviceNodeCp: node_b.port_ipv4_nated + serviceNodeExternallyManagedCp: node_b.port_internal_ext_managed + externalConnectionPoints: + serviceNodeIpv4: + - node_b.floating_ip diff --git a/nokiav2/driver/src/test/resources/unittests/missing.vnfd.zip b/nokiav2/driver/src/test/resources/unittests/missing.vnfd.zip Binary files differnew file mode 100644 index 00000000..cfabc407 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/missing.vnfd.zip diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.full.modified.vnfd.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.full.modified.vnfd.yaml new file mode 100644 index 00000000..83f1ea35 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.full.modified.vnfd.yaml @@ -0,0 +1,87 @@ +--- +tosca_definitions_version: "tosca_simple_profile_for_nfv_1_0_0_nokia" +topology_template: + substitution_mappings: + node_type: "tosca.nodes.nfv.VNF" + capabilities: + vnf: + properties: + modifiable_attributes: + extensions: + existingAttribute: + default: "value" + onapCsarId: + default: "kuku" + vimId: + default: "kuku" + interfaces: + Basic: + instantiate: + inputs: + extensions: + pre_actions: + - javascript: "pre" + include: + - "javascript/scalable_prepare_cbam_include.js" + output: "stack_parameters" + - javascript: "javascript/cbam.pre.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + post_actions: + - javascript: "post" + output: "ansible_inventory" + - javascript: "javascript/cbam.post.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + additional_parameters: + kuku: "muku" + jobId: "kuku" + terminate: + inputs: + extensions: + pre_actions: + - javascript: "javascript/cbam.pre.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + post_actions: + - javascript: "javascript/cbam.post.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + additional_parameters: + jobId: "kuku" + Scalable: + scale: + inputs: + extensions: + pre_actions: + - javascript: "javascript/cbam.pre.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + post_actions: + - javascript: "javascript/cbam.post.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + additional_parameters: + jobId: "kuku" + Healable: + heal: + inputs: + extensions: + pre_actions: + - javascript: "javascript/cbam.pre.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + post_actions: + - javascript: "javascript/cbam.post.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + additional_parameters: + jobId: "kuku" diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.full.original.vnfd.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.full.original.vnfd.yaml new file mode 100644 index 00000000..42569b04 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.full.original.vnfd.yaml @@ -0,0 +1,33 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0_nokia + +topology_template: + substitution_mappings: + node_type: tosca.nodes.nfv.VNF + capabilities: + vnf: + properties: + modifiable_attributes: + extensions: + existingAttribute: + default: "value" + interfaces: + Basic: + instantiate: + inputs: + extensions: + pre_actions: + - javascript: pre + include: + - javascript/scalable_prepare_cbam_include.js + output: stack_parameters + post_actions: + - javascript: post + output: ansible_inventory + additional_parameters: + kuku: muku + terminate: + Scalable: + scale: + Healable: + heal: + diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.minimal.modified.vnfd.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.minimal.modified.vnfd.yaml new file mode 100644 index 00000000..2b05ecf1 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.minimal.modified.vnfd.yaml @@ -0,0 +1,46 @@ +--- +tosca_definitions_version: "tosca_simple_profile_for_nfv_1_0_0_nokia" +topology_template: + substitution_mappings: + node_type: "tosca.nodes.nfv.VNF" + interfaces: + Basic: + instantiate: + inputs: + extensions: + pre_actions: + - javascript: "javascript/cbam.pre.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + post_actions: + - javascript: "javascript/cbam.post.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + additional_parameters: + jobId: "kuku" + terminate: + inputs: + extensions: + pre_actions: + - javascript: "javascript/cbam.pre.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + post_actions: + - javascript: "javascript/cbam.post.collectConnectionPoints.js" + include: + - "javascript/cbam.collectConnectionPoints.js" + output: "operation_result" + additional_parameters: + jobId: "kuku" + capabilities: + vnf: + properties: + modifiable_attributes: + extensions: + onapCsarId: + default: "kuku" + vimId: + default: "kuku" diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.minimal.original.vnfd.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.minimal.original.vnfd.yaml new file mode 100644 index 00000000..7709793c --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.minimal.original.vnfd.yaml @@ -0,0 +1,9 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0_nokia + +topology_template: + substitution_mappings: + node_type: tosca.nodes.nfv.VNF + interfaces: + Basic: + instantiate: + terminate: diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.package.zip b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.package.zip Binary files differnew file mode 100644 index 00000000..ac555dff --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.package.zip diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.package.zip.vnfd b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.package.zip.vnfd new file mode 100644 index 00000000..3c121386 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/cbam.package.zip.vnfd @@ -0,0 +1,17 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0_nokia + +topology_template: + substitution_mappings: + node_type: tosca.nodes.nfv.VNF + properties: + descriptor_id: Nokia~Maria DB~1.0~1.0 + descriptor_version: '1.0' + provider: Nokia + product_name: Maria DB + software_version: '1.0' + product_info_name: Maria DB + product_info_description: Relational database, non-scalable + interfaces: + Basic: + instantiate: + terminate: diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/empty.vnfd.cbam.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/empty.vnfd.cbam.yaml new file mode 100644 index 00000000..45bfb73f --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/empty.vnfd.cbam.yaml @@ -0,0 +1,11 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0_nokia + +topology_template: + substitution_mappings: + node_type: tosca.nodes.nfv.VNF + properties: + descriptor_version: '1.0' + provider: myProvider + product_name: 'myName' + software_version: '2.0' + product_info_name: product_info_name
\ No newline at end of file diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/empty.vnfd.onap.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/empty.vnfd.onap.yaml new file mode 100644 index 00000000..1cbc8ef7 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/empty.vnfd.onap.yaml @@ -0,0 +1,14 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +metadata: + vendor: Nokia + csarVersion: 1.0 + csarProvider: myProvider + id: Simple + version: 2.0 + csarType: NFAR + name: myName + vnfdVersion: 1.0 + +topology_template: + node_templates: diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.cbam.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.cbam.yaml new file mode 100644 index 00000000..a5e18eec --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.cbam.yaml @@ -0,0 +1,85 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0_nokia + +topology_template: + substitution_mappings: + node_type: tosca.nodes.nfv.VNF + properties: + descriptor_version: '1.0' + provider: myProvider + product_name: 'myName' + software_version: '2.0' + product_info_name: product_info_name + node_templates: + vduNode: + type: tosca.nodes.nfv.VDU + properties: + description: myVduDesc + requirements: + - virtual_compute: myCompute + - virtual_storage: myStorage1 + - virtual_storage: myStorage2 + + + myCompute: + type: tosca.nodes.nfv.VirtualCompute + properties: + virtual_memory: + virtual_mem_size: 8192 MB + virtual_cpu: + num_virtual_cpu: 4 + virtual_cpu_clock: 1234 Mhz + myStorage1: + type: tosca.nodes.nfv.VirtualStorage + properties: + id: myStorage1 + size_of_storage: 1G + + myStorage2: + type: tosca.nodes.nfv.VirtualStorage + properties: + id: myStorage2 + size_of_storage: 2G + + myNetwork1: + type: tosca.nodes.nfv.VL + + myNetwork2: + type: tosca.nodes.nfv.VL + + icpWithOutEcp: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + description: myDescription + requirements: + - virtual_binding: vduNode + - virtual_link: myNetwork1 + + icpWithEcp: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + description: myDescription + requirements: + - virtual_binding: vduNode + - virtual_link: myNetwork1 + + myEcp: + type: tosca.nodes.nfv.ECP + properties: + layer_protocol: ipv4 + requirements: + - internal_connection_point: icpWithEcp + + icpWithOutVdu: + type: tosca.nodes.nfv.ICP + properties: + layer_protocol: ipv4 + description: myDescription + + ecpWithIcpWithOutVdu: + type: tosca.nodes.nfv.ECP + properties: + layer_protocol: ipv4 + requirements: + - internal_connection_point: icpWithOutVdu
\ No newline at end of file diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.inconsistent.cbam.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.inconsistent.cbam.yaml new file mode 100644 index 00000000..abb1243f --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.inconsistent.cbam.yaml @@ -0,0 +1,18 @@ +tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0_nokia + +topology_template: + substitution_mappings: + node_type: tosca.nodes.nfv.VNF + properties: + descriptor_version: '1.0' + provider: myProvider + product_name: 'myName' + software_version: '2.0' + product_info_name: product_info_name + node_templates: + vduNode: + type: tosca.nodes.nfv.VDU + properties: + description: myVduDesc + requirements: + - virtual_compute: myComputeMissing diff --git a/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.onap.yaml b/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.onap.yaml new file mode 100644 index 00000000..ddb96bf0 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/packageconverter/nodes.vnfd.onap.yaml @@ -0,0 +1,80 @@ +tosca_definitions_version: tosca_simple_yaml_1_0 + +metadata: + vendor: Nokia + csarVersion: 1.0 + csarProvider: myProvider + id: Simple + version: 2.0 + csarType: NFAR + name: myName + vnfdVersion: 1.0 + +topology_template: + node_templates: + vduNode: + type: tosca.nodes.nfv.VDU.Compute + capabilities: + virtual_compute: + properties: + virtual_memory: + virtual_mem_size: 8192 MB + virtual_cpu: + num_virtual_cpu: 4 + requirements: + - virtual_storage: + capability: tosca.capabilities.nfv.VirtualStorage + node: myStorage1 + - virtual_storage: + capability: tosca.capabilities.nfv.VirtualStorage + node: myStorage2 + myStorage1: + type: tosca.nodes.nfv.VDU.VirtualStorage + properties: + id: myStorage1 + type_of_storage: volume + size_of_storage: 1G + myStorage2: + type: tosca.nodes.nfv.VDU.VirtualStorage + properties: + id: myStorage2 + type_of_storage: volume + size_of_storage: 2G + myNetwork1: + type: tosca.nodes.nfv.VnfVirtualLinkDesc + properties: + vl_flavours: + flavours: + flavourId: notUsed + myNetwork2: + type: tosca.nodes.nfv.VnfVirtualLinkDesc + properties: + vl_flavours: + flavours: + flavourId: notUsed + icpWithOutEcp: + type: tosca.nodes.nfv.VduCpd + properties: + layer_protocol: ipv4 + role: leaf + description: myDescription + requirements: + - virtual_binding: vduNode + - virtual_link: myNetwork1 + icpWithEcp: + type: tosca.nodes.nfv.VduCpd + properties: + layer_protocol: ipv4 + role: leaf + description: myDescription + requirements: + - virtual_binding: vduNode + - virtual_link: myNetwork1 + myEcp: + type: tosca.nodes.nfv.VduCpd + properties: + layer_protocol: ipv4 + role: leaf + description: myDescription + requirements: + - virtual_binding: vduNode diff --git a/nokiav2/driver/src/test/resources/unittests/sample.cert.pem b/nokiav2/driver/src/test/resources/unittests/sample.cert.pem new file mode 100644 index 00000000..0e41d269 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/sample.cert.pem @@ -0,0 +1,14 @@ +-----BEGIN CERTIFICATE----- +MIICEjCCAXsCAg36MA0GCSqGSIb3DQEBBQUAMIGbMQswCQYDVQQGEwJKUDEOMAwG +A1UECBMFVG9reW8xEDAOBgNVBAcTB0NodW8ta3UxETAPBgNVBAoTCEZyYW5rNERE +MRgwFgYDVQQLEw9XZWJDZXJ0IFN1cHBvcnQxGDAWBgNVBAMTD0ZyYW5rNEREIFdl +YiBDQTEjMCEGCSqGSIb3DQEJARYUc3VwcG9ydEBmcmFuazRkZC5jb20wHhcNMTIw +ODIyMDUyNjU0WhcNMTcwODIxMDUyNjU0WjBKMQswCQYDVQQGEwJKUDEOMAwGA1UE +CAwFVG9reW8xETAPBgNVBAoMCEZyYW5rNEREMRgwFgYDVQQDDA93d3cuZXhhbXBs +ZS5jb20wXDANBgkqhkiG9w0BAQEFAANLADBIAkEAm/xmkHmEQrurE/0re/jeFRLl +8ZPjBop7uLHhnia7lQG/5zDtZIUC3RVpqDSwBuw/NTweGyuP+o8AG98HxqxTBwID +AQABMA0GCSqGSIb3DQEBBQUAA4GBABS2TLuBeTPmcaTaUW/LCB2NYOy8GMdzR1mx +8iBIu2H6/E2tiY3RIevV2OW61qY2/XRQg7YPxx3ffeUugX9F4J/iPnnu1zAxxyBy +2VguKv4SWjRFoRkIfIlHX0qVviMhSlNy2ioFLy7JcPZb+v3ftDGywUqcBiVDoea0 +Hn+GmxZA +-----END CERTIFICATE-----
\ No newline at end of file diff --git a/nokiav2/driver/src/test/resources/unittests/vnfd.full.yaml b/nokiav2/driver/src/test/resources/unittests/vnfd.full.yaml new file mode 100644 index 00000000..460f7f10 --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/vnfd.full.yaml @@ -0,0 +1,24 @@ +topology_template: + substitution_mappings: + capabilities: + deployment_flavour: + properties: + flavour_id: myFlavorId + instantiation_levels: + level1: + vdu_levels: + vdu1: + number_of_instances: 1 + vdu2: + number_of_instances: 2 + level2: + vdu_levels: + vdu1: + number_of_instances: 2 + interfaces: + Basic: + scale: + inputs: + additional_parameters: + jobId: kuku + a: valueInVnfd
\ No newline at end of file diff --git a/nokiav2/driver/src/test/resources/unittests/vnfd.instantiation.yaml b/nokiav2/driver/src/test/resources/unittests/vnfd.instantiation.yaml new file mode 100644 index 00000000..ef858dbc --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/vnfd.instantiation.yaml @@ -0,0 +1,16 @@ +topology_template: + substitution_mappings: + capabilities: + deployment_flavour: + properties: + instantiation_levels: + level1: + vdu_levels: + vdu1: + number_of_instances: 1 + vdu2: + number_of_instances: 2 + level2: + vdu_levels: + vdu1: + number_of_instances: 2 diff --git a/nokiav2/driver/src/test/resources/unittests/vnfd.scale.yaml b/nokiav2/driver/src/test/resources/unittests/vnfd.scale.yaml new file mode 100644 index 00000000..478fedaf --- /dev/null +++ b/nokiav2/driver/src/test/resources/unittests/vnfd.scale.yaml @@ -0,0 +1,12 @@ +topology_template: + policies: + - heat_mapping: + properties: + aspects: + aspect1: + vdus: + vdu1: + - heatResource: wrapper_rg.0.server + - heatResource: wrapper_rg.1.server + vdu2: + - heatResource: wrapper_rg2.0.server
\ No newline at end of file |