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.onap.vfc;
19 import com.google.common.annotations.VisibleForTesting;
20 import com.google.gson.Gson;
21 import com.google.gson.JsonArray;
22 import com.google.gson.JsonElement;
23 import com.google.gson.JsonObject;
24 import com.nokia.cbam.lcm.v32.model.VnfInfo;
25 import com.nokia.cbam.lcm.v32.model.VnfcResourceInfo;
27 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.api.IGrantManager;
28 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.spring.Conditions;
29 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CatalogManager;
30 import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider;
31 import org.onap.vnfmdriver.model.*;
32 import org.slf4j.Logger;
33 import org.springframework.beans.factory.annotation.Autowired;
34 import org.springframework.context.annotation.Conditional;
35 import org.springframework.stereotype.Component;
36 import org.yaml.snakeyaml.Yaml;
38 import static com.nokia.cbam.lcm.v32.model.InstantiationState.INSTANTIATED;
39 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.buildFatalFailure;
40 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.child;
41 import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.CbamRestApiProvider.NOKIA_LCM_API_VERSION;
42 import static org.onap.vnfmdriver.model.OperationType.TERMINAL;
43 import static org.slf4j.LoggerFactory.getLogger;
46 * Responsible for handling granting before the execution of a VNF operation
49 @Conditional(value = Conditions.UseForVfc.class)
50 public class VfcGrantManager implements IGrantManager {
51 private static Logger logger = getLogger(VfcGrantManager.class);
52 private final CatalogManager catalogManager;
53 private final CbamRestApiProvider cbamRestApiProvider;
54 private final VfcRestApiProvider vfcRestApiProvider;
57 VfcGrantManager(CatalogManager catalogManager, CbamRestApiProvider cbamRestApiProvider, VfcRestApiProvider vfcRestApiProvider) {
58 this.catalogManager = catalogManager;
59 this.cbamRestApiProvider = cbamRestApiProvider;
60 this.vfcRestApiProvider = vfcRestApiProvider;
64 public void requestGrantForHeal(String vnfmId, String vnfId, String vimId, String onapCsarId, VnfHealRequest request, String jobId) {
65 GrantVNFRequest grantRequest = buildGrantRequest(vnfmId, vimId, onapCsarId, jobId, OperationType.HEAL);
66 ResourceChange resourceChange = new ResourceChange();
67 resourceChange.setType(ChangeType.VDU);
68 resourceChange.setVdu(request.getAffectedvm().getVduid());
69 resourceChange.setResourceDefinitionId(UUID.randomUUID().toString());
70 grantRequest.getRemoveResource().add(resourceChange);
71 grantRequest.getAddResource().add(resourceChange);
72 grantRequest.setVnfInstanceId(vnfId);
73 requestGrant(grantRequest);
77 public void requestGrantForScale(String vnfmId, String vnfId, String vimId, String onapCsarId, VnfScaleRequest request, String jobId) {
80 com.nokia.cbam.lcm.v32.model.VnfInfo vnf = cbamRestApiProvider.getCbamLcmApi(vnfmId).vnfsVnfInstanceIdGet(vnfId, NOKIA_LCM_API_VERSION).blockingFirst();
81 cbamVnfdId = vnf.getVnfdId();
82 } catch (Exception e) {
83 throw buildFatalFailure(logger, "Unable to query VNF " + vnfId, e);
85 OperationType operationType = ScaleDirection.IN.equals(request.getType()) ? OperationType.SCALEIN : OperationType.SCALEOUT;
86 GrantVNFRequest grantRequest = buildGrantRequest(vnfmId, vimId, onapCsarId, jobId, operationType);
87 String vnfdContent = catalogManager.getCbamVnfdContent(vnfmId, cbamVnfdId);
88 Set<ResourceChange> resourceChanges = calculateResourceChangeDuringScaling(vnfdContent, request.getAspectId(), Integer.parseInt(request.getNumberOfSteps()));
89 if (request.getType() == ScaleDirection.IN) {
90 grantRequest.getRemoveResource().addAll(resourceChanges);
93 grantRequest.getAddResource().addAll(resourceChanges);
95 grantRequest.setVnfInstanceId(vnfId);
96 requestGrant(grantRequest);
100 public void requestGrantForTerminate(String vnfmId, String vnfId, String vimId, String onapVnfdId, VnfInfo vnf, String jobId) {
101 if (vnf.getInstantiationState() == INSTANTIATED) {
102 GrantVNFRequest grantRequest;
104 grantRequest = buildGrantRequest(vnfmId, vimId, onapVnfdId, jobId, TERMINAL);
105 grantRequest.setVnfInstanceId(vnfId);
106 addVnfcsToGrant(vnf, grantRequest);
107 } catch (Exception e) {
108 throw buildFatalFailure(logger, "Unable to prepare grant request for termination", e);
110 requestGrant(grantRequest);
114 private void addVnfcsToGrant(VnfInfo vnf, GrantVNFRequest grantRequest) {
115 //VNF is instantiated but has no VNFC
116 if (vnf.getInstantiatedVnfInfo().getVnfcResourceInfo() != null) {
117 for (VnfcResourceInfo vnfc : vnf.getInstantiatedVnfInfo().getVnfcResourceInfo()) {
118 ResourceChange resourceChange = new ResourceChange();
119 grantRequest.getRemoveResource().add(resourceChange);
120 resourceChange.setVdu(vnfc.getVduId());
121 resourceChange.setType(ChangeType.VDU);
122 resourceChange.setResourceDefinitionId(UUID.randomUUID().toString());
128 public GrantVNFResponseVim requestGrantForInstantiate(String vnfmId, String vnfId, String vimId, String onapVnfdId, String instantiationLevelId, String cbamVnfdContent, String jobId) {
129 GrantVNFRequest grantRequest;
131 grantRequest = buildGrantRequest(vnfmId, vimId, onapVnfdId, jobId, OperationType.INSTANTIATE);
132 grantRequest.setVnfInstanceId(vnfId);
133 grantRequest.setAddResource(new ArrayList<>());
134 grantRequest.getAddResource().addAll(calculateResourceChangeDuringInstantiate(cbamVnfdContent, instantiationLevelId));
135 } catch (Exception e) {
136 throw buildFatalFailure(logger, "Unable to prepare grant request for instantiation", e);
138 return requestGrant(grantRequest);
141 private GrantVNFRequest buildGrantRequest(String vnfmId, String vimId, String onapCsarId, String jobId, OperationType operationType) {
142 GrantVNFRequest grantVNFRequest = new GrantVNFRequest();
144 //Currently the grant request sent to VF-C must contain the VIM identifier in the
145 //grant response (normally in ETSI VIM identifier is received in the grant response
146 //from ETSI orchestrator the vimId parameter should be removed from this POJO
147 //to be able to fix this https://jira.onap.org/browse/VFC-603 must be solved
148 //the vimId should be removed from the AdditionalGrantParams structure
149 grantVNFRequest.setAdditionalParam(new AdditionalGrantParams(vnfmId, vimId));
150 grantVNFRequest.setVnfDescriptorId(onapCsarId);
151 grantVNFRequest.setJobId(jobId);
152 grantVNFRequest.setLifecycleOperation(operationType);
153 grantVNFRequest.setAddResource(new ArrayList<>());
154 grantVNFRequest.setRemoveResource(new ArrayList<>());
155 return grantVNFRequest;
158 private GrantVNFResponseVim requestGrant(GrantVNFRequest grantRequest) {
160 return vfcRestApiProvider.getNsLcmApi().grantvnf(grantRequest).execute().body().getVim();
161 } catch (Exception e) {
162 throw buildFatalFailure(logger, "Unable to request grant", e);
166 private Set<ResourceChange> calculateResourceChangeDuringInstantiate(String vnfdContent, String instantiationLevelId) {
167 JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject();
168 JsonObject capabilities = child(child(child(root, "topology_template"), "substitution_mappings"), "capabilities");
169 JsonObject deploymentFlavorProperties = child(child(capabilities, "deployment_flavour"), "properties");
170 JsonObject instantiationLevels = child(deploymentFlavorProperties, "instantiation_levels");
171 Set<ResourceChange> resourceChanges = new HashSet<>();
172 for (Map.Entry<String, JsonElement> vdu_level : child(child(instantiationLevels, instantiationLevelId), ("vdu_levels")).entrySet()) {
173 JsonElement numberOfInstances = vdu_level.getValue().getAsJsonObject().get("number_of_instances");
174 for (int i = 0; i < numberOfInstances.getAsLong(); i++) {
175 ResourceChange resourceChange = new ResourceChange();
176 resourceChanges.add(resourceChange);
177 resourceChange.setVdu(vdu_level.getKey());
178 resourceChange.setType(ChangeType.VDU);
179 resourceChange.setResourceDefinitionId(UUID.randomUUID().toString());
182 return resourceChanges;
185 private Set<ResourceChange> calculateResourceChangeDuringScaling(String vnfdContent, String aspectId, int steps) {
186 JsonObject root = new Gson().toJsonTree(new Yaml().load(vnfdContent)).getAsJsonObject();
187 Set<ResourceChange> resourceChanges = new HashSet<>();
188 JsonArray policies = child(root, "topology_template").getAsJsonObject().get("policies").getAsJsonArray();
189 for (JsonElement policy : policies) {
190 if ("heat_mapping".equals(policy.getAsJsonObject().entrySet().iterator().next().getKey())) {
191 JsonObject aspects = policy.getAsJsonObject().entrySet().iterator().next().getValue().getAsJsonObject().get("properties").getAsJsonObject().get("aspects").getAsJsonObject();
192 JsonObject aspect = child(aspects, aspectId);
193 if (aspect.has("vdus")) {
194 addChangesForAspect(steps, resourceChanges, aspect);
198 return resourceChanges;
201 private void addChangesForAspect(int steps, Set<ResourceChange> resourceChanges, JsonObject aspect) {
202 for (Map.Entry<String, JsonElement> vdu : aspect.get("vdus").getAsJsonObject().entrySet()) {
203 String vduId = vdu.getKey();
204 for (int step = 0; step < steps; step++) {
205 for (int i = 0; i < vdu.getValue().getAsJsonArray().size(); i++) {
206 ResourceChange resourceChange = new ResourceChange();
207 resourceChange.setVdu(vduId);
208 resourceChange.setType(ChangeType.VDU);
209 resourceChange.setResourceDefinitionId(UUID.randomUUID().toString());
210 resourceChanges.add(resourceChange);
217 * Represents the mandatory parameters that must be sent during grant request to VF-C
220 static class AdditionalGrantParams {
221 private final String vnfmId;
222 private final String vimId;
224 AdditionalGrantParams(String vnfmId, String vimId) {
225 this.vnfmId = vnfmId;
230 * @return the identifier of the VNFM requesting the grant
232 public String getVnfmId() {
237 * @return the identifier of the VIM for which the grant is requested
239 public String getVimId() {