Adding Basic NSD parser 13/112213/3
authorwaqas.ikram <waqas.ikram@est.tech>
Mon, 7 Sep 2020 07:48:46 +0000 (08:48 +0100)
committerwaqas.ikram <waqas.ikram@est.tech>
Mon, 7 Sep 2020 09:08:42 +0000 (10:08 +0100)
Change-Id: I9b34054aac1649f71e0dece2a3a17e958d74d5be
Issue-ID: SO-3219
Signed-off-by: waqas.ikram <waqas.ikram@est.tech>
12 files changed:
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/FileEntry.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/FileParser.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptor.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptorParser.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/ToscaMetadata.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/ToscaMetadataParser.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/VirtualNetworkFunction.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/YamlFileParser.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptorParserTest.java [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/application.yaml
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/invalid_ns.csar [new file with mode: 0644]
so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/ns.csar [new file with mode: 0644]

diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/FileEntry.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/FileEntry.java
new file mode 100644 (file)
index 0000000..d1364b9
--- /dev/null
@@ -0,0 +1,111 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.utils.Utils.toIndentedString;
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.util.Objects;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class FileEntry {
+
+    private boolean isDirectory;
+    private String filePath;
+    private byte[] fileContent;
+
+    public boolean isDirectory() {
+        return isDirectory;
+    }
+
+    public void setDirectory(final boolean isDirectory) {
+        this.isDirectory = isDirectory;
+    }
+
+    public FileEntry isDirectory(final boolean isDirectory) {
+        this.isDirectory = isDirectory;
+        return this;
+    }
+
+    public String getFilePath() {
+        return filePath;
+    }
+
+    public void setFilename(final String filePath) {
+        this.filePath = filePath;
+    }
+
+    public FileEntry filePath(final String filePath) {
+        this.filePath = filePath;
+        return this;
+    }
+
+    public byte[] getFileContent() {
+        return fileContent;
+    }
+
+    public void setFileContent(final byte[] fileContent) {
+        this.fileContent = fileContent;
+    }
+
+    public FileEntry fileContent(final byte[] fileContent) {
+        this.fileContent = fileContent;
+        return this;
+    }
+
+    public InputStream getFileContentAsStream() {
+        if (fileContent == null || fileContent.length == 0) {
+            return null;
+        }
+        return new ByteArrayInputStream(fileContent);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(isDirectory, filePath, fileContent);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof FileEntry) {
+            final FileEntry other = (FileEntry) obj;
+            return Objects.equals(isDirectory, other.isDirectory) && Objects.equals(filePath, other.filePath)
+                    && Objects.equals(fileContent, other.fileContent);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("class FileEntry {\n");
+        sb.append("    isDirectory: ").append(toIndentedString(isDirectory)).append("\n");
+        sb.append("    filePath: ").append(toIndentedString(filePath)).append("\n");
+        sb.append("    fileContent size: ").append(toIndentedString(fileContent != null ? fileContent.length : 0))
+                .append("\n");
+        sb.append("}");
+        return sb.toString();
+    }
+
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/FileParser.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/FileParser.java
new file mode 100644 (file)
index 0000000..9df5262
--- /dev/null
@@ -0,0 +1,32 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import java.util.Map;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public interface FileParser {
+
+    Map<String, Object> getFileContent(final FileEntry entryDefinitionFileEntry);
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptor.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptor.java
new file mode 100644 (file)
index 0000000..694b476
--- /dev/null
@@ -0,0 +1,121 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.utils.Utils.toIndentedString;
+import java.io.Serializable;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class NetworkServiceDescriptor implements Serializable {
+
+    private static final long serialVersionUID = -1739293595041180242L;
+
+    private String type;
+
+    private Map<String, Object> properties = new HashMap<>();
+
+    private List<VirtualNetworkFunction> vnfs = new ArrayList<>();
+
+    public String getType() {
+        return type;
+    }
+
+    public void setType(final String type) {
+        this.type = type;
+    }
+
+    public NetworkServiceDescriptor type(final String type) {
+        this.type = type;
+        return this;
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(final Map<String, Object> properties) {
+        this.properties = properties;
+    }
+
+    public NetworkServiceDescriptor properties(final Map<String, Object> properties) {
+        this.properties = properties;
+        return this;
+    }
+
+    public List<VirtualNetworkFunction> getVnfs() {
+        return vnfs;
+    }
+
+    public void setVnfs(final List<VirtualNetworkFunction> vnfs) {
+        if (vnfs != null) {
+            this.vnfs = vnfs;
+        } else {
+            this.vnfs = new ArrayList<>();
+        }
+    }
+
+    public NetworkServiceDescriptor addVnfPkgIdsItem(final VirtualNetworkFunction vnf) {
+        if (this.vnfs == null) {
+            this.vnfs = new ArrayList<>();
+        }
+        this.vnfs.add(vnf);
+        return this;
+    }
+
+    public NetworkServiceDescriptor vnfs(final List<VirtualNetworkFunction> vnfs) {
+        this.vnfs = vnfs;
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(type, properties, vnfs);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof NetworkServiceDescriptor) {
+            final NetworkServiceDescriptor other = (NetworkServiceDescriptor) obj;
+            return Objects.equals(type, other.type) && Objects.equals(properties, other.properties)
+                    && Objects.equals(vnfs, other.vnfs);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("class NetworkServiceDescriptor {\n");
+        sb.append("    type: ").append(toIndentedString(type)).append("\n");
+        sb.append("    properties: ").append(toIndentedString(properties)).append("\n");
+        sb.append("    vnfs: ").append(toIndentedString(vnfs)).append("\n");
+        sb.append("}");
+        return sb.toString();
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptorParser.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptorParser.java
new file mode 100644 (file)
index 0000000..3012893
--- /dev/null
@@ -0,0 +1,209 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Optional;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class NetworkServiceDescriptorParser {
+    public static final String NS_NODE_TYPE = "tosca.nodes.nfv.NS";
+    private static final String NODE_TYPE = "node_type";
+    private static final String SUBSTITUTION_MAPPINGS = "substitution_mappings";
+    private static final Logger logger = LoggerFactory.getLogger(NetworkServiceDescriptorParser.class);
+    private static final String VNF_TYPE = "tosca.nodes.nfv.VNF";
+    private static final String PROPERTIES = "properties";
+    private static final String TYPE = "type";
+    private static final String NODE_TEMPLATES = "node_templates";
+    private static final String TOPOLOGY_TEMPLATE = "topology_template";
+    private static final String ENTRY_DEFINITIONS = "Entry-Definitions";
+    private static final String TOSCA_META_PATH_FILE_NAME = "TOSCA-Metadata/TOSCA.meta";
+    private final ToscaMetadataParser toscaMetadataParser;
+    private final FileParser fileParser;
+
+    @Autowired
+    public NetworkServiceDescriptorParser(final ToscaMetadataParser toscaMetadataParser, final FileParser fileParser) {
+        this.toscaMetadataParser = toscaMetadataParser;
+        this.fileParser = fileParser;
+    }
+
+    public Optional<NetworkServiceDescriptor> parser(final byte[] zipBytes) {
+        try {
+            final Map<String, FileEntry> files = getZipContent(zipBytes);
+            if (isMetaFilePresent(files)) {
+                final Optional<ToscaMetadata> optional =
+                        toscaMetadataParser.parse(files.get(TOSCA_META_PATH_FILE_NAME));
+                if (optional.isPresent()) {
+                    final ToscaMetadata toscaMetadata = optional.get();
+                    logger.info("Parsed ToscaMetadata {}", toscaMetadata);
+                    final String entryDefinitionFile = toscaMetadata.getEntry(ENTRY_DEFINITIONS);
+                    if (entryDefinitionFile != null && files.containsKey(entryDefinitionFile)) {
+                        final Map<String, Object> fileContent =
+                                fileParser.getFileContent(files.get(entryDefinitionFile));
+                        final Map<String, Object> topologyTemplates = getTopologyTemplates(fileContent);
+                        final Map<String, Object> nodeTemplates = getNodeTemplates(topologyTemplates);
+
+                        final Optional<NetworkServiceDescriptor> nsdOptional =
+                                getNetworkServiceDescriptor(topologyTemplates);;
+                        if (nsdOptional.isPresent()) {
+                            final NetworkServiceDescriptor networkServiceDescriptor = nsdOptional.get();
+                            networkServiceDescriptor.setVnfs(getVirtualNetworkFunctions(nodeTemplates));
+                            return Optional.of(networkServiceDescriptor);
+                        }
+
+                    }
+                }
+
+            }
+
+        } catch (final Exception exception) {
+            logger.error("Unable to parser nsd zip content", exception);
+        }
+        logger.error("Unable to parser nsd zip content");
+        return Optional.empty();
+    }
+
+    @SuppressWarnings("unchecked")
+    private Optional<NetworkServiceDescriptor> getNetworkServiceDescriptor(
+            final Map<String, Object> topologyTemplates) {
+        final Map<String, Object> substitutionMappings =
+                (Map<String, Object>) topologyTemplates.get(SUBSTITUTION_MAPPINGS);
+        final Object nodeType = substitutionMappings.get(NODE_TYPE);
+        if (substitutionMappings != null && nodeType != null && NS_NODE_TYPE.equals(nodeType)) {
+            final NetworkServiceDescriptor networkServiceDescriptor = new NetworkServiceDescriptor();
+            networkServiceDescriptor.setType(nodeType.toString());
+            networkServiceDescriptor.setProperties((Map<String, Object>) substitutionMappings.get(PROPERTIES));
+            return Optional.of(networkServiceDescriptor);
+        }
+        logger.error("No {} found in fileContent: {}", SUBSTITUTION_MAPPINGS, topologyTemplates);
+
+        return Optional.empty();
+    }
+
+    private List<VirtualNetworkFunction> getVirtualNetworkFunctions(final Map<String, Object> nodeTemplates) {
+        final List<VirtualNetworkFunction> vnfs = new ArrayList<>();
+        for (final Entry<String, Object> entry : nodeTemplates.entrySet()) {
+            @SuppressWarnings("unchecked")
+            final Map<String, Object> entryValue = (Map<String, Object>) entry.getValue();
+            final Object type = entryValue.get(TYPE);
+            if (type != null && type.equals(VNF_TYPE)) {
+                @SuppressWarnings("unchecked")
+                final Map<String, Object> vnfProperties = (Map<String, Object>) entryValue.get(PROPERTIES);
+                final VirtualNetworkFunction vnf = new VirtualNetworkFunction();
+                vnf.setVnfName(entry.getKey());
+
+                if (vnfProperties != null && !vnfProperties.isEmpty()) {
+                    final Object vnfDescriptorId = vnfProperties.get("descriptor_id");
+                    @SuppressWarnings("unchecked")
+                    final List<String> vnfmInfoList = (List<String>) vnfProperties.get("vnfm_info");
+                    if (vnfDescriptorId != null && vnfmInfoList != null) {
+                        vnf.setVnfmInfoList(vnfmInfoList);
+                        vnf.setVnfdId(vnfDescriptorId.toString());
+                        vnf.setProperties(vnfProperties);
+                        vnfs.add(vnf);
+                    } else {
+                        logger.warn("descriptor_id missing {}", entryValue);
+                    }
+                }
+            }
+
+        }
+        return vnfs;
+    }
+
+    private Map<String, Object> getNodeTemplates(final Map<String, Object> topologyTemplates) {
+        @SuppressWarnings("unchecked")
+        final Map<String, Object> nodeTemplates = (Map<String, Object>) topologyTemplates.get(NODE_TEMPLATES);
+        if (nodeTemplates != null) {
+            logger.debug("Found nodeTemplates: {}", topologyTemplates);
+            return nodeTemplates;
+        }
+        logger.error("No {} found in fileContent: {}", NODE_TEMPLATES, topologyTemplates);
+        return Collections.emptyMap();
+    }
+
+    private Map<String, Object> getTopologyTemplates(final Map<String, Object> fileContent) {
+        @SuppressWarnings("unchecked")
+        final Map<String, Object> topologyTemplates = (Map<String, Object>) fileContent.get(TOPOLOGY_TEMPLATE);
+        if (topologyTemplates != null) {
+            logger.debug("Found {}: {}", TOPOLOGY_TEMPLATE, topologyTemplates);
+
+            return topologyTemplates;
+        }
+        logger.error("No {} found in fileContent: {}", TOPOLOGY_TEMPLATE, fileContent);
+        return Collections.emptyMap();
+    }
+
+    private boolean isMetaFilePresent(final Map<String, FileEntry> files) {
+        return files.containsKey(TOSCA_META_PATH_FILE_NAME);
+    }
+
+    private Map<String, FileEntry> getZipContent(final byte[] zipBytes) {
+        final Map<String, FileEntry> files = new HashMap<>();
+        try (final ZipInputStream inputZipStream = new ZipInputStream(new ByteArrayInputStream(zipBytes));) {
+            ZipEntry zipEntry;
+            while ((zipEntry = inputZipStream.getNextEntry()) != null) {
+                logger.info("{} : {}", zipEntry.getName(), zipEntry.isDirectory());
+                if (files.get(zipEntry.getName()) != null) {
+                    logger.warn("{} File entry already exists ...", zipEntry.getName());
+                } else {
+                    final FileEntry fileEntry = new FileEntry().filePath(zipEntry.getName())
+                            .fileContent(getBytes(inputZipStream)).isDirectory(zipEntry.isDirectory());
+                    files.put(zipEntry.getName(), fileEntry);
+
+                }
+
+            }
+            return files;
+        } catch (final Exception exception) {
+            logger.error("Unable to parser nsd zip content", exception);
+            return Collections.emptyMap();
+        }
+    }
+
+    private byte[] getBytes(final ZipInputStream inputZipStream) throws IOException {
+        try {
+            return IOUtils.toByteArray(inputZipStream);
+        } catch (final IOException exception) {
+            logger.error("Could not read bytes from file", exception);
+            throw exception;
+        }
+    }
+
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/ToscaMetadata.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/ToscaMetadata.java
new file mode 100644 (file)
index 0000000..bf7648d
--- /dev/null
@@ -0,0 +1,75 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.utils.Utils.toIndentedString;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class ToscaMetadata {
+
+    private Map<String, String> entries = new HashMap<>();
+
+    public Map<String, String> getEntries() {
+        return entries;
+    }
+
+    public void addEntry(final String name, final String value) {
+        this.entries.put(name, value);
+    }
+
+    public boolean hasEntry(final String name) {
+        return this.entries.containsKey(name);
+    }
+
+    public String getEntry(final String name) {
+        return this.entries.get(name);
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(entries);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof ToscaMetadata) {
+            final ToscaMetadata other = (ToscaMetadata) obj;
+            return Objects.equals(entries, other.entries);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("class ToscaMetadata {\n");
+        sb.append("    entries: ").append(toIndentedString(entries)).append("\n");
+        sb.append("}");
+        return sb.toString();
+    }
+
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/ToscaMetadataParser.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/ToscaMetadataParser.java
new file mode 100644 (file)
index 0000000..795319c
--- /dev/null
@@ -0,0 +1,67 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import static org.apache.commons.lang3.StringUtils.isNotBlank;
+import java.util.List;
+import java.util.Optional;
+import org.apache.commons.io.IOUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.stereotype.Service;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class ToscaMetadataParser {
+    private static final String ATTRIBUTE_VALUE_SEPARATOR = ":";
+    private static final Logger logger = LoggerFactory.getLogger(ToscaMetadataParser.class);
+
+    public Optional<ToscaMetadata> parse(final FileEntry toscaMetaFile) {
+        try {
+            final ToscaMetadata toscaMetadata = new ToscaMetadata();
+            final List<String> lines = IOUtils.readLines(toscaMetaFile.getFileContentAsStream(), "utf-8");
+            for (final String line : lines) {
+                final String trimmedLine = line.trim();
+                if (!trimmedLine.isEmpty() && trimmedLine.contains(ATTRIBUTE_VALUE_SEPARATOR)) {
+                    final String[] entry = trimmedLine.split(ATTRIBUTE_VALUE_SEPARATOR);
+                    if (entry.length >= 2 && isNotBlank(entry[0]) && isNotBlank(entry[1])) {
+                        toscaMetadata.addEntry(entry[0].trim(), entry[1].trim());
+                    } else {
+                        logger.warn("Unexpected line in metadata file: {}", line);
+                    }
+                } else {
+                    logger.warn("Unexpected line does not contain valid separator {} in metadata file: {}",
+                            ATTRIBUTE_VALUE_SEPARATOR, line);
+                }
+
+            }
+            return Optional.of(toscaMetadata);
+
+        } catch (final Exception exception) {
+            logger.error("Unable to parser metadata file content", exception);
+        }
+        return Optional.empty();
+    }
+
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/VirtualNetworkFunction.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/VirtualNetworkFunction.java
new file mode 100644 (file)
index 0000000..06ea01c
--- /dev/null
@@ -0,0 +1,123 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Ericsson. All rights reserved.
+ * ================================================================================
+ * 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.
+ * 
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import static org.onap.so.etsi.nfvo.ns.lcm.database.beans.utils.Utils.toIndentedString;
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+public class VirtualNetworkFunction implements Serializable {
+
+    private static final long serialVersionUID = 3164293220359211834L;
+
+    private String vnfdId;
+    private String vnfName;
+    private List<String> vnfmInfoList;
+    private Map<String, Object> properties = new HashMap<>();
+
+    public String getVnfdId() {
+        return vnfdId;
+    }
+
+    public void setVnfdId(final String vnfdId) {
+        this.vnfdId = vnfdId;
+    }
+
+    public VirtualNetworkFunction vnfdId(final String vnfdId) {
+        this.vnfdId = vnfdId;
+        return this;
+    }
+
+    public String getVnfName() {
+        return vnfName;
+    }
+
+    public void setVnfName(final String vnfName) {
+        this.vnfName = vnfName;
+    }
+
+    public VirtualNetworkFunction vnfName(final String vnfName) {
+        this.vnfName = vnfName;
+        return this;
+    }
+
+    public List<String> getVnfmInfoList() {
+        return vnfmInfoList;
+    }
+
+    public void setVnfmInfoList(final List<String> vnfmInfoList) {
+        this.vnfmInfoList = vnfmInfoList;
+    }
+
+    public VirtualNetworkFunction vnfmInfoList(final List<String> vnfmInfoList) {
+        this.vnfmInfoList = vnfmInfoList;
+        return this;
+    }
+
+    public Map<String, Object> getProperties() {
+        return properties;
+    }
+
+    public void setProperties(final Map<String, Object> properties) {
+        this.properties = properties;
+    }
+
+    public VirtualNetworkFunction properties(final Map<String, Object> properties) {
+        this.properties = properties;
+        return this;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hash(vnfdId, vnfName, vnfmInfoList, properties);
+    }
+
+    @Override
+    public boolean equals(final Object obj) {
+        if (obj instanceof VirtualNetworkFunction) {
+            final VirtualNetworkFunction other = (VirtualNetworkFunction) obj;
+            return Objects.equals(vnfdId, other.vnfdId) && Objects.equals(vnfName, other.vnfName)
+                    && Objects.equals(vnfmInfoList, other.vnfmInfoList) && Objects.equals(properties, other.properties);
+        }
+        return false;
+    }
+
+    @Override
+    public String toString() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("class VirtualNetworkFunction {\n");
+        sb.append("    vnfdId: ").append(toIndentedString(vnfdId)).append("\n");
+        sb.append("    vnfName: ").append(toIndentedString(vnfName)).append("\n");
+        sb.append("    vnfmInfo: ").append(toIndentedString(vnfmInfoList)).append("\n");
+        sb.append("    properties: ").append(toIndentedString(properties)).append("\n");
+
+        sb.append("}");
+        return sb.toString();
+    }
+
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/YamlFileParser.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/main/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/YamlFileParser.java
new file mode 100644 (file)
index 0000000..ac8f782
--- /dev/null
@@ -0,0 +1,39 @@
+/*-
+ * ============LICENSE_START=======================================================
+ *  Copyright (C) 2020 Nordix Foundation.
+ * ================================================================================
+ * 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.
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ * ============LICENSE_END=========================================================
+ */
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import java.util.Map;
+import org.springframework.stereotype.Service;
+import org.yaml.snakeyaml.Yaml;
+
+/**
+ * @author Waqas Ikram (waqas.ikram@est.tech)
+ *
+ */
+@Service
+public class YamlFileParser implements FileParser {
+
+    @Override
+    public Map<String, Object> getFileContent(final FileEntry entryDefinitionFileEntry) {
+        final Yaml yaml = new Yaml();
+        return yaml.load(entryDefinitionFileEntry.getFileContentAsStream());
+    }
+
+}
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptorParserTest.java b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/java/org/onap/so/etsi/nfvo/ns/lcm/bpmn/flows/nsd/NetworkServiceDescriptorParserTest.java
new file mode 100644 (file)
index 0000000..29a70ec
--- /dev/null
@@ -0,0 +1,64 @@
+package org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.nsd;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+import java.io.File;
+import java.io.IOException;
+import java.nio.file.Files;
+import java.nio.file.Paths;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.onap.so.etsi.nfvo.ns.lcm.bpmn.flows.TestApplication;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.boot.test.context.SpringBootTest;
+import org.springframework.test.context.ActiveProfiles;
+import org.springframework.test.context.junit4.SpringRunner;
+
+
+@RunWith(SpringRunner.class)
+@SpringBootTest(classes = TestApplication.class, webEnvironment = SpringBootTest.WebEnvironment.RANDOM_PORT)
+@ActiveProfiles("test")
+public class NetworkServiceDescriptorParserTest {
+
+    private static final String VALID_ETSI_NSD_FILE = "src/test/resources/ns.csar";
+    private static final String INVALID_ETSI_NSD_FILE = "src/test/resources/invalid_ns.csar";
+
+    @Autowired
+    private NetworkServiceDescriptorParser objUnderTest;
+
+    @Test
+    public void testValidEtsiNsd_ableToParserIt() throws IOException {
+        final byte[] zipBytes = Files.readAllBytes(Paths.get(getAbsolutePath(VALID_ETSI_NSD_FILE)));
+        final Optional<NetworkServiceDescriptor> optional = objUnderTest.parser(zipBytes);
+        assertTrue(optional.isPresent());
+        final NetworkServiceDescriptor actualNsd = optional.get();
+        assertEquals(NetworkServiceDescriptorParser.NS_NODE_TYPE, actualNsd.getType());
+        assertFalse(actualNsd.getProperties().isEmpty());
+
+        final Map<String, Object> actualNsdProperties = actualNsd.getProperties();
+        assertEquals(5, actualNsdProperties.size());
+        assertEquals("ffdddc5d-a44b-45ae-8fc3-e6551cce350f", actualNsdProperties.get("descriptor_id"));
+        assertEquals(5, actualNsd.getVnfs().size());
+
+    }
+
+    @Test
+    public void testEmptyEtsiNsd_ableToParserIt() throws IOException {
+        assertFalse(objUnderTest.parser(new byte[] {}).isPresent());
+    }
+
+    @Test
+    public void testInvalidEtsiNsd_ableToParserIt() throws IOException {
+        final byte[] zipBytes = Files.readAllBytes(Paths.get(getAbsolutePath(INVALID_ETSI_NSD_FILE)));
+        assertFalse(objUnderTest.parser(zipBytes).isPresent());
+    }
+
+    private String getAbsolutePath(final String path) {
+        final File file = new File(path);
+        return file.getAbsolutePath();
+    }
+
+}
index 3faa62c..5c4f27c 100644 (file)
@@ -22,7 +22,7 @@ spring:
             pool-name: ns-lcm-bpmn-pool
             registerMbeans: true
          nfvo:
-            jdbcUrl: jdbc:h2:mem:nfvo;DB_CLOSE_DELAY=-1;INIT=CREATE SCHEMA IF NOT EXISTS nfvo;
+            jdbcUrl: jdbc:h2:mem:nfvo;DB_CLOSE_DELAY=-1;DB_CLOSE_ON_EXIT=FALSE;INIT=CREATE SCHEMA IF NOT EXISTS nfvo;
             driver-class-name: org.h2.Driver
             pool-name: ns-lcm-bpmn-pool
             registerMbeans: true
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/invalid_ns.csar b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/invalid_ns.csar
new file mode 100644 (file)
index 0000000..63bad96
Binary files /dev/null and b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/invalid_ns.csar differ
diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/ns.csar b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/ns.csar
new file mode 100644 (file)
index 0000000..eb19c76
Binary files /dev/null and b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/ns.csar differ