From aff272b3c41bc3be1b8a1748fd31acbadc369ff0 Mon Sep 17 00:00:00 2001 From: nirajsingh Date: Mon, 30 Sep 2019 08:36:30 +0000 Subject: [PATCH] Support short notation for artifacts definition As per [1], artifacts supports both short and extended notation. Extended notation is already supported. This patch adds support for short notation. Short notation example: artifacts: : [1] https://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.2/os/TOSCA-Simple-Profile-YAML-v1.2-os.html#DEFN_ENTITY_ARTIFACT_DEF Closes-Bug: #1850755 Change-Id: I057bfae8ba8aeee7c8ecb57cca26e11b1bf82bab --- ...tation-for-artifacts-8e7781fedcc8df33.yaml | 6 + tacker/common/csar_utils.py | 42 ++++--- .../Definitions/helloworld3_df_simple.yaml | 44 +++++++ .../TOSCA-Metadata/TOSCA.meta | 7 ++ .../Definitions/helloworld3_df_simple.yaml | 31 +++++ .../TOSCA-Metadata/TOSCA.meta | 7 ++ .../Definitions/helloworld3_df_simple.yaml | 114 ++++++++++++++++++ .../Definitions/helloworld3_top.vnfd.yaml | 31 +++++ .../Definitions/helloworld3_types.yaml | 53 ++++++++ .../TOSCA-Metadata/TOSCA.meta | 7 ++ tacker/tests/unit/common/test_csar_utils.py | 53 +++++++- 11 files changed, 373 insertions(+), 22 deletions(-) create mode 100644 releasenotes/notes/support-short-notation-for-artifacts-8e7781fedcc8df33.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/csar_multiple_sw_image_data_with_short_notation/Definitions/helloworld3_df_simple.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/csar_multiple_sw_image_data_with_short_notation/TOSCA-Metadata/TOSCA.meta create mode 100644 tacker/tests/etc/samples/etsi/nfv/csar_short_notation_for_artifacts_without_sw_image_data/Definitions/helloworld3_df_simple.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/csar_short_notation_for_artifacts_without_sw_image_data/TOSCA-Metadata/TOSCA.meta create mode 100644 tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_df_simple.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_top.vnfd.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_types.yaml create mode 100644 tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/TOSCA-Metadata/TOSCA.meta diff --git a/releasenotes/notes/support-short-notation-for-artifacts-8e7781fedcc8df33.yaml b/releasenotes/notes/support-short-notation-for-artifacts-8e7781fedcc8df33.yaml new file mode 100644 index 000000000..b330b2a61 --- /dev/null +++ b/releasenotes/notes/support-short-notation-for-artifacts-8e7781fedcc8df33.yaml @@ -0,0 +1,6 @@ +--- +fixes: + - | + Fixes `bug 1850755`_ which adds short notation support for artifacts. + + .. _bug 1850755: https://bugs.launchpad.net/tacker/+bug/1850755 diff --git a/tacker/common/csar_utils.py b/tacker/common/csar_utils.py index 0df5501ce..93673a348 100644 --- a/tacker/common/csar_utils.py +++ b/tacker/common/csar_utils.py @@ -46,9 +46,11 @@ def _get_sw_image_artifact(artifacts): return for artifact_value in artifacts.values(): - if 'type' in artifact_value: - if artifact_value['type'] == 'tosca.artifacts.nfv.SwImage': + if isinstance(artifact_value, dict): + if artifact_value.get('type') == 'tosca.artifacts.nfv.SwImage': return artifact_value + elif isinstance(artifact_value, str): + return {'file': artifact_value} def _update_default_vnfd_data(node_value, node_type_value): @@ -215,27 +217,31 @@ def _validate_instantiation_levels(policy, instantiation_levels): def _validate_sw_image_data_for_artifact(node_tpl, template_name): - artifact_type = [] + artifact_names = [] artifacts = node_tpl.get('artifacts') - if artifacts: - for key, value in artifacts.items(): + if not artifacts: + return + + for key, value in artifacts.items(): + if isinstance(value, dict): if value.get('type') == 'tosca.artifacts.nfv.SwImage': - artifact_type.append(value.get('type')) + artifact_names.append(key) + elif isinstance(value, str): + artifact_names.append(key) - if len(artifact_type) > 1: - error_msg = ('artifacts of type "tosca.artifacts.nfv.SwImage"' - ' is added more than one time for' - ' node %(node)s.') % {'node': template_name} + if len(artifact_names) > 1: + error_msg = ('artifacts of type "tosca.artifacts.nfv.SwImage"' + ' is added more than one time for' + ' node %(node)s.') % {'node': template_name} + raise exceptions.InvalidCSAR(error_msg) + + if artifact_names and node_tpl.get('properties'): + if not node_tpl.get('properties').get('sw_image_data'): + error_msg = ('Node property "sw_image_data" is missing for' + ' artifact %(artifact_name)s for node %(node)s.') % { + 'artifact_name': artifact_names[0], 'node': template_name} raise exceptions.InvalidCSAR(error_msg) - if artifact_type and node_tpl.get('properties'): - if not node_tpl.get('properties').get('sw_image_data'): - error_msg = ('Node property "sw_image_data" is missing for' - ' artifact type %(type)s for ' - 'node %(node)s.') % { - 'type': artifact_type[0], 'node': template_name} - raise exceptions.InvalidCSAR(error_msg) - def _validate_sw_image_data_for_artifacts(tosca): for tp in tosca.nested_tosca_templates_with_topology: diff --git a/tacker/tests/etc/samples/etsi/nfv/csar_multiple_sw_image_data_with_short_notation/Definitions/helloworld3_df_simple.yaml b/tacker/tests/etc/samples/etsi/nfv/csar_multiple_sw_image_data_with_short_notation/Definitions/helloworld3_df_simple.yaml new file mode 100644 index 000000000..6f3c8157c --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/csar_multiple_sw_image_data_with_short_notation/Definitions/helloworld3_df_simple.yaml @@ -0,0 +1,44 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Simple deployment flavour for Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + +topology_template: + node_templates: + VDU1: + type: tosca.nodes.nfv.Vdu.Compute + properties: + name: VDU1 + description: VDU1 compute node + vdu_profile: + min_number_of_instances: 1 + max_number_of_instances: 1 + sw_image_data: + name: Software of VDU1 + version: '0.4.0' + checksum: + algorithm: sha-256 + hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d + container_format: bare + disk_format: qcow2 + min_disk: 1 GB + size: 1 GB + + artifacts: + sw_image1: ../Files/images/cirros-0.4.0-x86_64-disk.img + sw_image2: + type: tosca.artifacts.nfv.SwImage + file: ../Files/images/cirros-0.4.0-x86_64-disk.img + + capabilities: + virtual_compute: + properties: + virtual_memory: + virtual_mem_size: 512 MB + virtual_cpu: + num_virtual_cpu: 1 + virtual_local_storage: + - size_of_storage: 1 GB diff --git a/tacker/tests/etc/samples/etsi/nfv/csar_multiple_sw_image_data_with_short_notation/TOSCA-Metadata/TOSCA.meta b/tacker/tests/etc/samples/etsi/nfv/csar_multiple_sw_image_data_with_short_notation/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 000000000..a5993440a --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/csar_multiple_sw_image_data_with_short_notation/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,7 @@ +TOSCA-Meta-File-Version: 1.0 +Created-by: Hiroyuki JO +CSAR-Version: 1.1 +Entry-Definitions: Definitions/helloworld3_df_simple.yaml + +Name: Files/images/cirros-0.4.0-x86_64-disk.img +Content-type: application/x-iso9066-image diff --git a/tacker/tests/etc/samples/etsi/nfv/csar_short_notation_for_artifacts_without_sw_image_data/Definitions/helloworld3_df_simple.yaml b/tacker/tests/etc/samples/etsi/nfv/csar_short_notation_for_artifacts_without_sw_image_data/Definitions/helloworld3_df_simple.yaml new file mode 100644 index 000000000..d3f790f5c --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/csar_short_notation_for_artifacts_without_sw_image_data/Definitions/helloworld3_df_simple.yaml @@ -0,0 +1,31 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Simple deployment flavour for Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + +topology_template: + node_templates: + VDU1: + type: tosca.nodes.nfv.Vdu.Compute + properties: + name: VDU1 + description: VDU1 compute node + vdu_profile: + min_number_of_instances: 1 + max_number_of_instances: 1 + + artifacts: + sw_image: ../Files/images/cirros-0.4.0-x86_64-disk.img + + capabilities: + virtual_compute: + properties: + virtual_memory: + virtual_mem_size: 512 MB + virtual_cpu: + num_virtual_cpu: 1 + virtual_local_storage: + - size_of_storage: 1 GB diff --git a/tacker/tests/etc/samples/etsi/nfv/csar_short_notation_for_artifacts_without_sw_image_data/TOSCA-Metadata/TOSCA.meta b/tacker/tests/etc/samples/etsi/nfv/csar_short_notation_for_artifacts_without_sw_image_data/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 000000000..a5993440a --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/csar_short_notation_for_artifacts_without_sw_image_data/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,7 @@ +TOSCA-Meta-File-Version: 1.0 +Created-by: Hiroyuki JO +CSAR-Version: 1.1 +Entry-Definitions: Definitions/helloworld3_df_simple.yaml + +Name: Files/images/cirros-0.4.0-x86_64-disk.img +Content-type: application/x-iso9066-image diff --git a/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_df_simple.yaml b/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_df_simple.yaml new file mode 100644 index 000000000..00b263b58 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_df_simple.yaml @@ -0,0 +1,114 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Simple deployment flavour for Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + - helloworld3_types.yaml + +topology_template: + inputs: + descriptor_id: + type: string + descriptor_version: + type: string + provider: + type: string + product_name: + type: string + software_version: + type: string + vnfm_info: + type: list + entry_schema: + type: string + flavour_id: + type: string + flavour_description: + type: string + + substitution_mappings: + node_type: company.provider.VNF + properties: + flavour_id: simple + requirements: + virtual_link_external: [ CP1, virtual_link ] + + node_templates: + VNF: + type: company.provider.VNF + properties: + flavour_description: A simple flavour + interfaces: + Vnflcm: + instantiate: [] + instantiate_start: [] + instantiate_end: [] + terminate: [] + terminate_start: [] + terminate_end: [] + modify_information: [] + modify_information_start: [] + modify_information_end: [] + + VDU1: + type: tosca.nodes.nfv.Vdu.Compute + properties: + name: VDU1 + description: VDU1 compute node + vdu_profile: + min_number_of_instances: 1 + max_number_of_instances: 1 + sw_image_data: + name: Software of VDU1 + version: '0.4.0' + checksum: + algorithm: sha-256 + hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d + container_format: bare + disk_format: qcow2 + min_disk: 1 GB + size: 1 GB + + artifacts: + sw_image: ../Files/images/cirros-0.4.0-x86_64-disk.img + + capabilities: + virtual_compute: + properties: + virtual_memory: + virtual_mem_size: 512 MB + virtual_cpu: + num_virtual_cpu: 1 + virtual_local_storage: + - size_of_storage: 1 GB + + CP1: + type: tosca.nodes.nfv.VduCp + properties: + layer_protocols: [ ipv4 ] + order: 0 + vnic_type: direct-physical + requirements: + - virtual_binding: VDU1 + - virtual_link: internalVL2 + + internalVL2: + type: tosca.nodes.nfv.VnfVirtualLink + properties: + connectivity_type: + layer_protocols: [ ipv4 ] + description: Internal Virtual link in the VNF + vl_profile: + max_bitrate_requirements: + root: 1048576 + leaf: 1048576 + min_bitrate_requirements: + root: 1048576 + leaf: 1048576 + virtual_link_protocol_data: + - associated_layer_protocol: ipv4 + l3_protocol_data: + ip_version: ipv4 + cidr: 11.11.0.0/24 diff --git a/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_top.vnfd.yaml b/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_top.vnfd.yaml new file mode 100644 index 000000000..e690da899 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_top.vnfd.yaml @@ -0,0 +1,31 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: Sample VNF + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + - helloworld3_types.yaml + - helloworld3_df_simple.yaml + +topology_template: + inputs: + selected_flavour: + type: string + description: VNF deployment flavour selected by the consumer. It is provided in the API + + node_templates: + VNF: + type: company.provider.VNF + properties: + flavour_id: { get_input: selected_flavour } + descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 + provider: Company + product_name: Sample VNF + software_version: '1.0' + descriptor_version: '1.0' + vnfm_info: + - Tacker + requirements: + #- virtual_link_external # mapped in lower-level templates + #- virtual_link_internal # mapped in lower-level templates diff --git a/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_types.yaml b/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_types.yaml new file mode 100644 index 000000000..12b92b710 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/Definitions/helloworld3_types.yaml @@ -0,0 +1,53 @@ +tosca_definitions_version: tosca_simple_yaml_1_2 + +description: VNF type definition + +imports: + - etsi_nfv_sol001_common_types.yaml + - etsi_nfv_sol001_vnfd_types.yaml + +node_types: + company.provider.VNF: + derived_from: tosca.nodes.nfv.VNF + properties: + descriptor_id: + type: string + constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 ] ] + default: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177 + descriptor_version: + type: string + constraints: [ valid_values: [ '1.0' ] ] + default: '1.0' + provider: + type: string + constraints: [ valid_values: [ 'Company' ] ] + default: 'Company' + product_name: + type: string + constraints: [ valid_values: [ 'Sample VNF' ] ] + default: 'Sample VNF' + software_version: + type: string + constraints: [ valid_values: [ '1.0' ] ] + default: '1.0' + vnfm_info: + type: list + entry_schema: + type: string + constraints: [ valid_values: [ Tacker ] ] + default: [ Tacker ] + flavour_id: + type: string + constraints: [ valid_values: [ simple ] ] + default: simple + flavour_description: + type: string + default: "" + requirements: + - virtual_link_external: + capability: tosca.capabilities.nfv.VirtualLinkable + - virtual_link_internal: + capability: tosca.capabilities.nfv.VirtualLinkable + interfaces: + Vnflcm: + type: tosca.interfaces.nfv.Vnflcm diff --git a/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/TOSCA-Metadata/TOSCA.meta b/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/TOSCA-Metadata/TOSCA.meta new file mode 100644 index 000000000..432a1b476 --- /dev/null +++ b/tacker/tests/etc/samples/etsi/nfv/csar_with_short_notation_for_artifacts/TOSCA-Metadata/TOSCA.meta @@ -0,0 +1,7 @@ +TOSCA-Meta-File-Version: 1.0 +Created-by: Hiroyuki JO +CSAR-Version: 1.1 +Entry-Definitions: Definitions/helloworld3_top.vnfd.yaml + +Name: Files/images/cirros-0.4.0-x86_64-disk.img +Content-type: application/x-iso9066-image diff --git a/tacker/tests/unit/common/test_csar_utils.py b/tacker/tests/unit/common/test_csar_utils.py index 8a7e8a45c..8dd6c4a57 100644 --- a/tacker/tests/unit/common/test_csar_utils.py +++ b/tacker/tests/unit/common/test_csar_utils.py @@ -21,6 +21,7 @@ from tacker.common import csar_utils from tacker.common import exceptions from tacker import context from tacker.tests import constants +from tacker.tests import utils class TestCSARUtils(testtools.TestCase): @@ -112,8 +113,8 @@ class TestCSARUtils(testtools.TestCase): exc = self.assertRaises(exceptions.InvalidCSAR, csar_utils.load_csar_data, self.context, constants.UUID, file_path) - msg = ('Node property "sw_image_data" is missing for artifact' - ' type tosca.artifacts.nfv.SwImage for node VDU1.') + msg = ('Node property "sw_image_data" is missing for ' + 'artifact sw_image for node VDU1.') self.assertEqual(msg, exc.format_message()) @mock.patch('tacker.common.csar_utils.extract_csar_zip_file') @@ -136,8 +137,8 @@ class TestCSARUtils(testtools.TestCase): exc = self.assertRaises(exceptions.InvalidCSAR, csar_utils.load_csar_data, self.context, constants.UUID, file_path) - msg = ('Node property "sw_image_data" is missing for artifact' - ' type tosca.artifacts.nfv.SwImage for node VDU1.') + msg = ('Node property "sw_image_data" is missing for' + ' artifact sw_image for node VDU1.') self.assertEqual(msg, exc.format_message()) @mock.patch('tacker.common.csar_utils.extract_csar_zip_file') @@ -175,3 +176,47 @@ class TestCSARUtils(testtools.TestCase): self.context, constants.UUID, file_path) self.assertIsNone(flavours[0].get('instantiation_levels')) self.assertEqual(vnf_data['descriptor_version'], '1.0') + + @mock.patch('tacker.common.csar_utils.extract_csar_zip_file') + def test_load_csar_with_artifacts_short_notation_without_sw_image_data( + self, mock_extract_csar_zip_file): + file_path = "./tacker/tests/etc/samples/etsi/nfv/" \ + "csar_short_notation_for_artifacts_without_sw_image_data" + zip_name, uniqueid = utils.create_csar_with_unique_vnfd_id(file_path) + exc = self.assertRaises(exceptions.InvalidCSAR, + csar_utils.load_csar_data, + self.context, constants.UUID, zip_name) + msg = ('Node property "sw_image_data" is missing for' + ' artifact sw_image for node VDU1.') + self.assertEqual(msg, exc.format_message()) + os.remove(zip_name) + + @mock.patch('tacker.common.csar_utils.extract_csar_zip_file') + def test_load_csar_data_with_artifacts_short_notation( + self, mock_extract_csar_zip_file): + file_path = "./tacker/tests/etc/samples/etsi/nfv/" \ + "csar_with_short_notation_for_artifacts" + zip_name, uniqueid = utils.create_csar_with_unique_vnfd_id(file_path) + + vnf_data, flavours = csar_utils.load_csar_data( + self.context, constants.UUID, zip_name) + self.assertEqual(vnf_data['descriptor_version'], '1.0') + self.assertEqual(vnf_data['vnfm_info'], ['Tacker']) + self.assertEqual(flavours[0]['flavour_id'], 'simple') + self.assertIsNotNone(flavours[0]['sw_images']) + os.remove(zip_name) + + @mock.patch('tacker.common.csar_utils.extract_csar_zip_file') + def test_load_csar_data_with_multiple_sw_image_data_with_short_notation( + self, mock_extract_csar_zip_file): + + file_path = "./tacker/tests/etc/samples/etsi/nfv/" \ + "csar_multiple_sw_image_data_with_short_notation" + zip_name, uniqueid = utils.create_csar_with_unique_vnfd_id(file_path) + exc = self.assertRaises(exceptions.InvalidCSAR, + csar_utils.load_csar_data, + self.context, constants.UUID, zip_name) + msg = ('artifacts of type "tosca.artifacts.nfv.SwImage"' + ' is added more than one time for node VDU1.') + self.assertEqual(msg, exc.format_message()) + os.remove(zip_name)