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:
    <artifact_name>: <artifact_file_URI>

[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
This commit is contained in:
nirajsingh 2019-09-30 08:36:30 +00:00
parent 4470236b5c
commit aff272b3c4
11 changed files with 373 additions and 22 deletions

View File

@ -0,0 +1,6 @@
---
fixes:
- |
Fixes `bug 1850755`_ which adds short notation support for artifacts.
.. _bug 1850755: https://bugs.launchpad.net/tacker/+bug/1850755

View File

@ -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:

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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)