diff options
14 files changed, 902 insertions, 2 deletions
diff --git a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java index 10f39f717f..7e25ed600f 100644 --- a/adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java +++ b/adapters/mso-openstack-adapters/src/main/java/org/onap/so/heatbridge/HeatBridgeImpl.java @@ -508,13 +508,14 @@ public class HeatBridgeImpl implements HeatBridgeApi { } } - private void updateLInterfaceIps(final Port port, final LInterface lIf) { + protected void updateLInterfaceIps(final Port port, final LInterface lIf) { for (IP ip : port.getFixedIps()) { String ipAddress = ip.getIpAddress(); if (InetAddressValidator.getInstance().isValidInet4Address(ipAddress)) { Subnet subnet = osClient.getSubnetById(ip.getSubnetId()); IPAddressString cidr = new IPAddressString(subnet.getCidr()); L3InterfaceIpv4AddressList lInterfaceIp = new L3InterfaceIpv4AddressList(); + lInterfaceIp.setIsFloating(false); lInterfaceIp.setL3InterfaceIpv4Address(ipAddress); lInterfaceIp.setNeutronNetworkId(port.getNetworkId()); lInterfaceIp.setNeutronSubnetId(ip.getSubnetId()); @@ -529,6 +530,7 @@ public class HeatBridgeImpl implements HeatBridgeApi { Subnet subnet = osClient.getSubnetById(ip.getSubnetId()); IPAddressString cidr = new IPAddressString(subnet.getCidr()); L3InterfaceIpv6AddressList ipv6 = new L3InterfaceIpv6AddressList(); + ipv6.setIsFloating(false); ipv6.setL3InterfaceIpv6Address(ipAddress); ipv6.setNeutronNetworkId(port.getNetworkId()); ipv6.setNeutronSubnetId(ip.getSubnetId()); diff --git a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/heatbridge/HeatBridgeImplTest.java b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/heatbridge/HeatBridgeImplTest.java index 03f6c737f3..18348f19d7 100644 --- a/adapters/mso-openstack-adapters/src/test/java/org/onap/so/heatbridge/HeatBridgeImplTest.java +++ b/adapters/mso-openstack-adapters/src/test/java/org/onap/so/heatbridge/HeatBridgeImplTest.java @@ -32,9 +32,12 @@ */ package org.onap.so.heatbridge; +import static com.shazam.shazamcrest.matcher.Matchers.sameBeanAs; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.ArgumentMatchers.eq; @@ -65,6 +68,7 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.Spy; import org.mockito.junit.MockitoJUnitRunner; +import org.onap.aai.domain.yang.L3InterfaceIpv6AddressList; import org.onap.aai.domain.yang.LInterface; import org.onap.aai.domain.yang.PInterface; import org.onap.aai.domain.yang.SriovPf; @@ -73,6 +77,8 @@ import org.onap.aaiclient.client.aai.AAIResourcesClient; import org.onap.aaiclient.client.aai.AAISingleTransactionClient; import org.onap.aaiclient.client.aai.entities.uri.AAIResourceUri; import org.onap.aaiclient.client.aai.entities.uri.AAIUriFactory; +import org.onap.aaiclient.client.generated.fluentbuilders.AAIFluentTypeBuilder; +import org.onap.aaiclient.client.graphinventory.GraphInventoryCommonObjectMapperProvider; import org.onap.aaiclient.client.graphinventory.exceptions.BulkProcessFailed; import org.onap.so.db.catalog.beans.CloudIdentity; import org.onap.so.heatbridge.constants.HeatBridgeConstants; @@ -93,8 +99,11 @@ import org.openstack4j.model.network.Subnet; import org.openstack4j.openstack.heat.domain.HeatResource; import org.openstack4j.openstack.heat.domain.HeatResource.Resources; import org.springframework.core.env.Environment; +import com.fasterxml.jackson.core.JsonParseException; +import com.fasterxml.jackson.databind.JsonMappingException; import com.fasterxml.jackson.databind.ObjectMapper; import com.google.common.collect.ImmutableMap; +import inet.ipaddr.IPAddressString; @RunWith(MockitoJUnitRunner.class) @@ -529,6 +538,54 @@ public class HeatBridgeImplTest { } @Test + public void testUpdateLInterfaceIps() + throws HeatBridgeException, JsonParseException, JsonMappingException, IOException { + + Port port = mock(Port.class); + when(port.getNetworkId()).thenReturn("890a203a-23gg-56jh-df67-731656a8f13a"); + when(port.getDeviceId()).thenReturn("test-device-id"); + + IP ip = mock(IP.class); + + Set<IP> ipSet = new HashSet<>(); + ipSet.add(ip); + when(ip.getIpAddress()).thenReturn("2606:ae00:2e60:100::226"); + when(ip.getSubnetId()).thenReturn("testSubnetId"); + when(port.getFixedIps()).thenAnswer(x -> ipSet); + + Subnet subnet = mock(Subnet.class); + when(subnet.getCidr()).thenReturn("169.254.100.0/24"); + when(osClient.getSubnetById("testSubnetId")).thenReturn(subnet); + + LInterface lIf = new LInterface(); + lIf.setInterfaceName("test-port-name"); + + // Act + heatbridge.updateLInterfaceIps(port, lIf); + + L3InterfaceIpv6AddressList ipv6 = new L3InterfaceIpv6AddressList(); + ipv6.setIsFloating(false); + ipv6.setL3InterfaceIpv6Address("2606:ae00:2e60:100::226"); + ipv6.setNeutronNetworkId(port.getNetworkId()); + ipv6.setNeutronSubnetId(ip.getSubnetId()); + ipv6.setL3InterfaceIpv6PrefixLength(Long.parseLong("24")); + + ArgumentCaptor<Optional> argument = ArgumentCaptor.forClass(Optional.class); + + // Assert + verify(transaction).createIfNotExists( + eq(AAIUriFactory.createResourceUri( + AAIFluentTypeBuilder.cloudInfrastructure().cloudRegion("CloudOwner", "RegionOne") + .tenant("7320ec4a5b9d4589ba7c4412ccfd290f").vserver("test-device-id") + .lInterface("test-port-name").l3InterfaceIpv6AddressList("2606:ae00:2e60:100::226"))), + argument.capture()); + + assertTrue(argument.getValue().isPresent()); + + assertThat((L3InterfaceIpv6AddressList) argument.getValue().get(), sameBeanAs(ipv6)); + } + + @Test public void testUpdateVserverLInterfacesToAai_skipVlans() throws HeatBridgeException { // Arrange List<Resource> stackResources = (List<Resource>) extractTestStackResources(); 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 index 0000000000..d1364b9e38 --- /dev/null +++ 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 @@ -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 index 0000000000..9df5262302 --- /dev/null +++ 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 @@ -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 index 0000000000..694b476ce3 --- /dev/null +++ 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 @@ -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 index 0000000000..3012893dc9 --- /dev/null +++ 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 @@ -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 index 0000000000..bf7648d8c0 --- /dev/null +++ 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 @@ -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 index 0000000000..795319c957 --- /dev/null +++ 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 @@ -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 index 0000000000..06ea01c744 --- /dev/null +++ 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 @@ -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 index 0000000000..ac8f782a99 --- /dev/null +++ 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 @@ -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 index 0000000000..29a70ecca8 --- /dev/null +++ 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 @@ -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(); + } + +} diff --git a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/application.yaml b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/application.yaml index 3faa62c51d..5c4f27c8ab 100644 --- a/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/application.yaml +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/application.yaml @@ -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 Binary files differnew file mode 100644 index 0000000000..63bad965b7 --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/invalid_ns.csar 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 Binary files differnew file mode 100644 index 0000000000..eb19c762ae --- /dev/null +++ b/so-etsi-nfvo/so-etsi-nfvo-ns-lcm/so-etsi-nfvo-ns-lcm-bpmn-flows/src/test/resources/ns.csar |