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.so.etsi.nfvo.ns.lcm.bpmn.flows.CamundaVariableNameConstants.NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME;
32 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.etsicatalog.EtsiCatalogServiceProviderConfiguration.ETSI_CATALOG_REST_TEMPLATE_BEAN;
33 import static org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.extclients.vnfm.Sol003AdapterConfiguration.SOL003_ADAPTER_REST_TEMPLATE_BEAN;
34 import static org.springframework.test.web.client.ExpectedCount.times;
35 import static org.springframework.test.web.client.match.MockRestRequestMatchers.method;
36 import static org.springframework.test.web.client.match.MockRestRequestMatchers.requestTo;
37 import static org.springframework.test.web.client.response.MockRestResponseCreators.withSuccess;
39 import java.io.IOException;
40 import java.nio.file.Files;
41 import java.nio.file.Paths;
42 import java.time.LocalDateTime;
43 import java.util.ArrayList;
44 import java.util.HashMap;
45 import java.util.List;
47 import java.util.Map.Entry;
48 import java.util.Optional;
49 import java.util.UUID;
50 import java.util.stream.Collectors;
51 import org.camunda.bpm.engine.history.HistoricProcessInstance;
52 import org.camunda.bpm.engine.history.HistoricVariableInstance;
53 import org.hamcrest.text.MatchesPattern;
54 import org.junit.After;
55 import org.junit.Before;
56 import org.junit.Test;
57 import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.CreateVnfResponse;
58 import org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStatusRetrievalStatusEnum;
59 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.NsdInfo;
60 import org.onap.so.adapters.etsisol003adapter.pkgm.extclients.etsicatalog.model.VnfPkgInfo;
61 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.BaseTest;
62 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.GsonProvider;
63 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd.NetworkServiceDescriptor;
64 import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.service.JobExecutorService;
65 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoJob;
66 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNfInst;
67 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NfvoNsInst;
68 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.NsLcmOpOcc;
69 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.OperationStateEnum;
70 import org.onap.so.etsi.nfvo.ns.lcm.database.beans.State;
71 import org.onap.so.etsi.nfvo.ns.lcm.database.service.DatabaseServiceProvider;
72 import org.onap.so.etsi.nfvo.ns.lcm.model.InstantiateNsRequest;
73 import org.onap.so.etsi.nfvo.ns.lcm.model.NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf;
74 import org.springframework.beans.factory.annotation.Autowired;
75 import org.springframework.beans.factory.annotation.Qualifier;
76 import org.springframework.http.HttpMethod;
77 import org.springframework.http.MediaType;
78 import org.springframework.http.converter.json.GsonHttpMessageConverter;
79 import org.springframework.test.web.client.MockRestServiceServer;
80 import org.springframework.web.client.RestTemplate;
81 import com.google.gson.Gson;
84 * @author Andrew Lamb (andrew.a.lamb@est.tech)
85 * @author Waqas Ikram (waqas.ikram@est.tech)
88 public class InstantiateNsTaskTest extends BaseTest {
90 private static final String TENANT_ID = "6ca8680feba04dad9254f423c6e28e1c";
91 private static final String CLOUD_REGION = "regionOne";
92 private static final String CLOUD_OWNER = "CloudOwner";
93 private static final String UUID_REGEX =
94 "[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}";
95 private static final String VCPE_VBRGEMU_VNFD_ID = "b1bb0ce7-2222-4fa7-95ed-4840d70a1102";
96 private static final String VCPE_VBNG = "b1bb0ce7-2222-4fa7-95ed-4840d70a1101";
97 private static final String VCPE_INFRA_VNFD_ID = "b1bb0ce7-2222-4fa7-95ed-4840d70a1100";
98 private static final String VGMUX_VNFD_ID = "0408f076-e6c0-4c82-9940-272fddbb82de";
99 private static final String VGW_VNFD_ID = "3fca3543-07f5-492f-812c-ed462e4f94f4";
100 private static final String[] VCPE_VNFDS =
101 new String[] {VGW_VNFD_ID, VGMUX_VNFD_ID, VCPE_INFRA_VNFD_ID, VCPE_VBNG, VCPE_VBRGEMU_VNFD_ID};
102 private static final String SAMPLE_NSD_FILE = "src/test/resources/ns.csar";
103 private static final String NS_NAME = "InstantiateNetworkService";
106 private DatabaseServiceProvider databaseServiceProvider;
109 @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
110 private RestTemplate etsiCatalogRestTemplate;
113 @Qualifier(SOL003_ADAPTER_REST_TEMPLATE_BEAN)
114 private RestTemplate sol003AdapterRestTemplate;
116 private MockRestServiceServer mockEtsiCatalogRestServiceServer;
118 private MockRestServiceServer mockSol003AdapterRestServiceServer;
121 private JobExecutorService objUnderTest;
124 private GsonProvider gsonProvider;
128 private static final Map<String, String> VNFD_ID_TO_VNFPKG_ID_MAPPING = new HashMap<>();
130 for (final String vnfd : VCPE_VNFDS) {
131 VNFD_ID_TO_VNFPKG_ID_MAPPING.put(vnfd, UUID.randomUUID().toString());
136 public void before() {
137 wireMockServer.resetAll();
138 gson = gsonProvider.getGson();
140 mockEtsiCatalogRestServiceServer =
141 MockRestServiceServer.bindTo(etsiCatalogRestTemplate).ignoreExpectOrder(true).build();
142 mockSol003AdapterRestServiceServer =
143 MockRestServiceServer.bindTo(sol003AdapterRestTemplate).ignoreExpectOrder(true).build();
145 etsiCatalogRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
146 sol003AdapterRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
151 public void after() {
152 wireMockServer.resetAll();
153 mockEtsiCatalogRestServiceServer.reset();
157 public void testInstantiateNsWorkflow_JustUpdateStatus_SuccessfullCase() throws InterruptedException, IOException {
158 final String nsdId = UUID.randomUUID().toString();
159 final String nsdName = NS_NAME + "-" + System.currentTimeMillis();
161 final NfvoNsInst newNfvoNsInst = new NfvoNsInst().nsInstId(nsdId).name(nsdName)
162 .nsPackageId(UUID.randomUUID().toString()).nsPackageId(nsdId).nsdId(nsdId).nsdInvariantId(nsdId)
163 .status(State.NOT_INSTANTIATED).statusUpdatedTime(LocalDateTime.now());
165 databaseServiceProvider.saveNfvoNsInst(newNfvoNsInst);
167 mockSol003AdapterEndpoints();
168 mockAAIEndpoints(nsdId);
169 mockEtsiCatalogEndpoints(nsdId);
171 final String nsLcmOpOccId =
172 objUnderTest.runInstantiateNsJob(newNfvoNsInst.getNsInstId(), getInstantiateNsRequest());
174 final Optional<NfvoJob> optional = getJobByResourceId(newNfvoNsInst.getNsInstId());
175 assertTrue(optional.isPresent());
176 final NfvoJob nfvoJob = optional.get();
178 assertTrue(waitForProcessInstanceToFinish(nfvoJob.getProcessInstanceId()));
180 final HistoricProcessInstance historicProcessInstance =
181 getHistoricProcessInstance(nfvoJob.getProcessInstanceId());
182 assertNotNull(historicProcessInstance);
184 assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
186 // check if value in database has updated
187 final Optional<NfvoNsInst> optionalNfvoNsInst = databaseServiceProvider.getNfvoNsInst(nsdId);
188 final NfvoNsInst nfvoNsInst = optionalNfvoNsInst.get();
189 assertEquals(State.INSTANTIATED, nfvoNsInst.getStatus());
191 final HistoricVariableInstance historicVariableInstance =
192 getVariable(nfvoJob.getProcessInstanceId(), NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME);
193 assertNotNull(historicVariableInstance);
194 final NetworkServiceDescriptor nsd = (NetworkServiceDescriptor) historicVariableInstance.getValue();
197 assertEquals(VNFD_ID_TO_VNFPKG_ID_MAPPING.size(), nsd.getVnfs().size());
199 final List<NfvoNfInst> nfvoNfInsts = databaseServiceProvider.getNfvoNfInstByNsInstId(nsdId);
201 assertEquals(VNFD_ID_TO_VNFPKG_ID_MAPPING.size(), nfvoNfInsts.size());
203 final Optional<NsLcmOpOcc> optionalNsLcmOpOcc = databaseServiceProvider.getNsLcmOpOcc(nsLcmOpOccId);
204 assertTrue(optionalNsLcmOpOcc.isPresent());
206 assertEquals(OperationStateEnum.COMPLETED, optionalNsLcmOpOcc.get().getOperationState());
208 final Map<String, NfvoNfInst> nfvoNfInstsMap =
209 nfvoNfInsts.stream().collect(Collectors.toMap(NfvoNfInst::getVnfdId, nfvoNfInst -> nfvoNfInst));
211 for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
212 assertTrue(nfvoNfInstsMap.containsKey(entry.getKey()));
213 assertEquals(State.INSTANTIATED, nfvoNfInstsMap.get(entry.getKey()).getStatus());
219 private void mockSol003AdapterEndpoints() {
220 mockSol003AdapterRestServiceServer
221 .expect(times(VNFD_ID_TO_VNFPKG_ID_MAPPING.size()),
222 requestTo(MatchesPattern.matchesPattern(SOL003_ADAPTER_ENDPOINT_URL + "/vnfs/.*")))
223 .andExpect(method(HttpMethod.POST))
224 .andRespond(withSuccess(gson.toJson(new CreateVnfResponse().jobId(UUID.randomUUID().toString())),
225 MediaType.APPLICATION_JSON));
227 mockSol003AdapterRestServiceServer
228 .expect(times(VNFD_ID_TO_VNFPKG_ID_MAPPING.size()),
229 requestTo(MatchesPattern.matchesPattern(SOL003_ADAPTER_ENDPOINT_URL + "/jobs/.*")))
230 .andExpect(method(HttpMethod.GET))
231 .andRespond(withSuccess(gson.toJson(
232 new org.onap.so.adapters.etsisol003adapter.lcm.v1.model.QueryJobResponse().operationState(
233 org.onap.so.adapters.etsisol003adapter.lcm.v1.model.OperationStateEnum.COMPLETED)
234 .operationStatusRetrievalStatus(OperationStatusRetrievalStatusEnum.STATUS_FOUND)),
235 MediaType.APPLICATION_JSON));
238 private void mockEtsiCatalogEndpoints(final String nsdId) throws IOException {
239 mockEtsiCatalogRestServiceServer.expect(requestTo(ETSI_CATALOG_URL + "/nsd/v1/ns_descriptors/" + nsdId))
240 .andExpect(method(HttpMethod.GET))
241 .andRespond(withSuccess(gson.toJson(getNSPackageModel(nsdId)), MediaType.APPLICATION_JSON));
242 mockEtsiCatalogRestServiceServer
243 .expect(requestTo(ETSI_CATALOG_URL + "/nsd/v1/ns_descriptors/" + nsdId + "/nsd_content"))
244 .andExpect(method(HttpMethod.GET)).andRespond(withSuccess(
245 getFileContent(getAbsolutePath(SAMPLE_NSD_FILE)), MediaType.APPLICATION_OCTET_STREAM));
247 for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
248 mockEtsiCatalogRestServiceServer
249 .expect(requestTo(ETSI_CATALOG_URL + "/vnfpkgm/v1/vnf_packages/" + entry.getValue()))
250 .andExpect(method(HttpMethod.GET)).andRespond(withSuccess(
251 gson.toJson(getVnfPkgInfo(entry.getKey(), entry.getValue())), MediaType.APPLICATION_JSON));
256 private VnfPkgInfo getVnfPkgInfo(final String vnfdId, final String vnfPkgId) {
257 return new VnfPkgInfo().id(vnfPkgId).vnfdId(vnfdId);
260 private InstantiateNsRequest getInstantiateNsRequest() {
261 final Map<String, Object> additionalParams = new HashMap<>();
262 additionalParams.put("vim_id", CLOUD_OWNER + "_" + CLOUD_REGION + "_" + TENANT_ID);
264 final InstantiateNsRequest instantiateNsRequest = new InstantiateNsRequest().nsFlavourId("default");
266 for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
268 .addAdditionalParamsForVnfItem(new NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf()
269 .vnfProfileId(entry.getValue()).additionalParams(additionalParams));
272 return instantiateNsRequest;
275 private NsdInfo getNSPackageModel(final String nsdId) {
276 return new NsdInfo().id(nsdId).nsdId(nsdId).nsdInvariantId(NSD_INVARIANT_ID).nsdName("vcpe").nsdDesigner("ONAP")
277 .vnfPkgIds(new ArrayList<>(VNFD_ID_TO_VNFPKG_ID_MAPPING.values()));
280 private byte[] getFileContent(final String path) throws IOException {
281 return Files.readAllBytes(Paths.get(path));
285 private String getAbsolutePath(final String path) {
286 return new File(path).getAbsolutePath();
289 private void mockAAIEndpoints(final String nsdId) {
290 final String modelEndpoint = "/aai/v[0-9]+/network/generic-vnfs/generic-vnf/" + UUID_REGEX;
291 wireMockServer.stubFor(
292 get(urlMatching(modelEndpoint + "\\?resultIndex=0&resultSize=1&format=count")).willReturn(notFound()));
294 wireMockServer.stubFor(put(urlMatching(modelEndpoint)).willReturn(ok()));
295 wireMockServer.stubFor(put(urlMatching(modelEndpoint + "/relationship-list/relationship")).willReturn(ok()));
297 wireMockServer.stubFor(get(urlMatching(modelEndpoint)).willReturn(ok())
298 .willReturn(okJson("{\"orchestration-status\": \"Created\"}")));
300 final String resourceType = "service-instance";
301 final String resourceLink = "/aai/v20/business/customers/customer/" + GLOBAL_CUSTOMER_ID
302 + "/service-subscriptions/service-subscription/NetworkService/service-instances/service-instance/"
305 final String body = "{\n" + " \"results\": [{\n" + " \"resource-type\": \"" + resourceType + "\",\n"
306 + " \"resource-link\": \"" + resourceLink + "\"\n" + " }]\n" + "}";
308 wireMockServer.stubFor(
309 get(urlMatching("/aai/v[0-9]+/nodes/service-instances/service-instance/" + nsdId + "\\?format=pathed"))
310 .willReturn(okJson(body)));
313 .stubFor(put(urlMatching("/aai/v[0-9]+/cloud-infrastructure/cloud-regions/cloud-region/" + CLOUD_OWNER
314 + "/" + CLOUD_REGION + "/tenants/tenant/" + TENANT_ID + "/relationship-list/relationship"))