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.ILifecycleChangeNotificationManager.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 private static Logger logger = getLogger(LifecycleManager.class);
74 private final CatalogManager catalogManager;
75 private final IGrantManager grantManager;
76 private final JobManager jobManager;
77 private final ILifecycleChangeNotificationManager notificationManager;
78 private final CbamRestApiProvider cbamRestApiProvider;
79 private final VimInfoProvider vimInfoProvider;
82 * Runs asynchronous operations in the background
84 private ExecutorService executorService = Executors.newCachedThreadPool();
87 LifecycleManager(CatalogManager catalogManager, IGrantManager grantManager, CbamRestApiProvider restApiProvider, VimInfoProvider vimInfoProvider, JobManager jobManager, ILifecycleChangeNotificationManager notificationManager) {
88 this.vimInfoProvider = vimInfoProvider;
89 this.grantManager = grantManager;
90 this.cbamRestApiProvider = restApiProvider;
91 this.jobManager = jobManager;
92 this.notificationManager = notificationManager;
93 this.catalogManager = catalogManager;
96 public static String getRegionName(String vimId) {
97 return newArrayList(on(SEPARATOR).split(vimId)).get(1);
100 public static String getCloudOwner(String vimId) {
101 return newArrayList(on(SEPARATOR).split(vimId)).get(0);
104 private static OperationExecution findLastInstantiation(List<OperationExecution> operationExecutions) {
105 return find(NEWEST_OPERATIONS_FIRST.sortedCopy(operationExecutions), op -> INSTANTIATE.equals(op.getOperationType()));
109 * Instantiate (VF-C terminology) the VNF. It consists of the following steps
111 * <li>upload the VNF package to CBAM package (if not already there)</li>
112 * <li>create the VNF on CBAM</li>
113 * <li>modify attributes of the VNF (add onapCsarId field)</li>
114 * <li>asynchronously</li>
115 * <li>request grant from VF-C</li>
116 * <li>instantiate VNF on CBAM</li>
117 * <li>return VNF & job id (after create VNF on CBAM)</li>
120 * The rollback of the failed operation is not implemented
122 * <li>delete the VNF if error occurs before instantiation</li>
123 * <li>terminate & delete VNf if error occurs after instantiation</li>
126 * @param vnfmId the identifier of the VNFM
127 * @param request the instantiation request
128 * @param httpResponse the HTTP response
129 * @return the instantiation response
131 public VnfInstantiateResponse instantiate(String vnfmId, VnfInstantiateRequest request, HttpServletResponse httpResponse) {
132 if (logger.isDebugEnabled()) {
133 logger.debug("Additional parameters for instantiation: {}", new Gson().toJson(request.getAdditionalParam()));
135 AdditionalParams additionalParams = convertInstantiationAdditionalParams(request.getVnfPackageId(), request.getAdditionalParam());
136 validateVimType(additionalParams);
137 CatalogAdapterVnfpackage cbamPackage = catalogManager.preparePackageInCbam(vnfmId, request.getVnfPackageId());
139 CreateVnfRequest vnfCreateRequest = new CreateVnfRequest();
140 vnfCreateRequest.setVnfdId(cbamPackage.getId());
141 vnfCreateRequest.setName(request.getVnfInstanceName());
142 vnfCreateRequest.setDescription(request.getVnfInstanceDescription());
143 com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsPost(vnfCreateRequest, NOKIA_LCM_API_VERSION);
144 VnfInstantiateResponse response = new VnfInstantiateResponse();
145 response.setVnfInstanceId(vnfInfo.getId());
146 String vimId = getVimId(request.getAdditionalParam());
147 addVnfdIdToVnfModifyableAttributeExtensions(vnfmId, vnfInfo.getId(), request.getVnfPackageId());
148 JobInfo spawnJob = scheduleExecution(vnfInfo.getId(), httpResponse, "instantiate", jobInfo ->
149 instantiateVnf(vnfmId, request, additionalParams, cbamPackage, vnfInfo, vimId, jobInfo)
151 response.setJobId(spawnJob.getJobId());
153 } catch (Exception e) {
154 throw fatalFailure(logger, "Unable to create the VNF", e);
158 private void instantiateVnf(String vnfmId, VnfInstantiateRequest request, AdditionalParams additionalParams, CatalogAdapterVnfpackage cbamPackage, com.nokia.cbam.lcm.v32.model.VnfInfo vnfInfo, String vimId, JobInfo jobInfo) throws ApiException {
159 String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, cbamPackage.getId());
160 GrantVNFResponseVim vim = grantManager.requestGrantForInstantiate(vnfmId, vnfInfo.getId(), vimId, request.getVnfPackageId(), additionalParams.getInstantiationLevel(), vnfdContent, jobInfo.getJobId());
161 if (vim.getVimId() == null) {
162 fatalFailure(logger, "VF-C did not send VIM identifier in grant response");
164 VimInfo vimInfo = vimInfoProvider.getVimInfo(vim.getVimId());
165 InstantiateVnfRequest instantiationRequest = new InstantiateVnfRequest();
166 addExernalLinksToRequest(request.getExtVirtualLink(), additionalParams, instantiationRequest, vimId);
167 if (additionalParams.getVimType() == OPENSTACK_V2_INFO) {
168 instantiationRequest.getVims().add(buildOpenStackV2INFO(vimId, vim, vimInfo));
170 } else if (additionalParams.getVimType() == OPENSTACK_V3_INFO) {
171 instantiationRequest.getVims().add(buildOpenStackV3INFO(vimId, additionalParams, vim, vimInfo));
173 } else if (additionalParams.getVimType() == VMWARE_VCLOUD_INFO) {
174 instantiationRequest.getVims().add(buildVcloudInfo(vimId, vimInfo));
177 instantiationRequest.setFlavourId(getFlavorId(vnfdContent));
178 instantiationRequest.setComputeResourceFlavours(additionalParams.getComputeResourceFlavours());
179 instantiationRequest.setGrantlessMode(true);
180 instantiationRequest.setInstantiationLevelId(additionalParams.getInstantiationLevel());
181 instantiationRequest.setSoftwareImages(additionalParams.getSoftwareImages());
182 instantiationRequest.setZones(additionalParams.getZones());
183 instantiationRequest.setExtManagedVirtualLinks(additionalParams.getExtManagedVirtualLinks());
184 for (ExtVirtualLinkData extVirtualLinkData : additionalParams.getExtVirtualLinks()) {
185 instantiationRequest.addExtVirtualLinksItem(extVirtualLinkData);
187 JsonObject root = new Gson().toJsonTree(jobInfo).getAsJsonObject();
188 if (additionalParams.getAdditionalParams() != null && !isEmpty(additionalParams.getAdditionalParams().toString())) {
189 for (Map.Entry<String, JsonElement> item : new Gson().toJsonTree(additionalParams.getAdditionalParams()).getAsJsonObject().entrySet()) {
190 root.add(item.getKey(), item.getValue());
193 instantiationRequest.setAdditionalParams(root);
194 OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdInstantiatePost(vnfInfo.getId(), instantiationRequest, NOKIA_LCM_API_VERSION);
195 waitForOperationToFinish(vnfmId, vnfInfo.getId(), operationExecution.getId());
198 private void validateVimType(AdditionalParams additionalParams) {
199 switch (additionalParams.getVimType()) {
200 case OPENSTACK_V2_INFO:
201 case OPENSTACK_V3_INFO:
202 case VMWARE_VCLOUD_INFO:
205 throw fatalFailure(logger, "Only " + OPENSTACK_V2_INFO + ", " + OPENSTACK_V3_INFO + " and " + VMWARE_VCLOUD_INFO + " is the supported VIM types");
209 private String getVimId(Object additionalParams) {
210 return childElement(new Gson().toJsonTree(additionalParams).getAsJsonObject(), "vimId").getAsString();
213 private AdditionalParams convertInstantiationAdditionalParams(String csarId, Object additionalParams) {
214 JsonObject vnfParameters = child(child(new Gson().toJsonTree(additionalParams).getAsJsonObject(), "inputs"), "vnfs");
215 if (!vnfParameters.has(csarId)) {
216 throw fatalFailure(logger, "The additional parameter section does not contain setting for VNF with " + csarId + " CSAR id");
218 JsonElement additionalParamsForVnf = vnfParameters.get(csarId);
219 return new Gson().fromJson(additionalParamsForVnf, AdditionalParams.class);
222 private String getFlavorId(String vnfdContent) {
223 JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject();
224 JsonObject capabilities = child(child(child(root, "topology_template"), "substitution_mappings"), "capabilities");
225 JsonObject deploymentFlavorProperties = child(child(capabilities, "deployment_flavour"), "properties");
226 return childElement(deploymentFlavorProperties, "flavour_id").getAsString();
229 private Set<String> getAcceptableOperationParameters(String vnfdContent, String categroryOfOperation, String operationName) {
230 JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject();
231 JsonObject interfaces = child(child(child(root, "topology_template"), "substitution_mappings"), "interfaces");
232 JsonObject additionalParameters = child(child(child(child(interfaces, categroryOfOperation), operationName), "inputs"), "additional_parameters");
233 return additionalParameters.keySet();
236 private void addExernalLinksToRequest(List<ExtVirtualLinkInfo> extVirtualLinks, AdditionalParams additionalParams, InstantiateVnfRequest instantiationRequest, String vimId) {
237 for (ExtVirtualLinkInfo extVirtualLink : extVirtualLinks) {
238 ExtVirtualLinkData cbamExternalVirtualLink = new ExtVirtualLinkData();
239 cbamExternalVirtualLink.setVimId(vimId);
240 cbamExternalVirtualLink.setResourceId(extVirtualLink.getResourceId());
241 VnfExtCpData ecp = new VnfExtCpData();
242 cbamExternalVirtualLink.setExtVirtualLinkId(extVirtualLink.getVlInstanceId());
243 cbamExternalVirtualLink.getExtCps().add(ecp);
244 ecp.setCpdId(extVirtualLink.getCpdId());
245 List<NetworkAddress> addresses = additionalParams.getExternalConnectionPointAddresses().get(extVirtualLink.getCpdId());
246 ecp.setAddresses(addresses);
247 instantiationRequest.addExtVirtualLinksItem(cbamExternalVirtualLink);
251 private void addVnfdIdToVnfModifyableAttributeExtensions(String vnfmId, String vnfId, String onapCsarId) {
252 ModifyVnfInfoRequest request = new ModifyVnfInfoRequest();
253 VnfProperty onapCsarIdProperty = new VnfProperty();
254 onapCsarIdProperty.setName(ONAP_CSAR_ID);
255 onapCsarIdProperty.setValue(onapCsarId);
256 request.setExtensions(new ArrayList<>());
257 request.getExtensions().add(onapCsarIdProperty);
258 VnfProperty externalVnfmIdProperty = new VnfProperty();
259 externalVnfmIdProperty.setName(EXTERNAL_VNFM_ID);
260 externalVnfmIdProperty.setValue(vnfmId);
261 request.getExtensions().add(externalVnfmIdProperty);
262 request.setVnfConfigurableProperties(null);
264 OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdPatch(vnfId, request, NOKIA_LCM_API_VERSION);
265 waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
266 } catch (ApiException e) {
267 fatalFailure(logger, "Unable to set the " + ONAP_CSAR_ID + " property on the VNF", e);
271 private OPENSTACKV3INFO buildOpenStackV3INFO(String vimId, AdditionalParams additionalParams, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) {
272 OPENSTACKV3INFO openstackv3INFO = new OPENSTACKV3INFO();
273 openstackv3INFO.setVimInfoType(OPENSTACK_V3_INFO);
274 OpenStackAccessInfoV3 accessInfov3 = new OpenStackAccessInfoV3();
275 openstackv3INFO.accessInfo(accessInfov3);
276 accessInfov3.setPassword(vimInfo.getPassword());
277 accessInfov3.setDomain(additionalParams.getDomain());
278 accessInfov3.setProject(vim.getAccessInfo().getTenant());
279 accessInfov3.setRegion(getRegionName(vimId));
280 accessInfov3.setUsername(vimInfo.getUserName());
281 EndpointInfo interfaceInfoV3 = new EndpointInfo();
282 interfaceInfoV3.setEndpoint(vimInfo.getUrl());
283 if (!isEmpty(vimInfo.getSslInsecure())) {
284 interfaceInfoV3.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure()));
285 interfaceInfoV3.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure()));
287 interfaceInfoV3.setSkipCertificateHostnameCheck(true);
288 interfaceInfoV3.setSkipCertificateVerification(true);
290 if (!interfaceInfoV3.isSkipCertificateVerification()) {
291 interfaceInfoV3.setTrustedCertificates(new ArrayList<>());
292 for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) {
293 interfaceInfoV3.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8));
296 openstackv3INFO.setInterfaceInfo(interfaceInfoV3);
297 openstackv3INFO.setId(vimId);
298 return openstackv3INFO;
301 private OPENSTACKV2INFO buildOpenStackV2INFO(String vimId, GrantVNFResponseVim vim, org.onap.vnfmdriver.model.VimInfo vimInfo) {
302 OPENSTACKV2INFO openstackv2INFO = new OPENSTACKV2INFO();
303 openstackv2INFO.setVimInfoType(OPENSTACK_V2_INFO);
304 OpenStackAccessInfoV2 accessInfo = new OpenStackAccessInfoV2();
305 openstackv2INFO.setAccessInfo(accessInfo);
306 accessInfo.setPassword(vimInfo.getPassword());
307 accessInfo.setTenant(vim.getAccessInfo().getTenant());
308 accessInfo.setUsername(vimInfo.getUserName());
309 accessInfo.setRegion(getRegionName(vimId));
310 EndpointInfo interfaceEndpoint = new EndpointInfo();
311 if (!isEmpty(vimInfo.getSslInsecure())) {
312 interfaceEndpoint.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure()));
313 interfaceEndpoint.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure()));
315 interfaceEndpoint.setSkipCertificateHostnameCheck(true);
316 interfaceEndpoint.setSkipCertificateVerification(true);
318 interfaceEndpoint.setEndpoint(vimInfo.getUrl());
319 if (!interfaceEndpoint.isSkipCertificateVerification()) {
320 interfaceEndpoint.setTrustedCertificates(new ArrayList<>());
321 for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) {
322 interfaceEndpoint.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8));
325 openstackv2INFO.setInterfaceInfo(interfaceEndpoint);
326 openstackv2INFO.setId(vimId);
327 return openstackv2INFO;
330 private VMWAREVCLOUDINFO buildVcloudInfo(String vimId, org.onap.vnfmdriver.model.VimInfo vimInfo) {
331 VMWAREVCLOUDINFO vcloudInfo = new VMWAREVCLOUDINFO();
332 vcloudInfo.setVimInfoType(VMWARE_VCLOUD_INFO);
333 VCloudAccessInfo accessInfo = new VCloudAccessInfo();
334 vcloudInfo.setAccessInfo(accessInfo);
335 accessInfo.setPassword(vimInfo.getPassword());
336 accessInfo.setUsername(vimInfo.getUserName());
337 accessInfo.setOrganization(getRegionName(vimId));
338 EndpointInfo interfaceEndpoint = new EndpointInfo();
339 if (!isEmpty(vimInfo.getSslInsecure())) {
340 interfaceEndpoint.setSkipCertificateHostnameCheck(Boolean.parseBoolean(vimInfo.getSslInsecure()));
341 interfaceEndpoint.setSkipCertificateVerification(Boolean.parseBoolean(vimInfo.getSslInsecure()));
343 interfaceEndpoint.setSkipCertificateHostnameCheck(true);
344 interfaceEndpoint.setSkipCertificateVerification(true);
346 interfaceEndpoint.setEndpoint(vimInfo.getUrl());
347 if (!interfaceEndpoint.isSkipCertificateVerification()) {
348 interfaceEndpoint.setTrustedCertificates(new ArrayList<>());
349 for (String trustedCertificate : StoreLoader.getCertifacates(vimInfo.getSslCacert())) {
350 interfaceEndpoint.getTrustedCertificates().add(trustedCertificate.getBytes(UTF_8));
353 vcloudInfo.setInterfaceInfo(interfaceEndpoint);
354 vcloudInfo.setId(vimId);
359 * Terminates and deletes the VNF
361 * <li>fails if the VNF does not exist</li>
362 * <li>terminates if instantiated</li>
363 * <li>deletes the VNF</li>
366 * @param vnfmId the identifier of the VNFM
367 * @param vnfId the identifier of the VNF
368 * @param request the termination request
369 * @param httpResponse the HTTP response
370 * @return the job for polling the progress of the termination
372 public JobInfo terminateVnf(String vnfmId, String vnfId, VnfTerminateRequest request, HttpServletResponse httpResponse) {
373 return scheduleExecution(vnfId, httpResponse, "terminate", jobInfo -> {
374 TerminateVnfRequest cbamRequest = new TerminateVnfRequest();
375 cbamRequest.setAdditionalParams(jobInfo);
376 if (request.getTerminationType() == null) {
377 cbamRequest.setTerminationType(TerminationType.FORCEFUL);
379 if (request.getTerminationType().equals(VnfTerminationType.GRACEFUL)) {
380 cbamRequest.setTerminationType(TerminationType.GRACEFUL);
381 cbamRequest.setGracefulTerminationTimeout(parseInt(request.getGracefulTerminationTimeout()));
383 cbamRequest.setTerminationType(TerminationType.FORCEFUL);
386 com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
387 if (vnf.getInstantiationState() == INSTANTIATED) {
388 terminateVnf(vnfmId, vnfId, jobInfo, cbamRequest, vnf);
391 cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION);
397 private void terminateVnf(String vnfmId, String vnfId, JobInfo jobInfo, TerminateVnfRequest cbamRequest, com.nokia.cbam.lcm.v32.model.VnfInfo vnf) throws ApiException {
398 String vimId = getVimIdFromInstantiationRequest(vnfmId, vnf);
399 grantManager.requestGrantForTerminate(vnfmId, vnfId, vimId, getVnfdIdFromModifyableAttributes(vnf), vnf, jobInfo.getJobId());
400 OperationExecution terminationOperation = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdTerminatePost(vnfId, cbamRequest, NOKIA_LCM_API_VERSION);
401 OperationExecution finishedOperation = waitForOperationToFinish(vnfmId, vnfId, terminationOperation.getId());
402 if (finishedOperation.getStatus() == FINISHED) {
403 notificationManager.waitForTerminationToBeProcessed(finishedOperation.getId());
404 logger.info("Deleting VNF with {}", vnfId);
405 cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdDelete(vnfId, NOKIA_LCM_API_VERSION);
406 logger.info("VNF with {} has been deleted", vnfId);
409 logger.error("Unable to terminate VNF the operation did not finish with success");
413 private String getVimIdFromInstantiationRequest(String vnfmId, com.nokia.cbam.lcm.v32.model.VnfInfo vnf) throws ApiException {
414 OperationExecution lastInstantiation = findLastInstantiation(vnf.getOperationExecutions());
415 Object operationParameters = cbamRestApiProvider.getCbamOperationExecutionApi(vnfmId).operationExecutionsOperationExecutionIdOperationParamsGet(lastInstantiation.getId(), NOKIA_LCM_API_VERSION);
416 JsonObject root = new Gson().toJsonTree(operationParameters).getAsJsonObject();
417 return childElement(childElement(root, "vims").getAsJsonArray().get(0).getAsJsonObject(), "id").getAsString();
420 private String getVnfdIdFromModifyableAttributes(com.nokia.cbam.lcm.v32.model.VnfInfo vnf) {
421 return find(vnf.getExtensions(), p -> p.getName().equals(ONAP_CSAR_ID)).getValue().toString();
425 * @param vnfmId the identifier of the VNFM
426 * @param vnfId the identifier of the VNF
427 * @return the current state of the VNF
429 public VnfInfo queryVnf(String vnfmId, String vnfId) {
431 com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
432 VnfInfo vnfInfo = new VnfInfo();
433 vnfInfo.setVersion(cbamVnfInfo.getVnfSoftwareVersion());
434 vnfInfo.setVnfInstanceId(vnfId);
435 String onapCsarId = getVnfdIdFromModifyableAttributes(cbamVnfInfo);
436 vnfInfo.setVnfdId(onapCsarId);
437 vnfInfo.setVnfPackageId(onapCsarId);
438 vnfInfo.setVnfInstanceDescription(cbamVnfInfo.getDescription());
439 vnfInfo.setVnfInstanceName(cbamVnfInfo.getName());
440 vnfInfo.setVnfProvider(cbamVnfInfo.getVnfProvider());
441 vnfInfo.setVnfStatus("ACTIVE");
442 vnfInfo.setVnfType("Kuku");
444 } catch (ApiException e) {
445 throw fatalFailure(logger, "Unable to query VNF (" + vnfId + ")", e);
449 private ScaleDirection convert(org.onap.vnfmdriver.model.ScaleDirection direction) {
450 if (org.onap.vnfmdriver.model.ScaleDirection.IN.equals(direction)) {
451 return ScaleDirection.IN;
453 return ScaleDirection.OUT;
460 * @param vnfmId the identifier of the VNFM
461 * @param vnfId the identifier of the VNF
462 * @param request the scale request
463 * @param httpResponse the HTTP response
464 * @return the job for tracking the scale
466 public JobInfo scaleVnf(String vnfmId, String vnfId, VnfScaleRequest request, HttpServletResponse httpResponse) {
467 if (logger.isInfoEnabled()) {
468 logger.info("Scale VNF with {} identifier REST: {}", vnfId, new Gson().toJson(request));
470 return scheduleExecution(vnfId, httpResponse, "scale", jobInfo -> {
471 ScaleVnfRequest cbamRequest = new ScaleVnfRequest();
472 cbamRequest.setAspectId(request.getAspectId());
473 cbamRequest.setNumberOfSteps(Integer.valueOf(request.getNumberOfSteps()));
474 cbamRequest.setType(convert(request.getType()));
475 com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
476 JsonObject root = new Gson().toJsonTree(jobInfo).getAsJsonObject();
477 com.nokia.cbam.lcm.v32.model.VnfInfo cbamVnfInfo = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
478 String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, cbamVnfInfo.getVnfdId());
479 Set<String> acceptableOperationParameters = getAcceptableOperationParameters(vnfdContent, "Basic", "scale");
480 if (request.getAdditionalParam() != null) {
481 for (Map.Entry<String, JsonElement> item : new Gson().toJsonTree(request.getAdditionalParam()).getAsJsonObject().entrySet()) {
482 if (acceptableOperationParameters.contains(item.getKey())) {
483 root.add(item.getKey(), item.getValue());
487 logger.warn("No additional parameters were passed for scaling");
489 cbamRequest.setAdditionalParams(root);
490 grantManager.requestGrantForScale(vnfmId, vnfId, getVimIdFromInstantiationRequest(vnfmId, vnf), getVnfdIdFromModifyableAttributes(vnf), request, jobInfo.getJobId());
491 OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdScalePost(vnfId, cbamRequest, NOKIA_LCM_API_VERSION);
492 waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
499 * @param vnfmId the identifier of the VNFM
500 * @param vnfId the identifier of the VNF
501 * @param request the heal request
502 * @param httpResponse the HTTP response
503 * @return the job for tracking the heal
505 public JobInfo healVnf(String vnfmId, String vnfId, VnfHealRequest request, HttpServletResponse httpResponse) {
506 return scheduleExecution(vnfId, httpResponse, "heal", job -> {
507 HealVnfRequest cbamHealRequest = new HealVnfRequest();
508 Map<String, String> additionalParams = new HashMap<>();
509 additionalParams.put("vmName", request.getAffectedvm().getVmname());
510 additionalParams.put("action", request.getAction());
511 additionalParams.put("jobId", job.getJobId());
512 cbamHealRequest.setAdditionalParams(additionalParams);
513 com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION);
514 String vimId = getVimIdFromInstantiationRequest(vnfmId, vnf);
515 grantManager.requestGrantForHeal(vnfmId, vnfId, vimId, getVnfdIdFromModifyableAttributes(vnf), request, job.getJobId());
516 OperationExecution operationExecution = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdHealPost(vnfId, cbamHealRequest, NOKIA_LCM_API_VERSION);
517 waitForOperationToFinish(vnfmId, vnfId, operationExecution.getId());
521 private JobInfo scheduleExecution(String vnfId, HttpServletResponse httpResponse, String operation, AsynchronousExecution asynchronExecution) {
522 JobInfo jobInfo = new JobInfo();
523 jobInfo.setJobId(jobManager.spawnJob(vnfId, httpResponse));
524 executorService.submit(() -> {
526 asynchronExecution.execute(jobInfo);
527 } catch (RuntimeException e) {
528 logger.error("Unable to " + operation + " VNF with " + vnfId + " identifier", e);
529 jobManager.jobFinished(jobInfo.getJobId());
531 } catch (Exception e) {
532 String msg = "Unable to " + operation + " VNF with " + vnfId + " identifier";
533 logger.error(msg, e);
534 //the job can only be signaled to be finished after the error is logged
535 jobManager.jobFinished(jobInfo.getJobId());
536 throw new UserVisibleError(msg, e);
538 jobManager.jobFinished(jobInfo.getJobId());
543 private OperationExecution waitForOperationToFinish(String vnfmId, String vnfId, String operationExecutionId) {
546 OperationExecution operationExecution = find(cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdOperationExecutionsGet(vnfId, NOKIA_LCM_API_VERSION), opEx -> operationExecutionId.equals(opEx.getId()));
547 if (hasOperationFinished(operationExecution)) {
548 logger.debug("Operation finished with " + operationExecution.getId());
549 return operationExecution;
551 } catch (Exception e) {
552 //swallow exception and retry
553 logger.warn("Unable to retrieve operations details", e);
555 systemFunctions().sleep(OPERATION_STATUS_POLLING_INTERVAL_IN_MS);
559 private boolean hasOperationFinished(OperationExecution operationExecution) {
560 return newHashSet(FINISHED, OperationStatus.FAILED).contains(operationExecution.getStatus());
564 private interface AsynchronousExecution {
565 void execute(JobInfo job) throws ApiException;