Adding NS instantiation
[so.git] / so-etsi-nfvo / so-etsi-nfvo-ns-lcm / so-etsi-nfvo-ns-lcm-bpmn-flows / src / test / java / org / onap / so / etsi / nfvo / ns / workflow / engine / tasks / InstantiateNsTaskTest.java
1 /*-
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
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
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.
16  *
17  * SPDX-License-Identifier: Apache-2.0
18  * ============LICENSE_END=========================================================
19  */
20 package org.onap.so.etsi.nfvo.ns.workflow.engine.tasks;
21
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;
38 import java.io.File;
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;
46 import java.util.Map;
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;
82
83 /**
84  * @author Andrew Lamb (andrew.a.lamb@est.tech)
85  * @author Waqas Ikram (waqas.ikram@est.tech)
86  *
87  */
88 public class InstantiateNsTaskTest extends BaseTest {
89
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";
104
105     @Autowired
106     private DatabaseServiceProvider databaseServiceProvider;
107
108     @Autowired
109     @Qualifier(ETSI_CATALOG_REST_TEMPLATE_BEAN)
110     private RestTemplate etsiCatalogRestTemplate;
111
112     @Autowired
113     @Qualifier(SOL003_ADAPTER_REST_TEMPLATE_BEAN)
114     private RestTemplate sol003AdapterRestTemplate;
115
116     private MockRestServiceServer mockEtsiCatalogRestServiceServer;
117
118     private MockRestServiceServer mockSol003AdapterRestServiceServer;
119
120     @Autowired
121     private JobExecutorService objUnderTest;
122
123     @Autowired
124     private GsonProvider gsonProvider;
125
126     private Gson gson;
127
128     private static final Map<String, String> VNFD_ID_TO_VNFPKG_ID_MAPPING = new HashMap<>();
129     static {
130         for (final String vnfd : VCPE_VNFDS) {
131             VNFD_ID_TO_VNFPKG_ID_MAPPING.put(vnfd, UUID.randomUUID().toString());
132         }
133     }
134
135     @Before
136     public void before() {
137         wireMockServer.resetAll();
138         gson = gsonProvider.getGson();
139
140         mockEtsiCatalogRestServiceServer =
141                 MockRestServiceServer.bindTo(etsiCatalogRestTemplate).ignoreExpectOrder(true).build();
142         mockSol003AdapterRestServiceServer =
143                 MockRestServiceServer.bindTo(sol003AdapterRestTemplate).ignoreExpectOrder(true).build();
144
145         etsiCatalogRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
146         sol003AdapterRestTemplate.getMessageConverters().add(new GsonHttpMessageConverter(gson));
147
148     }
149
150     @After
151     public void after() {
152         wireMockServer.resetAll();
153         mockEtsiCatalogRestServiceServer.reset();
154     }
155
156     @Test
157     public void testInstantiateNsWorkflow_JustUpdateStatus_SuccessfullCase() throws InterruptedException, IOException {
158         final String nsdId = UUID.randomUUID().toString();
159         final String nsdName = NS_NAME + "-" + System.currentTimeMillis();
160
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());
164
165         databaseServiceProvider.saveNfvoNsInst(newNfvoNsInst);
166
167         mockSol003AdapterEndpoints();
168         mockAAIEndpoints(nsdId);
169         mockEtsiCatalogEndpoints(nsdId);
170
171         final String nsLcmOpOccId =
172                 objUnderTest.runInstantiateNsJob(newNfvoNsInst.getNsInstId(), getInstantiateNsRequest());
173
174         final Optional<NfvoJob> optional = getJobByResourceId(newNfvoNsInst.getNsInstId());
175         assertTrue(optional.isPresent());
176         final NfvoJob nfvoJob = optional.get();
177
178         assertTrue(waitForProcessInstanceToFinish(nfvoJob.getProcessInstanceId()));
179
180         final HistoricProcessInstance historicProcessInstance =
181                 getHistoricProcessInstance(nfvoJob.getProcessInstanceId());
182         assertNotNull(historicProcessInstance);
183
184         assertEquals(HistoricProcessInstance.STATE_COMPLETED, historicProcessInstance.getState());
185
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());
190
191         final HistoricVariableInstance historicVariableInstance =
192                 getVariable(nfvoJob.getProcessInstanceId(), NETWORK_SERVICE_DESCRIPTOR_PARAM_NAME);
193         assertNotNull(historicVariableInstance);
194         final NetworkServiceDescriptor nsd = (NetworkServiceDescriptor) historicVariableInstance.getValue();
195         assertNotNull(nsd);
196
197         assertEquals(VNFD_ID_TO_VNFPKG_ID_MAPPING.size(), nsd.getVnfs().size());
198
199         final List<NfvoNfInst> nfvoNfInsts = databaseServiceProvider.getNfvoNfInstByNsInstId(nsdId);
200         assertNotNull(nsd);
201         assertEquals(VNFD_ID_TO_VNFPKG_ID_MAPPING.size(), nfvoNfInsts.size());
202
203         final Optional<NsLcmOpOcc> optionalNsLcmOpOcc = databaseServiceProvider.getNsLcmOpOcc(nsLcmOpOccId);
204         assertTrue(optionalNsLcmOpOcc.isPresent());
205
206         assertEquals(OperationStateEnum.COMPLETED, optionalNsLcmOpOcc.get().getOperationState());
207
208         final Map<String, NfvoNfInst> nfvoNfInstsMap =
209                 nfvoNfInsts.stream().collect(Collectors.toMap(NfvoNfInst::getVnfdId, nfvoNfInst -> nfvoNfInst));
210
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());
214
215         }
216
217     }
218
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));
226
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));
236     }
237
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));
246
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));
252         }
253
254     }
255
256     private VnfPkgInfo getVnfPkgInfo(final String vnfdId, final String vnfPkgId) {
257         return new VnfPkgInfo().id(vnfPkgId).vnfdId(vnfdId);
258     }
259
260     private InstantiateNsRequest getInstantiateNsRequest() {
261         final Map<String, Object> additionalParams = new HashMap<>();
262         additionalParams.put("vim_id", CLOUD_OWNER + "_" + CLOUD_REGION + "_" + TENANT_ID);
263
264         final InstantiateNsRequest instantiateNsRequest = new InstantiateNsRequest().nsFlavourId("default");
265
266         for (final Entry<String, String> entry : VNFD_ID_TO_VNFPKG_ID_MAPPING.entrySet()) {
267             instantiateNsRequest
268                     .addAdditionalParamsForVnfItem(new NsInstancesnsInstanceIdinstantiateAdditionalParamsForVnf()
269                             .vnfProfileId(entry.getValue()).additionalParams(additionalParams));
270         }
271
272         return instantiateNsRequest;
273     }
274
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()));
278     }
279
280     private byte[] getFileContent(final String path) throws IOException {
281         return Files.readAllBytes(Paths.get(path));
282     }
283
284
285     private String getAbsolutePath(final String path) {
286         return new File(path).getAbsolutePath();
287     }
288
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()));
293
294         wireMockServer.stubFor(put(urlMatching(modelEndpoint)).willReturn(ok()));
295         wireMockServer.stubFor(put(urlMatching(modelEndpoint + "/relationship-list/relationship")).willReturn(ok()));
296
297         wireMockServer.stubFor(get(urlMatching(modelEndpoint)).willReturn(ok())
298                 .willReturn(okJson("{\"orchestration-status\": \"Created\"}")));
299
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/"
303                 + nsdId;
304
305         final String body = "{\n" + "  \"results\": [{\n" + "    \"resource-type\": \"" + resourceType + "\",\n"
306                 + "    \"resource-link\": \"" + resourceLink + "\"\n" + "  }]\n" + "}";
307
308         wireMockServer.stubFor(
309                 get(urlMatching("/aai/v[0-9]+/nodes/service-instances/service-instance/" + nsdId + "\\?format=pathed"))
310                         .willReturn(okJson(body)));
311
312         wireMockServer
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"))
315                                 .willReturn(ok()));
316
317     }
318
319 }