2 * Copyright 2016-2017, Nokia Corporation
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
8 * http://www.apache.org/licenses/LICENSE-2.0
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
17 package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm;
20 import com.google.gson.Gson;
21 import com.google.gson.JsonElement;
22 import com.google.gson.JsonObject;
23 import com.nokia.cbam.catalog.v1.model.CatalogAdapterVnfpackage;
24 import com.nokia.cbam.lcm.v32.ApiException;
25 import com.nokia.cbam.lcm.v32.model.*;
26 import com.nokia.cbam.lcm.v32.model.ScaleDirection;
27 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IGrantManager;
28 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.VimInfoProvider;
29 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.StoreLoader;
30 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.UserVisibleError;
31 import org.onap.vnfmdriver.model.ExtVirtualLinkInfo;
32 import org.onap.vnfmdriver.model.*;
33 import org.onap.vnfmdriver.model.VimInfo;
34 import org.onap.vnfmdriver.model.VnfInfo;
35 import org.slf4j.Logger;
36 import org.springframework.beans.factory.annotation.Autowired;
37 import org.springframework.stereotype.Component;
38 import org.yaml.snakeyaml.Yaml;
40 import javax.servlet.http.HttpServletResponse;
42 import java.util.concurrent.ExecutorService;
43 import java.util.concurrent.Executors;
45 import static com.google.common.base.Splitter.on;
46 import static com.google.common.collect.Iterables.find;
47 import static com.google.common.collect.Lists.newArrayList;
48 import static com.google.common.collect.Sets.newHashSet;
49 import static com.nokia.cbam.lcm.v32.model.InstantiationState.INSTANTIATED;
50 import static com.nokia.cbam.lcm.v32.model.OperationStatus.FINISHED;
51 import static com.nokia.cbam.lcm.v32.model.OperationType.INSTANTIATE;
52 import static com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum.*;
53 import static java.lang.Integer.parseInt;
54 import static java.nio.charset.StandardCharsets.UTF_8;
55 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.*;
56 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.SystemFunctions.systemFunctions;
57 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION;
58 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.notification.LifecycleChangeNotificationManager.NEWEST_OPERATIONS_FIRST;
59 import static org.slf4j.LoggerFactory.getLogger;
60 import static org.springframework.util.StringUtils.isEmpty;
63 * Responsible for executing lifecycle operation on the VNF
66 public class LifecycleManager {
67 public static final String ONAP_CSAR_ID = "onapCsarId";
68 public static final long OPERATION_STATUS_POLLING_INTERVAL_IN_MS = 5000L;
70 * The key of the CBAM VNF extension for the identifier of the VNFM in ONAP
72 public static final String EXTERNAL_VNFM_ID = "externalVnfmId";
73 public static final String SCALE_OPERATION_NAME = "scale";
74 private static Logger logger = getLogger(LifecycleManager.class);
75 private final CatalogManager catalogManager;
76 private final IGrantManager grantManager;
77 private final JobManager jobManager;
78 private final ILifecycleChangeNotificationManager notificationManager;
79 private final CbamRestApiProvider cbamRestApiProvider;
80 private final VimInfoProvider vimInfoProvider;
83 * Runs asynchronous operations in the background
85 private ExecutorService executorService = Executors.newCachedThreadPool();
88 LifecycleManager(CatalogManager catalogManager, IGrantManager grantManager, CbamRestApiProvider restApiProvider, VimInfoProvider vimInfoProvider, JobManager jobManager, ILifecycleChangeNotificationManager notificationManager) {
89 this.vimInfoProvider = vimInfoProvider;
90 this.grantManager = grantManager;
91 this.cbamRestApiProvider = restApiProvider;
92 this.jobManager = jobManager;
93 this.notificationManager = notificationManager;
94 this.catalogManager = catalogManager;
98 * @param vimId the VIM identifier
99 * @return the name of the region
101 public static String getRegionName(String vimId) {
102 return newArrayList(on(SEPARATOR).split(vimId)).get(1);
106 * @param vimId the VIM identifier
107 * @return the owner of the cloud
109 public static String getCloudOwner(String vimId) {
110 return newArrayList(on(SEPARATOR).split(vimId)).get(0);
113 private static OperationExecution findLastInstantiation(List<OperationExecution> operationExecutions) {
114 return find(NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions), op -> INSTANTIATE.equals(op.getOperationType()));
118 * Create the VNF. It consists of the following steps
120 * <li>upload the VNF package to CBAM package (if not already there)</li>
121 * <li>create the VNF on CBAM</li>
122 * <li>modify attributes of the VNF (add onapCsarId field)</li>
124 * The rollback of the failed operation is not implemented
126 * <li>delete the VNF if error occurs before instantiation</li>
127 * <li>terminate & delete VNF if error occurs after instantiation</li>
130 * @param vnfmId the identifier of the VNFM
131 * @param csarId the identifier of the VNF package
132 * @param vnfName the name of the VNF
133 * @param description the description of the VNF
134 * @return the VNF creation result
136 public VnfCreationResult create(String vnfmId, String csarId, String vnfName, String description) {
137 logOperationInput("not yet specified", "creation", csarId);
139 CatalogAdapterVnfpackage cbamPackage = catalogManager.preparePackageInCbam(vnfmId, csarId);
140 CreateVnfRequest vnfCreateRequest = new CreateVnfRequest();
141 vnfCreateRequest.setVnfdId(cbamPackage.getVnfdId());
142 vnfCreateRequest.setName(vnfName);
143 vnfCreateRequest.setDescription(description);
144 com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsPost(vnfCreateRequest, NOKIA_LCM_API_VERSION);
145 addVnfdIdToVnfModifyableAttributeExtensions(vnfmId, vnfInfo.getId(), csarId);
146 return new VnfCreationResult(vnfInfo, cbamPackage.getVnfdId());
147 } catch (Exception e) {
148 throw buildFatalFailure(logger, "Unable to create the VNF", e);
152 private void logOperationInput(String vnfId, String operationName, Object payload) {
153 if (logger.isInfoEnabled()) {
154 logger.info("Starting {} operation on VNF with {} identifier with {} parameter", operationName, vnfId, new Gson().toJson(payload));
159 * Instantiate the VNF
161 * @param vnfmId the identifier of the VNFM
162 * @param request the VNF instantiation request
163 * @param httpResponse the HTTP response that corresponds to the VNF instantiation request
164 * @param additionalParameters additional parameters
165 * @param vnfId thr identifier of the VNF
166 * @param vnfdId the identifier of the VNF package in CBAM
167 * @return the instantiation response
169 public VnfInstantiateResponse instantiate(String vnfmId, VnfInstantiateRequest request, HttpServletResponse httpResponse, AdditionalParameters additionalParameters, String vnfId, String vnfdId) {
170 logOperationInput(vnfId, "instantiation", request);
171 validateVimType(additionalParameters.getVimType());
172 VnfInstantiateResponse response = new VnfInstantiateResponse();
173 response.setVnfInstanceId(vnfId);
174 String vimId = getVimId(request.getAdditionalParam());
175 JobInfo spawnJob = scheduleExecution(vnfId, httpResponse, "instantiate", jobInfo ->
176 instantiateVnf(vnfmId, request, additionalParameters, vnfdId, vnfId, vimId, jobInfo)
178 response.setJobId(spawnJob.getJobId());
183 * Instantiate (VF-C terminology) the VNF. It consists of the following steps
185 * <li>upload the VNF package to CBAM package (if not already there)</li>
186 * <li>create the VNF on CBAM</li>
187 * <li>modify attributes of the VNF (add onapCsarId field)</li>
188 * <li>asynchronously</li>
189 * <li>request grant from VF-C</li>
190 * <li>instantiate VNF on CBAM</li>
191 * <li>return VNF & job id (after create VNF on CBAM)</li>
194 * The rollback of the failed operation is not implemented
196 * <li>delete the VNF if error occurs before instantiation</li>
197 * <li>terminate & delete VNf if error occurs after instantiation</li>
200 * @param vnfmId the identifier of the VNFM
201 * @param request the instantiation request
202 * @param httpResponse the HTTP response
203 * @return the instantiation response
205 public VnfInstantiateResponse createAndInstantiate(String vnfmId, VnfInstantiateRequest request, HttpServletResponse httpResponse) {
206 AdditionalParameters additionalParameters = convertInstantiationAdditionalParams(request.getVnfPackageId(), request.getAdditionalParam());
207 validateVimType(additionalParameters.getVimType());
208 VnfCreationResult creationResult = create(vnfmId, request.getVnfDescriptorId(), request.getVnfInstanceName(), request.getVnfInstanceDescription());
209 return instantiate(vnfmId, request, httpResponse, additionalParameters, creationResult.vnfInfo.getId(), creationResult.vnfdId);
212 private void instantiateVnf(String vnfmId, VnfInstantiateRequest request, AdditionalParameters additionalParameters, String vnfdId, String vnfId, String vimId, JobInfo jobInfo) throws ApiException {
213 String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, vnfdId);
214 GrantVNFResponseVim vim = grantManager.requestGrantForInstantiate(vnfmId, vnfId, vimId, request.getVnfPackageId(), additionalParameters.getInstantiationLevel(), vnfdContent, jobInfo.getJobId());
215 if (vim.getVimId() == null) {
216 throw buildFatalFailure(logger, "VF-C did not send VIM identifier in grant response");
218 VimInfo vimInfo = vimInfoProvider.getVimInfo(vim.getVimId());
219 InstantiateVnfRequest instantiationRequest = new InstantiateVnfRequest();
220 addExternalLinksToRequest(request.getExtVirtualLink(), additionalParameters, instantiationRequest, vimId);
221 instantiationRequest.getVims().add(addVim(additionalParameters, vimId, vim, vimInfo));
222 instantiationRequest.setFlavourId(getFlavorId(vnfdContent));
223 instantiationRequest.setComputeResourceFlavours(additionalParameters.getComputeResourceFlavours());
224 instantiationRequest.setGrantlessMode(true);
225 instantiationRequest.setInstantiationLevelId(additionalParameters.getInstantiationLevel());
226 instantiationRequest.setSoftwareImages(additionalParameters.getSoftwareImages());
227 instantiationRequest.setZones(additionalParameters.getZones());
228 instantiationRequest.setExtManagedVirtualLinks(additionalParameters.getExtManagedVirtualLinks());
229 for (ExtVirtualLinkData extVirtualLinkData : additionalParameters.getExtVirtualLinks()) {
230 instantiationRequest.addExtVirtualLinksItem(extVirtualLinkData);
232 JsonObject root = new Gson().toJsonTree(jobInfo).getAsJsonObject();
233 if (additionalParameters.getAdditionalParams() != null) {
234 for (Map.Entry<String, JsonElement> item : new Gson().toJsonTree(additionalParameters.getAdditionalParams()).getAsJsonObject().entrySet()) {
235 root.add(item.getKey(), item.getValue());
238 logger.warn("No additional parameters were specified for the operation");
240 instantiationRequest.setAdditionalParams(root);
241 OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdInstantiatePost(vnfId, instantiationRequest, NOKIA_LCM_API_VERSION);
242 waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
245 private com.nokia.cbam.lcm.v32.model.VimInfo addVim(AdditionalParameters additionalParameters, String vimId, GrantVNFResponseVim vim, VimInfo vimInfo) {
246 if (additionalParameters.getVimType() == OPENSTACK_V2_INFO) {
247 return buildOpenStackV2INFO(vimId, vim, vimInfo);
249 } else if (additionalParameters.getVimType() == OPENSTACK_V3_INFO) {
250 return buildOpenStackV3INFO(vimId, additionalParameters, vim, vimInfo);
253 //OTHER VIM TYPE is not possible
254 return buildVcloudInfo(vimId, vimInfo);
258 private void validateVimType(com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum vimType) {
259 if (com.nokia.cbam.lcm.v32.model.VimInfo.VimInfoTypeEnum.OTHER_VIM_INFO.equals(vimType)) {
260 throw buildFatalFailure(logger, "Only " + OPENSTACK_V2_INFO + ", " + OPENSTACK_V3_INFO + " and " + VMWARE_VCLOUD_INFO + " is the supported VIM types");
264 private String getVimId(Object additionalParams) {
265 return childElement(new Gson().toJsonTree(additionalParams).getAsJsonObject(), "vimId").getAsString();
268 private AdditionalParameters convertInstantiationAdditionalParams(String csarId, Object additionalParams) {
269 JsonObject vnfParameters = child(child(new Gson().toJsonTree(additionalParams).getAsJsonObject(), "inputs"), "vnfs");
270 if (!vnfParameters.has(csarId)) {
271 throw buildFatalFailure(logger, "The additional parameter section does not contain setting for VNF with " + csarId + " CSAR id");
273 JsonElement additionalParamsForVnf = vnfParameters.get(csarId);
274 return new Gson().fromJson(additionalParamsForVnf, AdditionalParameters.class);
277 private String getFlavorId(String vnfdContent) {
278 JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject();
279 JsonObject capabilities = child(child(child(root, "topology_template"), "substitution_mappings"), "capabilities");
280 JsonObject deploymentFlavorProperties = child(child(capabilities, "deployment_flavour"), "properties");
281 return childElement(deploymentFlavorProperties, "flavour_id").getAsString();
284 private Set<String> getAcceptableOperationParameters(String vnfdContent, String categroryOfOperation, String operationName) {
285 JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject();
286 JsonObject interfaces = child(child(child(root, "topology_template"), "substitution_mappings"), "interfaces");
287 JsonObject additionalParameters = child(child(child(child(interfaces, categroryOfOperation), operationName), "inputs"), "additional_parameters");
288 return additionalParameters.keySet();
291 private void addExternalLinksToRequest(List<ExtVirtualLinkInfo> extVirtualLinks, AdditionalParameters additionalParameters, InstantiateVnfRequest instantiationRequest, String vimId) {
292 for (ExtVirtualLinkInfo extVirtualLink : extVirtualLinks) {
293 ExtVirtualLinkData cbamExternalVirtualLink = new ExtVirtualLinkData();
294 cbamExternalVirtualLink.setVimId(vimId);
295 cbamExternalVirtualLink.setResourceId(extVirtualLink.getResourceId());
296 VnfExtCpData ecp = new VnfExtCpData();
297 cbamExternalVirtualLink.setExtVirtualLinkId(extVirtualLink.getVlInstanceId());
298 cbamExternalVirtualLink.getExtCps().add(ecp);
299 ecp.setCpdId(extVirtualLink.getCpdId());
300 List<NetworkAddress> addresses = additionalParameters.getExternalConnectionPointAddresses().get(extVirtualLink.getCpdId());
301 ecp.setAddresses(addresses);
302 instantiationRequest.addExtVirtualLinksItem(cbamExternalVirtualLink);
306 private void addVnfdIdToVnfModifyableAttributeExtensions(String vnfmId, String vnfId, String onapCsarId) {
307 ModifyVnfInfoRequest request = new ModifyVnfInfoRequest();
308 VnfProperty onapCsarIdProperty = new VnfProperty();
309 onapCsarIdProperty.setName(ONAP_CSAR_ID);
310 onapCsarIdProperty.setValue(onapCsarId);
311 request.setExtensions(new ArrayList<>());
312 request.getExtensions().add(onapCsarIdProperty);
313 VnfProperty externalVnfmIdProperty = new VnfProperty();
314 externalVnfmIdProperty.setName(EXTERNAL_VNFM_ID);
315 externalVnfmIdProperty.setValue(vnfmId);
316 request.getExtensions().add(externalVnfmIdProperty);
317 request.setVnfConfigurableProperties(null);
319 OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdPatch(vnfId, request, NOKIA_LCM_API_VERSION);
320 waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
321 } catch (ApiException e) {
322 throw buildFatalFailure(logger, "Unable to set the " + ONAP_CSAR_ID + " property on the VNF", e);
326 private OPENSTACKV3INFO buildOpenStackV3INFO(String vimId, AdditionalParameters additionalParameters, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) {
327 OPENSTACKV3INFO openstackv3INFO = new OPENSTACKV3INFO();
328 openstackv3INFO.setVimInfoType(OPENSTACK_V3_INFO);
329 OpenStackAccessInfoV3 accessInfov3 = new OpenStackAccessInfoV3();
330 openstackv3INFO.accessInfo(accessInfov3);
331 accessInfov3.setPassword(vimInfo.getPassword());
332 accessInfov3.setDomain(additionalParameters.getDomain());
333 accessInfov3.setProject(vim.getAccessInfo().getTenant());
334 accessInfov3.setRegion(getRegionName(vimId));
335 accessInfov3.setUsername(vimInfo.getUserName());
336 EndpointInfo interfaceInfoV3 = new EndpointInfo();
337 interfaceInfoV3.setEndpoint(vimInfo.getUrl());
338 if (!isEmpty(vimInfo.getSslInsecure())) {
339 interfaceInfoV3.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure()));
340 interfaceInfoV3.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure()));
342 interfaceInfoV3.setSkipCertificateHostnameCheck(true);
343 interfaceInfoV3.setSkipCertificateVerification(true);
345 if (!interfaceInfoV3.isSkipCertificateVerification()) {
346 interfaceInfoV3.setTrustedCertificates(new ArrayList<>());
347 for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) {
348 interfaceInfoV3.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8));
351 openstackv3INFO.setInterfaceInfo(interfaceInfoV3);
352 openstackv3INFO.setId(vimId);
353 return openstackv3INFO;
356 private OPENSTACKV2INFO buildOpenStackV2INFO(String vimId, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) {
357 OPENSTACKV2INFO openstackv2INFO = new OPENSTACKV2INFO();
358 openstackv2INFO.setVimInfoType(OPENSTACK_V2_INFO);
359 OpenStackAccessInfoV2 accessInfo = new OpenStackAccessInfoV2();
360 openstackv2INFO.setAccessInfo(accessInfo);
361 accessInfo.setPassword(vimInfo.getPassword());
362 accessInfo.setTenant(vim.getAccessInfo().getTenant());
363 accessInfo.setUsername(vimInfo.getUserName());
364 accessInfo.setRegion(getRegionName(vimId));
365 EndpointInfo interfaceEndpoint = new EndpointInfo();
366 if (!isEmpty(vimInfo.getSslInsecure())) {
367 interfaceEndpoint.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure()));
368 interfaceEndpoint.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure()));
370 interfaceEndpoint.setSkipCertificateHostnameCheck(true);
371 interfaceEndpoint.setSkipCertificateVerification(true);
373 interfaceEndpoint.setEndpoint(vimInfo.getUrl());
374 if (!interfaceEndpoint.isSkipCertificateVerification()) {
375 interfaceEndpoint.setTrustedCertificates(new ArrayList<>());
376 for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) {
377 interfaceEndpoint.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8));
380 openstackv2INFO.setInterfaceInfo(interfaceEndpoint);
381 openstackv2INFO.setId(vimId);
382 return openstackv2INFO;
385 private VMWAREVCLOUDINFO buildVcloudInfo(String vimId, org.onap.vnfmdriver.model.VimInfo vimInfo) {
386 VMWAREVCLOUDINFO vcloudInfo = new VMWAREVCLOUDINFO();
387 vcloudInfo.setVimInfoType(VMWARE_VCLOUD_INFO);
388 VCloudAccessInfo accessInfo = new VCloudAccessInfo();
389 vcloudInfo.setAccessInfo(accessInfo);
390 accessInfo.setPassword(vimInfo.getPassword());
391 accessInfo.setUsername(vimInfo.getUserName());
392 accessInfo.setOrganization(getRegionName(vimId));
393 EndpointInfo interfaceEndpoint = new EndpointInfo();
394 if (!isEmpty(vimInfo.getSslInsecure())) {
395 interfaceEndpoint.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure()));
396 interfaceEndpoint.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure()));
398 interfaceEndpoint.setSkipCertificateHostnameCheck(true);
399 interfaceEndpoint.setSkipCertificateVerification(true);
401 interfaceEndpoint.setEndpoint(vimInfo.getUrl());
402 if (!interfaceEndpoint.isSkipCertificateVerification()) {
403 interfaceEndpoint.setTrustedCertificates(new ArrayList<>());
404 for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) {
405 interfaceEndpoint.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8));
408 vcloudInfo.setInterfaceInfo(interfaceEndpoint);
409 vcloudInfo.setId(vimId);
414 * Terminates and deletes the VNF
416 * <li>fails if the VNF does not exist</li>
417 * <li>terminates if instantiated</li>
418 * <li>deletes the VNF</li>
421 * @param vnfmId the identifier of the VNFM
422 * @param vnfId the identifier of the VNF
423 * @param request the termination request
424 * @param httpResponse the HTTP response
425 * @return the job for polling the progress of the termination
427 public JobInfo terminateVnf(String vnfmId, String vnfId, VnfTerminateRequest request, HttpServletResponse httpResponse) {
428 logOperationInput(vnfId, "termination", request);
429 return scheduleExecution(vnfId, httpResponse, "terminate", jobInfo -> {
430 TerminateVnfRequest cbamRequest = new TerminateVnfRequest();
431 cbamRequest.setAdditionalParams(jobInfo);
432 if (request.getTerminationType() == null) {
433 cbamRequest.setTerminationType(TerminationType.FORCEFUL);
435 if (request.getTerminationType().equals(VnfTerminationType.GRACEFUL)) {
436 cbamRequest.setTerminationType(TerminationType.GRACEFUL);
437 cbamRequest.setGracefulTerminationTimeout(parseInt(request.getGracefulTerminationTimeout()));
439 cbamRequest.setTerminationType(TerminationType.FORCEFUL);
442 com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
443 if (vnf.getInstantiationState() == INSTANTIATED) {
444 terminateVnf(vnfmId, vnfId, jobInfo, cbamRequest, vnf);
446 cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION);
451 private void terminateVnf(String vnfmId, String vnfId, JobInfo jobInfo, TerminateVnfRequest cbamRequest, com.nokia.cbam.lcm.v32.model.VnfInfo vnf) throws ApiException {
452 String vimId = getVimIdFromInstantiationRequest(vnfmId, vnf);
453 grantManager.requestGrantForTerminate(vnfmId, vnfId, vimId, getVnfdIdFromModifyableAttributes(vnf), vnf, jobInfo.getJobId());
454 OperationExecution terminationOperation = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdTerminatePost(vnfId, cbamRequest, NOKIA_LCM_API_VERSION);
455 OperationExecution finishedOperation = waitForOperationToFinish(vnfmId, vnfId, terminationOperation.getId());
456 if (finishedOperation.getStatus() == FINISHED) {
457 notificationManager.waitForTerminationToBeProcessed(finishedOperation.getId());
458 logger.info("Deleting VNF with {}", vnfId);
459 cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION);
460 logger.info("VNF with {} has been deleted", vnfId);
463 logger.error("Unable to terminate VNF the operation did not finish with success");
467 private String getVimIdFromInstantiationRequest(String vnfmId, com.nokia.cbam.lcm.v32.model.VnfInfo vnf) throws ApiException {
468 OperationExecution lastInstantiation = findLastInstantiation(vnf.getOperationExecutions());
469 Object operationParameters = cbamRestApiProvider.getCbamOperationExecutionApi(vnfmId).operationExecutionsOperationExecutionIdOperationParamsGet(lastInstantiation.getId(), NOKIA_LCM_API_VERSION);
470 JsonObject root = new Gson().toJsonTree(operationParameters).getAsJsonObject();
471 return childElement(childElement(root, "vims").getAsJsonArray().get(0).getAsJsonObject(), "id").getAsString();
474 private String getVnfdIdFromModifyableAttributes(com.nokia.cbam.lcm.v32.model.VnfInfo vnf) {
475 return find(vnf.getExtensions(), p -> p.getName().equals(ONAP_CSAR_ID)).getValue().toString();
479 * @param vnfmId the identifier of the VNFM
480 * @param vnfId the identifier of the VNF
481 * @return the current state of the VNF
483 public VnfInfo queryVnf(String vnfmId, String vnfId) {
485 com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
486 VnfInfo vnfInfo = new VnfInfo();
487 vnfInfo.setVersion(cbamVnfInfo.getVnfSoftwareVersion());
488 vnfInfo.setVnfInstanceId(vnfId);
489 String onapCsarId = getVnfdIdFromModifyableAttributes(cbamVnfInfo);
490 vnfInfo.setVnfdId(onapCsarId);
491 vnfInfo.setVnfPackageId(onapCsarId);
492 vnfInfo.setVnfInstanceDescription(cbamVnfInfo.getDescription());
493 vnfInfo.setVnfInstanceName(cbamVnfInfo.getName());
494 vnfInfo.setVnfProvider(cbamVnfInfo.getVnfProvider());
495 vnfInfo.setVnfStatus("ACTIVE");
496 vnfInfo.setVnfType("Kuku");
498 } catch (ApiException e) {
499 throw buildFatalFailure(logger, "Unable to query VNF (" + vnfId + ")", e);
503 private ScaleDirection convert(org.onap.vnfmdriver.model.ScaleDirection direction) {
504 if (org.onap.vnfmdriver.model.ScaleDirection.IN.equals(direction)) {
505 return ScaleDirection.IN;
507 return ScaleDirection.OUT;
514 * @param vnfmId the identifier of the VNFM
515 * @param vnfId the identifier of the VNF
516 * @param request the scale request
517 * @param httpResponse the HTTP response
518 * @return the job for tracking the scale
520 public JobInfo scaleVnf(String vnfmId, String vnfId, VnfScaleRequest request, HttpServletResponse httpResponse) {
521 logOperationInput(vnfId, SCALE_OPERATION_NAME, request);
522 return scheduleExecution(vnfId, httpResponse, SCALE_OPERATION_NAME, jobInfo -> {
523 ScaleVnfRequest cbamRequest = new ScaleVnfRequest();
524 cbamRequest.setAspectId(request.getAspectId());
525 cbamRequest.setNumberOfSteps(Integer.valueOf(request.getNumberOfSteps()));
526 cbamRequest.setType(convert(request.getType()));
527 com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
528 JsonObject root = new Gson().toJsonTree(jobInfo).getAsJsonObject();
529 com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
530 String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, cbamVnfInfo.getVnfdId());
531 Set<String> acceptableOperationParameters = getAcceptableOperationParameters(vnfdContent, "Basic", SCALE_OPERATION_NAME);
532 buildAdditionalParameters(request, root, acceptableOperationParameters);
533 cbamRequest.setAdditionalParams(root);
534 grantManager.requestGrantForScale(vnfmId, vnfId, getVimIdFromInstantiationRequest(vnfmId, vnf), getVnfdIdFromModifyableAttributes(vnf), request, jobInfo.getJobId());
535 OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdScalePost(vnfId, cbamRequest, NOKIA_LCM_API_VERSION);
536 waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
540 private void buildAdditionalParameters(VnfScaleRequest request, JsonObject root, Set<String> acceptableOperationParameters) {
541 if (request.getAdditionalParam() != null) {
542 for (Map.Entry<String, JsonElement> item : new Gson().toJsonTree(request.getAdditionalParam()).getAsJsonObject().entrySet()) {
543 if (acceptableOperationParameters.contains(item.getKey())) {
544 root.add(item.getKey(), item.getValue());
548 logger.warn("No additional parameters were passed for scaling");
555 * @param vnfmId the identifier of the VNFM
556 * @param vnfId the identifier of the VNF
557 * @param request the heal request
558 * @param httpResponse the HTTP response
559 * @param vnfcId the identifer of thr VNFC to be healed
560 * @return the job for tracking the heal
562 public JobInfo healVnf(String vnfmId, String vnfId, VnfHealRequest request, Optional<String> vnfcId, HttpServletResponse httpResponse) {
563 logOperationInput(vnfId, "heal", request);
564 return scheduleExecution(vnfId, httpResponse, "heal", job -> {
565 HealVnfRequest cbamHealRequest = new HealVnfRequest();
566 Map<String, String> additionalParams = new HashMap<>();
567 additionalParams.put("vmName", request.getAffectedvm().getVmname());
568 additionalParams.put("action", request.getAction());
569 additionalParams.put("jobId", job.getJobId());
570 additionalParams.put("vnfcId", vnfcId.orElse("unknown"));
571 cbamHealRequest.setAdditionalParams(additionalParams);
572 com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
573 String vimId = getVimIdFromInstantiationRequest(vnfmId, vnf);
574 grantManager.requestGrantForHeal(vnfmId, vnfId, vimId, getVnfdIdFromModifyableAttributes(vnf), request, job.getJobId());
575 OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdHealPost(vnfId, cbamHealRequest, NOKIA_LCM_API_VERSION);
576 waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
580 private JobInfo scheduleExecution(String vnfId, HttpServletResponse httpResponse, String operation, AsynchronousExecution asynchronExecution) {
581 JobInfo jobInfo = new JobInfo();
582 jobInfo.setJobId(jobManager.spawnJob(vnfId, httpResponse));
583 executorService.submit(() -> {
585 asynchronExecution.execute(jobInfo);
586 } catch (RuntimeException e) {
587 logger.error("Unable to " + operation + " VNF with " + vnfId + " identifier", e);
588 jobManager.jobFinished(jobInfo.getJobId());
590 } catch (Exception e) {
591 String msg = "Unable to " + operation + " VNF with " + vnfId + " identifier";
592 logger.error(msg, e);
593 //the job can only be signaled to be finished after the error is logged
594 jobManager.jobFinished(jobInfo.getJobId());
595 throw new UserVisibleError(msg, e);
597 jobManager.jobFinished(jobInfo.getJobId());
602 private OperationExecution waitForOperationToFinish(String vnfmId, String vnfId, String operationExecutionId) {
605 OperationExecution operationExecution = find(cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdOperationExecutionsGet(vnfId, NOKIA_LCM_API_VERSION), opEx -> operationExecutionId.equals(opEx.getId()));
606 if (hasOperationFinished(operationExecution)) {
607 logger.debug("Operation finished with " + operationExecution.getId());
608 return operationExecution;
610 } catch (Exception e) {
611 //swallow exception and retry
612 logger.warn("Unable to retrieve operations details", e);
614 systemFunctions().sleep(OPERATION_STATUS_POLLING_INTERVAL_IN_MS);
618 private boolean hasOperationFinished(OperationExecution operationExecution) {
619 return newHashSet(FINISHED, OperationStatus.FAILED).contains(operationExecution.getStatus());
623 private interface AsynchronousExecution {
624 void execute(JobInfo job) throws ApiException;
627 public static class VnfCreationResult {
628 private final com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo;
629 private final String vnfdId;
630 VnfCreationResult(com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo, String vnfdId) {
631 this.vnfInfo = vnfInfo;
632 this.vnfdId = vnfdId;
635 public com.nokia.cbam.lcm.v32.model.VnfInfo getVnfInfo() {