2 * ============LICENSE_START=======================================================
3 * Copyright (C) 2020 Nordix Foundation.
4 * ================================================================================
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
17 * SPDX-License-Identifier: Apache-2.0
18 * ============LICENSE_END=========================================================
20 package org.onap.so.etsi.nfvo.ns.workflow.engine.tasks;
22 import static com.github.tomakehurst.wiremock.client.WireMock.get;
23 import static com.github.tomakehurst.wiremock.client.WireMock.notFound;
24 import static com.github.tomakehurst.wiremock.client.WireMock.ok;
25 import static com.github.tomakehurst.wiremock.client.WireMock.okJson;
26 import static com.github.tomakehurst.wiremock.client.WireMock.put;
27 import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching;
28 import static org.junit.Assert.assertEquals;
29 import static org.junit.Assert.assertNotNull;
30 import static org.junit.Assert.assertTrue;
31 import static org.onap.aaiclient.client.aai.AAIVersion.V19;
32 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME;
33 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_REST_TEMPLATE_BEAN;
34 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003AdapterConfiguration.SOL003_ADAPTER_REST_TEMPLATE_BEAN;
35 import static org.springframework.test.web.client.ExpectedCount.times;
36 import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
37 import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
38 import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
40 import java.io.IOException;
41 import java.nio.file.Files;
42 import java.nio.file.Paths;
43 import java.time.LocalDateTime;
44 import java.util.ArrayList;
45 import java.util.HashMap;
46 import java.util.List;
48 import java.util.Map.Entry;
49 import java.util.Optional;
50 import java.util.UUID;
51 import java.util.stream.Collectors;
52 import org.camunda.bpm.engine.history.HistoricProcessInstance;
53 import org.camunda.bpm.engine.history.HistoricVariableInstance;
54 import org.hamcrest.text.MatchesPattern;
55 import org.junit.After;
56 import org.junit.Before;
57 import org.junit.Test;
58 import org.onap.aaiclient.client.aai.entities.Results;
59 import org.onap.aaiclient.client.graphinventory.entities.Resource;
60 import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfResponse;
61 import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStatusRetrievalStatusEnum;
62 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo;
63 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfPkgInfo;
64 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.BaseTest;
65 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.GsonProvider;
66 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd.NetworkServiceDescriptor;
67 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service.JobExecutorService;
68 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob;
69 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNfInst;
70 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst;
71 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpOcc;
72 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.OperationStateEnum;
73 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State;
74 import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider;
75 import org.onap.so.etsi.nfvo.ns.lcm.model.InstantiateNsRequest;
76 import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf;
77 import org.springframework.beans.factory.annotation.Autowired;
78 import org.springframework.beans.factory.annotation.Qualifier;
79 import org.springframework.http.HttpMethod;
80 import org.springframework.http.MediaType;
81 import org.springframework.http.converter.json.GsonHttpMessageConverter;
82 import org.springframework.test.web.client.MockRestServiceServer;
83 import org.springframework.web.client.RestTemplate;
84 import com.fasterxml.jackson.core.JsonProcessingException;
85 import com.fasterxml.jackson.databind.ObjectMapper;
86 import com.google.gson.Gson;
89 * @author Andrew Lamb (andrew.a.lamb@est.tech)
90 * @author Waqas Ikram (waqas.ikram@est.tech)
93 public class InstantiateNsTaskTest extends BaseTest {
95 private static final String TENANT_ID = "6ca8680feba04dad9254f423c6e28e1c";
96 private static final String CLOUD_REGION = "regionOne";
97 private static final String CLOUD_OWNER = "CloudOwner";
98 private static final String UUID_REGEX =
99 "[0-9a-zA-Z]{8}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{4}\\-[0-9a-zA-Z]{12}";
100 private static final String VCPE_VBRGEMU_VNFD_ID = "b1bb0ce7-2222-4fa7-95ed-4840d70a1102";
101 private static final String VCPE_VBNG = "b1bb0ce7-2222-4fa7-95ed-4840d70a1101";
102 private static final String VCPE_INFRA_VNFD_ID = "b1bb0ce7-2222-4fa7-95ed-4840d70a1100";
103 private static final String VGMUX_VNFD_ID = "0408f076-e6c0-4c82-9940-272fddbb82de";
104 private static final String VGW_VNFD_ID = "3fca3543-07f5-492f-812c-ed462e4f94f4";
105 private static final String[] VCPE_VNFDS =
106 new String[] {VGW_VNFD_ID, VGMUX_VNFD_ID, VCPE_INFRA_VNFD_ID, VCPE_VBNG, VCPE_VBRGEMU_VNFD_ID};
107 private static final String SAMPLE_NSD_FILE = "src/test/resources/ns.csar";
108 private static final String NS_NAME = "InstantiateNetworkService";
111 private DatabaseServiceProvider databaseServiceProvider;
114 @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
115 private RestTemplate etsiCatalogRestTemplate;
118 @Qualifier(SOL003_ADAPTER_REST_TEMPLATE_BEAN)
119 private RestTemplate sol003AdapterRestTemplate;
121 private MockRestServiceServer mockEtsiCatalogRestServiceServer;
123 private MockRestServiceServer mockSol003AdapterRestServiceServer;
126 private JobExecutorService objUnderTest;
129 private GsonProvider gsonProvider;
133 private static final Map<String, String> VNFD_ID_TO_VNFPKG_ID_MAPPING = new HashMap<>();
135 for (final String vnfd : VCPE_VNFDS) {
136 VNFD_ID_TO_VNFPKG_ID_MAPPING.put(vnfd, UUID.randomUUID().toString());
141 public void before() {
142 wireMockServer.resetAll();
143 gson = gsonProvider.getGson();
145 mockEtsiCatalogRestServiceServer =
146 MockRestServiceServer.bindTo(etsiCatalogRestTemplate).ignoreExpectOrder(true).build();
147 mockSol003AdapterRestServiceServer =
148 MockRestServiceServer.bindTo(sol003AdapterRestTemplate).ignoreExpectOrder(true).build();
150 etsiCatalogRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
151 sol003AdapterRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
156 public void after() {
157 wireMockServer.resetAll();
158 mockEtsiCatalogRestServiceServer.reset();
162 public void testInstantiateNsWorkflow_JustUpdateStatus_SuccessfullCase() throws InterruptedException, IOException {
163 final String nsdId = UUID.randomUUID().toString();
164 final String nsdName = NS_NAME + "-" + System.currentTimeMillis();
166 final NfvoNsInst newNfvoNsInst = new NfvoNsInst().nsInstId(nsdId).name(nsdName)
167 .nsPackageId(UUID.randomUUID().toString()).nsPackageId(nsdId).nsdId(nsdId).nsdInvariantId(nsdId)
168 .status(State.NOT_INSTANTIATED).statusUpdatedTime(LocalDateTime.now());
170 databaseServiceProvider.saveNfvoNsInst(newNfvoNsInst);
172 mockSol003AdapterEndpoints();
173 mockAAIEndpoints(nsdId);
174 mockEtsiCatalogEndpoints(nsdId);
176 final String nsLcmOpOccId =
177 objUnderTest.runInstantiateNsJob(newNfvoNsInst.getNsInstId(), getInstantiateNsRequest());
179 final Optional<NfvoJob> optional = getJobByResourceId(newNfvoNsInst.getNsInstId());
180 assertTrue(optional.isPresent());
181 final NfvoJob nfvoJob = optional.get();
183 assertTrue(waitForProcessInstanceToFinish(nfvoJob.getProcessInstanceId()));
185 final HistoricProcessInstance historicProcessInstance =
186 getHistoricProcessInstance(nfvoJob.getProcessInstanceId());
187 assertNotNull(historicProcessInstance);
189 assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
191 // check if value in database has updated
192 final Optional<NfvoNsInst> optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsdId);
193 final NfvoNsInst nfvoNsInst = optionalNfvoNsInst.get();
194 assertEquals(State.INSTANTIATED, nfvoNsInst.getStatus());
196 final HistoricVariableInstance historicVariableInstance =
197 getVariable(nfvoJob.getProcessInstanceId(), NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME);
198 assertNotNull(historicVariableInstance);
199 final NetworkServiceDescriptor nsd = (NetworkServiceDescriptor) historicVariableInstance.getValue();
202 assertEquals(VNFD_ID_TO_VNFPKG_ID_MAPPING.size(), nsd.getVnfs().size());
204 final List<NfvoNfInst> nfvoNfInsts = databaseServiceProvider.getNfvoNfInstByNsInstId(nsdId);
206 assertEquals(VNFD_ID_TO_VNFPKG_ID_MAPPING.size(), nfvoNfInsts.size());
208 final Optional<NsLcmOpOcc> optionalNsLcmOpOcc = databaseServiceProvider.getNsLcmOpOcc(nsLcmOpOccId);
209 assertTrue(optionalNsLcmOpOcc.isPresent());
211 assertEquals(OperationStateEnum.COMPLETED, optionalNsLcmOpOcc.get().getOperationState());
213 final Map<String, NfvoNfInst> nfvoNfInstsMap =
214 nfvoNfInsts.stream().collect(Collectors.toMap(NfvoNfInst::getVnfdId, nfvoNfInst -> nfvoNfInst));
216 for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
217 assertTrue(nfvoNfInstsMap.containsKey(entry.getKey()));
218 assertEquals(State.INSTANTIATED, nfvoNfInstsMap.get(entry.getKey()).getStatus());
224 private void mockSol003AdapterEndpoints() {
225 mockSol003AdapterRestServiceServer
226 .expect(times(VNFD_ID_TO_VNFPKG_ID_MAPPING.size()),
227 requestTo(MatchesPattern.matchesPattern(SOL003_ADAPTER_ENDPOINT_URL + "/vnfs/.*")))
228 .andExpect(method(HttpMethod.POST))
229 .andRespond(withSuccess(gson.toJson(new CreateVnfResponse().jobId(UUID.randomUUID().toString())),
230 MediaType.APPLICATION_JSON));
232 mockSol003AdapterRestServiceServer
233 .expect(times(VNFD_ID_TO_VNFPKG_ID_MAPPING.size()),
234 requestTo(MatchesPattern.matchesPattern(SOL003_ADAPTER_ENDPOINT_URL + "/jobs/.*")))
235 .andExpect(method(HttpMethod.GET))
236 .andRespond(withSuccess(gson.toJson(
237 new org.onap.so.adapters.etsisol003adapter.lcm.v1.model.QueryJobResponse().operationState(
238 org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStateEnum.COMPLETED)
239 .operationStatusRetrievalStatus(OperationStatusRetrievalStatusEnum.STATUS_FOUND)),
240 MediaType.APPLICATION_JSON));
243 private void mockEtsiCatalogEndpoints(final String nsdId) throws IOException {
244 mockEtsiCatalogRestServiceServer.expect(requestTo(ETSI_CATALOG_URL + "/nsd/v1/ns_descriptors/" + nsdId))
245 .andExpect(method(HttpMethod.GET))
246 .andRespond(withSuccess(gson.toJson(getNSPackageModel(nsdId)), MediaType.APPLICATION_JSON));
247 mockEtsiCatalogRestServiceServer
248 .expect(requestTo(ETSI_CATALOG_URL + "/nsd/v1/ns_descriptors/" + nsdId + "/nsd_content"))
249 .andExpect(method(HttpMethod.GET)).andRespond(withSuccess(
250 getFileContent(getAbsolutePath(SAMPLE_NSD_FILE)), MediaType.APPLICATION_OCTET_STREAM));
252 for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
253 mockEtsiCatalogRestServiceServer
254 .expect(requestTo(ETSI_CATALOG_URL + "/vnfpkgm/v1/vnf_packages/" + entry.getValue()))
255 .andExpect(method(HttpMethod.GET)).andRespond(withSuccess(
256 gson.toJson(getVnfPkgInfo(entry.getKey(), entry.getValue())), MediaType.APPLICATION_JSON));
261 private VnfPkgInfo getVnfPkgInfo(final String vnfdId, final String vnfPkgId) {
262 return new VnfPkgInfo().id(vnfPkgId).vnfdId(vnfdId);
265 private InstantiateNsRequest getInstantiateNsRequest() {
266 final Map<String, Object> additionalParams = new HashMap<>();
267 additionalParams.put("vim_id", CLOUD_OWNER + "_" + CLOUD_REGION + "_" + TENANT_ID);
269 final InstantiateNsRequest instantiateNsRequest = new InstantiateNsRequest().nsFlavourId("default");
271 for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
273 .addAdditionalParamsForVnfItem(new NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf()
274 .vnfProfileId(entry.getValue()).additionalParams(additionalParams));
277 return instantiateNsRequest;
280 private NsdInfo getNSPackageModel(final String nsdId) {
281 return new NsdInfo().id(nsdId).nsdId(nsdId).nsdInvariantId(NSD_INVARIANT_ID).nsdName("vcpe").nsdDesigner("ONAP")
282 .vnfPkgIds(new ArrayList<>(VNFD_ID_TO_VNFPKG_ID_MAPPING.values()));
285 private byte[] getFileContent(final String path) throws IOException {
286 return Files.readAllBytes(Paths.get(path));
290 private String getAbsolutePath(final String path) {
291 return new File(path).getAbsolutePath();
294 private void mockAAIEndpoints(final String nsdId) throws JsonProcessingException {
295 final String modelEndpoint = "/aai/" + V19 + "/network/generic-vnfs/generic-vnf/" + UUID_REGEX;
297 wireMockServer.stubFor(
298 get(urlMatching(modelEndpoint + "\\?resultIndex=0&resultSize=1&format=count")).willReturn(notFound()));
300 wireMockServer.stubFor(put(urlMatching(modelEndpoint)).willReturn(ok()));
301 wireMockServer.stubFor(put(urlMatching(modelEndpoint + "/relationship-list/relationship")).willReturn(ok()));
303 wireMockServer.stubFor(get(urlMatching(modelEndpoint)).willReturn(ok())
304 .willReturn(okJson("{\"orchestration-status\": \"Created\"}")));
306 wireMockServer.stubFor(get(urlMatching("/aai/" + V19 + "/nodes/service-instances/service-instance/.*"))
307 .willReturn(okJson(getResourceResultsResponseAsJson(nsdId))));
309 wireMockServer.stubFor(
310 put(urlMatching("/aai/" + V19 + "/cloud-infrastructure/cloud-regions/cloud-region/" + CLOUD_OWNER + "/"
311 + CLOUD_REGION + "/tenants/tenant/" + TENANT_ID + "/relationship-list/relationship"))
316 private String getResourceResultsResponseAsJson(final String nsdId) throws JsonProcessingException {
317 final Resource resource = new Resource();
318 resource.setResourceType("service-instance");
319 resource.setResourceLink("/aai/" + V19 + "/business/customers/customer/" + GLOBAL_CUSTOMER_ID
320 + "/service-subscriptions/service-subscription/NetworkService/service-instances/service-instance/"
322 final Results<Resource> results = new Results<>();
323 results.getResult().add(resource);
324 return new ObjectMapper().writeValueAsString(results);