diff options
Diffstat (limited to 'dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java')
-rw-r--r-- | dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java | 120 |
1 files changed, 87 insertions, 33 deletions
diff --git a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java index 7a6f9a7..fba8245 100644 --- a/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java +++ b/dcaedt_be/src/main/java/org/onap/sdc/dcae/composition/impl/BlueprintBusinessLogic.java @@ -1,42 +1,42 @@ package org.onap.sdc.dcae.composition.impl; +import com.google.gson.Gson; import org.apache.commons.lang.StringUtils; import org.onap.sdc.common.onaplog.Enums.LogLevel; -import org.onap.sdc.dcae.catalog.asdc.ASDC; -import org.onap.sdc.dcae.catalog.asdc.ASDCUtils; -import org.onap.sdc.dcae.catalog.asdc.Blueprinter; +import org.onap.sdc.dcae.catalog.commons.Recycler; import org.onap.sdc.dcae.composition.restmodels.MessageResponse; import org.onap.sdc.dcae.composition.restmodels.VfcmtData; import org.onap.sdc.dcae.composition.restmodels.sdc.Artifact; import org.onap.sdc.dcae.composition.restmodels.sdc.ResourceDetailed; -import org.onap.sdc.dcae.composition.util.DcaeBeConstants; import org.onap.sdc.dcae.errormng.ActionStatus; import org.onap.sdc.dcae.errormng.ErrConfMgr; -import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.boot.context.properties.ConfigurationProperties; +import org.springframework.http.HttpEntity; import org.springframework.http.HttpStatus; import org.springframework.http.ResponseEntity; import org.springframework.stereotype.Component; +import org.springframework.util.Base64Utils; +import org.springframework.web.client.RestTemplate; +import org.yaml.snakeyaml.Yaml; -import javax.annotation.PostConstruct; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.IOException; import java.io.StringReader; -import java.net.URI; +import java.util.*; +import java.util.stream.Collectors; +import java.util.zip.ZipEntry; +import java.util.zip.ZipInputStream; @Component +@ConfigurationProperties(prefix="blueprinter") public class BlueprintBusinessLogic extends CompositionBusinessLogic { - @Autowired - private Blueprinter blueprinter; - @Autowired - private ASDC asdc; - - - @PostConstruct - public void init() { - URI sdcUri = URI.create(systemProperties.getProperties().getProperty(DcaeBeConstants.Config.URI)); - asdc.setUri(sdcUri); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "SDC uri: {}", sdcUri); - } + private String uri; + public void setUri(String uri) { + this.uri = uri; + } public ResponseEntity generateAndSaveBlueprint(String userId, String context, String vfcmtUuid, String serviceUuid, String vfiName, String flowType, String requestId) { try { @@ -50,7 +50,13 @@ public class BlueprintBusinessLogic extends CompositionBusinessLogic { debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Found the cdump (composition.yml) on top of VFCMT {}", vfcmtUuid); String cdump = cdumpArtifactData.getPayloadData(); debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "Going to use python procedure to create a blueprint...."); - String resultBlueprintCreation = generateBlueprintViaToscaLab(cdump); + + String input = prepareInput(cdump, requestId); + if (null == input) { + return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.SUBMIT_BLUEPRINT_ERROR); + } + String resultBlueprintCreation = new RestTemplate().postForObject(uri, new HttpEntity<>(input), String.class); + if (StringUtils.isEmpty(resultBlueprintCreation)) { errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Error occurred during blueprint generation"); return ErrConfMgr.INSTANCE.buildErrorResponse(ActionStatus.GENERATE_BLUEPRINT_ERROR, "", vfcmt.getName()); @@ -80,17 +86,65 @@ public class BlueprintBusinessLogic extends CompositionBusinessLogic { } } - private String generateBlueprintViaToscaLab(String cdump) { - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "---------------------------------------------------------------CDUMP: -----------------------------------------------------------------------------"); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), cdump); - debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "---------------------------------------------------------------------------------------------------------------------------------------------------"); - ASDCUtils utils = new ASDCUtils(asdc, blueprinter); - String resultBlueprintCreation = null; - try{ - resultBlueprintCreation = utils.buildBlueprintViaToscaLab(new StringReader(cdump)).waitForResult().waitForResult(); - }catch (Exception e){ - errLogger.log(LogLevel.ERROR, this.getClass().getName(), "Generate blueprint via tosca lab error: {}", e); - } - return resultBlueprintCreation; - } + private String prepareInput(String cdump, String requestId) throws IOException { + + debugLogger.log(LogLevel.DEBUG, this.getClass().getName(), "fetched cdump payload: {}", cdump); + Map cdumpToTosca = new Recycler().recycle(new StringReader(cdump)); + Set<String> dcaeComponentsUuids = extractComponentUuids(cdumpToTosca); + List<Map> extractedModels = Collections.synchronizedSet(dcaeComponentsUuids).parallelStream().map(id -> fetchAndExtractModel(id, requestId)).filter(Objects::nonNull).collect(Collectors.toList()); + // aggregation of parallel stream fetch results - exceptions are swallowed and we check the final size to verify no errors occurred + if(dcaeComponentsUuids.size() != extractedModels.size()) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "error: {} distinct DCAE components were mapped to {} tosca lab input models.", dcaeComponentsUuids.size(), extractedModels.size()); + return null; + } + return new Gson().toJson(new ToscaLabInput(Base64Utils.encodeToString(new Yaml().dump(cdumpToTosca).getBytes()), extractedModels)); + } + + private Set<String> extractComponentUuids(Map cdump) { + //the node description contains the UUID of the resource declaring it + //if the description is the URI the resource uuid is the 5th path element (backward compatibility) + // TODO there has to be a better way + Map<String, Map<String, Object>> nodes = (Map<String, Map<String, Object>>)((Map<String, Object>)cdump.get("topology_template")).get("node_templates"); + return nodes.values().stream() + .map(n -> (String)n.get("description")) + .filter(StringUtils::isNotBlank) + .map(d -> StringUtils.substringBetween(d, "resources/", "/")) + .collect(Collectors.toSet()); + } + + + private class ToscaLabInput { + private String template; + private List<Map> models; + + ToscaLabInput(String template, List<Map> models){ + this.template = template; + this.models = models; + } + } + + private Map<String, String> fetchAndExtractModel(String uuid, String requestId) { + try { + return extractModelFromCsar(sdcRestClient.getResourceToscaModel(uuid, requestId)); + } catch (Exception e) { + errLogger.log(LogLevel.ERROR, this.getClass().getName(), "model extraction error: {}", e); + return null; + } + } + + private Map<String, String> extractModelFromCsar(byte[] csar) throws IOException { + //we are only interested in unzipping the 3 files under Artifacts/Deployment/DCAE_TOSCA/ + String dcaeToscaDir = "Artifacts/Deployment/DCAE_TOSCA/"; + Map<String, String> extracted = new HashMap<>(); + try (ZipInputStream zis = new ZipInputStream(new ByteArrayInputStream(csar))) { + ZipEntry ze = zis.getNextEntry(); + while (ze != null && 3 != extracted.size()) { + if(ze.getName().startsWith(dcaeToscaDir)) { + extracted.put(ze.getName().replace(dcaeToscaDir,"").split("\\.")[0], Base64Utils.encodeToString(extractFile(zis))); + } + ze = zis.getNextEntry(); + } + return extracted; + } + } } |