diff options
author | Yan Yang <yangyanyj@chinamobile.com> | 2018-07-26 01:11:57 +0000 |
---|---|---|
committer | Gerrit Code Review <gerrit@onap.org> | 2018-07-26 01:11:57 +0000 |
commit | 0ba27e81b04128fe3c5c2a476eda8484f32ccfd7 (patch) | |
tree | 99ced00b5ad2a17f6b79333e723c13d6a9bef807 /nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java | |
parent | 3cc1fad281c125803f4fb7b4284e1437a8ce1663 (diff) | |
parent | 3e8bea1fa3861581b3caa81628da52da538b05f3 (diff) |
Merge "Add SO APIs to Nokia VNFM adapter"
Diffstat (limited to 'nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java')
-rw-r--r-- | nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java | 216 |
1 files changed, 216 insertions, 0 deletions
diff --git a/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java new file mode 100644 index 00000000..f437a902 --- /dev/null +++ b/nokiav2/driver/src/main/java/org/onap/vfc/nfvo/driver/vnfm/svnfm/nokia/packagetransformer/OnapR2HeatPackageBuilder.java @@ -0,0 +1,216 @@ +/* + * Copyright 2016-2017, Nokia Corporation + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.packagetransformer; + +import com.google.common.collect.Sets; +import com.google.gson.*; +import java.util.HashMap; +import java.util.Map; +import java.util.Set; +import org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.vnfm.LifecycleManager; +import org.slf4j.Logger; +import org.yaml.snakeyaml.Yaml; + +import static java.util.stream.Collectors.toSet; + +import static org.onap.vfc.nfvo.driver.vnfm.svnfm.nokia.util.CbamUtils.*; +import static org.slf4j.LoggerFactory.getLogger; + +/** + * Transforms a CBAM package into an ONAP package + */ +public class OnapR2HeatPackageBuilder { + public static final String ETSI_MODIFIABLE_ATTRIBUTES_EXTENSTION = "etsi_modifiable_attributes_extenstion_"; + public static final String IMAGE_NAME = "_image_name"; + public static final String FLAVOR_NAME = "_flavor_name"; + public static final String NET_ID = "_net_id"; + private static Logger logger = getLogger(OnapR2HeatPackageBuilder.class); + public static final String BASE_ENV_FILE_NAME = "base.env"; + public static final String BASE_YAML_FILE_NAME = "base.yaml"; + + private Set<String> autoManagedExtensions = Sets.newHashSet(LifecycleManager.ONAP_CSAR_ID, LifecycleManager.EXTERNAL_VNFM_ID); + + Map<String, String> processVnfd(String cbamVnfd) { + Map<String, String> files = new HashMap<>(); + JsonObject root = new Gson().toJsonTree(new Yaml().load(cbamVnfd)).getAsJsonObject(); + JsonObject topologyTemplate = child(root, "topology_template"); + JsonObject substitutionMappings = child(topologyTemplate, "substitution_mappings"); + JsonObject capabilities = child(substitutionMappings, "capabilities"); + JsonObject deploymentFlavour = child(capabilities, "deployment_flavour"); + JsonArray policies = childElement(topologyTemplate, "policies").getAsJsonArray(); + JsonObject manifest = new JsonObject(); + manifest.addProperty("name", "ONAP VNF package"); + manifest.addProperty("description", ""); + JsonArray data = new JsonArray(); + manifest.add("data", data); + JsonObject deploymentFlavorProperties = child(deploymentFlavour, "properties"); + if (deploymentFlavorProperties.has("scaling_aspects")) { + JsonObject scalingAspects = child(deploymentFlavorProperties, "scaling_aspects"); + for (Map.Entry<String, JsonElement> scalingAspect : scalingAspects.entrySet()) { + processAspect(files, data, policies, scalingAspect.getKey(), childElement(scalingAspect.getValue().getAsJsonObject(), "max_scale_level").getAsLong()); + } + } + processBaseIncrement(topologyTemplate, files, policies, data); + files.put("MANIFEST.json", new GsonBuilder().setPrettyPrinting().create().toJson(manifest)); + return files; + } + + private void processBaseIncrement(JsonObject topologyTemplate, Map<String, String> files, JsonArray policies, JsonArray data) { + StringBuilder envContent = prepareEvnContent(); + StringBuilder yamlContent = prepareYamlContent(); + if (topologyTemplate.has("node_templates")) { + JsonObject nodeTemplates = child(topologyTemplate, "node_templates"); + processEcps(nodeTemplates, envContent, yamlContent); + for (Map.Entry<String, JsonElement> vdu : filterType(nodeTemplates, "tosca.nodes.nfv.VDU")) { + addImageAndFlavor(envContent, yamlContent, vdu); + } + } + processModifiableAttributes(topologyTemplate, envContent, yamlContent); + data.add(buildManifestEntry(BASE_ENV_FILE_NAME, BASE_YAML_FILE_NAME, true)); + files.put(BASE_ENV_FILE_NAME, envContent.toString()); + files.put(BASE_YAML_FILE_NAME, yamlContent.toString()); + } + + private void processModifiableAttributes(JsonObject topologyTemplate, StringBuilder envContent, StringBuilder yamlContent) { + JsonObject capabilities = child(child(topologyTemplate, "substitution_mappings"), "capabilities"); + if (capabilities.has("vnf")) { + JsonObject vnf = child(capabilities, "vnf"); + if (vnf.has("properties")) { + JsonObject properties = child(vnf, "properties"); + if (properties.has("modifiable_attributes")) { + JsonObject modifiableAttributes = child(properties, "modifiable_attributes"); + if (modifiableAttributes.has("extensions")) { + JsonObject extensions = child(modifiableAttributes, "extensions"); + for (Map.Entry<String, JsonElement> extension : extensions.entrySet()) { + if (!autoManagedExtensions.contains(extension.getKey())) { + addParameter(yamlContent, envContent, ETSI_MODIFIABLE_ATTRIBUTES_EXTENSTION + extension.getKey(), "Modifiable attribute", "Modifiable attribute for " + extension.getKey()); + } + } + } + } + } + } + } + + public static Set<Map.Entry<String, JsonElement>> filterType(JsonObject nodeTemplates, String type) { + return nodeTemplates.entrySet().stream().filter(e -> e.getValue().getAsJsonObject().get("type").equals(type)).collect(toSet()); + } + + private void processEcps(JsonObject nodeTemplates, StringBuilder envContent, StringBuilder yamlContent) { + for (Map.Entry<String, JsonElement> node : filterType(nodeTemplates, "tosca.nodes.nfv.ECP")) { + envContent.append(" " + node.getKey() + NET_ID + ": PUT YOUR NETWORK ID HERE\n"); + addYamlParameter(yamlContent, node.getKey() + NET_ID, "Network id", "Network identifier for " + node.getKey() + " ECP"); + } + } + + private StringBuilder prepareYamlContent() { + StringBuilder yamlContent = new StringBuilder(); + yamlContent.append("heat_template_version: 2013-05-23\n"); + yamlContent.append("parameters:\n"); + return yamlContent; + } + + private void processAspect(Map<String, String> files, JsonArray data, JsonArray policies, String aspectName, long maxScaleLevel) { + JsonObject aspect = locateAspect(locateHeatPolicy(policies), aspectName); + StringBuilder envContent = prepareEvnContent(); + StringBuilder yamlContent = prepareYamlContent(); + if (aspect.has("vdus")) { + processMapping(aspect, envContent, yamlContent); + } + if (maxScaleLevel > 1001) { + throw buildFatalFailure(logger, "Refusing to create more than 1001 scaling levels"); + } + envContent.append(" etsi.scalingAspectId: "+ aspectName + "\n"); + for (int scaleIndex = 0; scaleIndex < maxScaleLevel; scaleIndex++) { + String envFileName = "module_" + aspectName + "_" + scaleIndex + ".env"; + files.put(envFileName, envContent.toString()); + String yamlFileName = "module_" + aspectName + "_" + scaleIndex + ".yaml"; + files.put(yamlFileName, yamlContent.toString()); + data.add(buildManifestEntry(envFileName, yamlFileName, false)); + } + } + + private StringBuilder prepareEvnContent() { + StringBuilder envContent = new StringBuilder(); + envContent.append("parameters:\n"); + return envContent; + } + + private JsonObject buildManifestEntry(String envFileName, String yamlFileName, boolean base) { + JsonObject manifestEntry = new JsonObject(); + manifestEntry.addProperty("file", yamlFileName); + manifestEntry.addProperty("type", "HEAT"); + manifestEntry.addProperty("isBase", Boolean.toString(base)); + JsonArray envEntries = new JsonArray(); + manifestEntry.add("data", envEntries); + JsonObject envEntry = new JsonObject(); + envEntries.add(envEntry); + envEntry.addProperty("file", envFileName); + envEntry.addProperty("type", "HEAT_ENV"); + return manifestEntry; + } + + private void processMapping(JsonObject mapping, StringBuilder envContent, StringBuilder yamlContent) { + for (Map.Entry<String, JsonElement> vdusElement : child(mapping, "vdus").entrySet()) { + addImageAndFlavor(envContent, yamlContent, vdusElement); + } + if (mapping.has("externalConnectionPoints")) { + for (Map.Entry<String, JsonElement> externalConnectionPoints : child(mapping, "externalConnectionPoints").entrySet()) { + addParameter(yamlContent, envContent, externalConnectionPoints.getKey() + "_net_id", "Network id", "Network to be used for " + externalConnectionPoints.getKey() + " ECP"); + addParameter(yamlContent, envContent, externalConnectionPoints.getKey() + "_subnet_id", "Subnet id", "Subnet to be used for " + externalConnectionPoints.getKey() + " ECP"); + } + } + } + + private void addImageAndFlavor(StringBuilder envContent, StringBuilder yamlContent, Map.Entry<String, JsonElement> vdusElement) { + String vdu = vdusElement.getKey(); + addParameter(yamlContent, envContent, vdu + IMAGE_NAME, "Image name or identifier", "Image to be used for " + vdu + " VDU"); + addParameter(yamlContent, envContent, vdu + FLAVOR_NAME, "Flavor name or identifier", "Flavor to be used for " + vdu + " VDU"); + } + + private void addParameter(StringBuilder yamlContent, StringBuilder envContent, String key, String label, String description) { + addYamlParameter(yamlContent, key, label, description); + envContent.append(" " + key + ": PUT YOUR " + label.toUpperCase() + " HERE\n"); + } + + private void addYamlParameter(StringBuilder yamlContent, String key, String label, String description) { + yamlContent.append(" " + key + ":\n"); + yamlContent.append(" type: string\n"); + yamlContent.append(" label: " + label + "\n"); + yamlContent.append(" description: " + description + "\n"); + } + + private JsonObject locateHeatPolicy(JsonArray policies) { + for (int index = 0; index < policies.size(); index++) { + JsonObject c = policies.get(index).getAsJsonObject(); + JsonObject policy = c.getAsJsonObject().entrySet().iterator().next().getValue().getAsJsonObject(); + if ("tosca.policies.nfv.HeatMapping".equals(childElement(policy, "type").getAsString())) { + return policy; + } + } + throw buildFatalFailure(logger, "The heat_mapping section is missing from VNFD"); + } + + private JsonObject locateAspect(JsonObject policy, String aspectName) { + for (Map.Entry<String, JsonElement> aspect : child(child(policy, "properties"), "aspects").entrySet()) { + if (aspect.getKey().equals(aspectName)) { + return aspect.getValue().getAsJsonObject(); + } + } + throw buildFatalFailure(logger, "Unable to locate " + aspectName + " in heat policy"); + } +} |