Merge "Support multi artifact of interfaces"

This commit is contained in:
Zuul 2022-09-16 20:34:54 +00:00 committed by Gerrit Code Review
commit 5fef0040f7
9 changed files with 789 additions and 6 deletions

View File

@ -0,0 +1,271 @@
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:
inputs:
id:
type: string
vendor:
type: string
version:
type: version
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:
implementation:
primary: vnflcm_noop
dependencies:
- mgmt-drivers-ansible-sample-end
terminate: []
terminate_start: []
terminate_end: []
artifacts:
vnflcm_noop:
description: Management driver plugin
type: tosca.artifacts.Implementation.Python
file: Drivers/vnflcm_noop.py
mgmt-drivers-ansible-sample-end:
description: Management driver sample
type: tosca.artifacts.Implementation.Yaml
file: ScriptANSIBLE/config_complex_end.yaml
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.5.2'
checksum:
algorithm: sha-256
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
container_format: bare
disk_format: qcow2
min_disk: 1 GB
size: 1 GB
artifacts:
sw_image:
type: tosca.artifacts.nfv.SwImage
file: ../Files/images/cirros-0.5.2-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
VDU2:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU2
description: VDU2 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
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
requirements:
- virtual_storage: VirtualStorage
VirtualStorage:
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
properties:
virtual_block_storage_data:
size_of_storage: 30 GB
rdma_enabled: true
sw_image_data:
name: VrtualStorage
version: '0.5.2'
checksum:
algorithm: sha-256
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
container_format: bare
disk_format: qcow2
min_disk: 2 GB
min_ram: 8192 MB
size: 2 GB
artifacts:
sw_image:
type: tosca.artifacts.nfv.SwImage
file: ../Files/images/cirros-0.5.2-x86_64-disk.img
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
vnic_type: direct-physical
requirements:
- virtual_binding: VDU1
#- virtual_link: # the target node is determined in the NSD
CP2:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 1
requirements:
- virtual_binding: VDU1
- virtual_link: internalVL2
CP3:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 2
requirements:
- virtual_binding: VDU2
- 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
policies:
- scaling_aspects:
type: tosca.policies.nfv.ScalingAspects
properties:
aspects:
worker_instance:
name: worker_instance_aspect
description: worker_instance scaling aspect
max_scale_level: 2
step_deltas:
- delta_1
- VDU2_initial_delta:
type: tosca.policies.nfv.VduInitialDelta
properties:
initial_delta:
number_of_instances: 1
targets: [ VDU2 ]
- VDU2_scaling_aspect_deltas:
type: tosca.policies.nfv.VduScalingAspectDeltas
properties:
aspect: worker_instance
deltas:
delta_1:
number_of_instances: 1
targets: [ VDU2 ]
- instantiation_levels:
type: tosca.policies.nfv.InstantiationLevels
properties:
levels:
instantiation_level_1:
description: Smallest size
scale_info:
worker_instance:
scale_level: 0
instantiation_level_2:
description: Largest size
scale_info:
worker_instance:
scale_level: 2
default_level: instantiation_level_1
- VDU1_instantiation_levels:
type: tosca.policies.nfv.VduInstantiationLevels
properties:
levels:
instantiation_level_1:
number_of_instances: 1
instantiation_level_2:
number_of_instances: 3
targets: [ VDU1 ]
- VDU2_instantiation_levels:
type: tosca.policies.nfv.VduInstantiationLevels
properties:
levels:
instantiation_level_1:
number_of_instances: 1
instantiation_level_2:
number_of_instances: 1
targets: [ VDU2 ]
- internalVL2_instantiation_levels:
type: tosca.policies.nfv.VirtualLinkInstantiationLevels
properties:
levels:
instantiation_level_1:
bitrate_requirements:
root: 1048576
leaf: 1048576
instantiation_level_2:
bitrate_requirements:
root: 1048576
leaf: 1048576
targets: [ internalVL2 ]

View File

@ -0,0 +1,68 @@
# Copyright (C) 2022 NEC
# 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.
from tacker.common import log
from tacker.vnfm.mgmt_drivers import vnflcm_abstract_driver
class VnflcmMgmtNoop(vnflcm_abstract_driver.VnflcmMgmtAbstractDriver):
def get_type(self):
return 'vnflcm_noop'
def get_name(self):
return 'vnflcm_noop'
def get_description(self):
return 'Tacker VNFMgmt VnflcmNoop Driver'
@log.log
def instantiate_start(self, context, vnf_instance,
additional_params, **kwargs):
pass
@log.log
def instantiate_end(self, context, vnf_instance,
additional_params, **kwargs):
pass
@log.log
def terminate_start(self, context, vnf_instance,
additional_params, **kwargs):
pass
@log.log
def terminate_end(self, context, vnf_instance,
additional_params, **kwargs):
pass
@log.log
def scale_start(self, context, vnf_instance,
additional_params, **kwargs):
pass
@log.log
def scale_end(self, context, vnf_instance,
additional_params, **kwargs):
pass
@log.log
def heal_start(self, context, vnf_instance,
additional_params, **kwargs):
pass
@log.log
def heal_end(self, context, vnf_instance,
additional_params, **kwargs):
pass

View File

@ -0,0 +1,19 @@
configurable_properties:
_VAR_user: 'some_user'
_VAR_password: 'password'
_VAR_vdu_password: 'password'
vdus:
VDU1:
config:
order: 1
vm_app_config:
type: ansible
instantiation:
- path: _VAR_vnf_package_path/Scripts/complex/instantiation_end.yaml
params:
ansible_password: _VAR_password
order: 0
username: _VAR_user
password: _VAR_vdu_password

View File

@ -0,0 +1,10 @@
# This playbook prints a simple debug message
- name: Echo
hosts: 127.0.0.1
connection: local
tasks:
- name: Print debug message
debug:
msg: Complex INSTANTIATION END Hello, world!

View File

@ -0,0 +1,271 @@
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:
inputs:
id:
type: string
vendor:
type: string
version:
type: version
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:
implementation:
primary: ansible_driver
dependencies:
- mgmt-drivers-ansible-sample-end
terminate: []
terminate_start: []
terminate_end: []
artifacts:
ansible_driver:
description: Management driver plugin
type: tosca.artifacts.Implementation.Python
file: /opt/stack/tacker/tacker/vnfm/mgmt_drivers/ansible/ansible.py
mgmt-drivers-ansible-sample-end:
description: Management driver sample
type: tosca.artifacts.Implementation.Yaml
file: ScriptANSIBLE/config_complex_end.yaml
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.5.2'
checksum:
algorithm: sha-256
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
container_format: bare
disk_format: qcow2
min_disk: 1 GB
size: 1 GB
artifacts:
sw_image:
type: tosca.artifacts.nfv.SwImage
file: ../Files/images/cirros-0.5.2-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
VDU2:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU2
description: VDU2 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
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
requirements:
- virtual_storage: VirtualStorage
VirtualStorage:
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
properties:
virtual_block_storage_data:
size_of_storage: 30 GB
rdma_enabled: true
sw_image_data:
name: VrtualStorage
version: '0.5.2'
checksum:
algorithm: sha-256
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
container_format: bare
disk_format: qcow2
min_disk: 2 GB
min_ram: 8192 MB
size: 2 GB
artifacts:
sw_image:
type: tosca.artifacts.nfv.SwImage
file: ../Files/images/cirros-0.5.2-x86_64-disk.img
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
vnic_type: direct-physical
requirements:
- virtual_binding: VDU1
#- virtual_link: # the target node is determined in the NSD
CP2:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 1
requirements:
- virtual_binding: VDU1
- virtual_link: internalVL2
CP3:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 2
requirements:
- virtual_binding: VDU2
- 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
policies:
- scaling_aspects:
type: tosca.policies.nfv.ScalingAspects
properties:
aspects:
worker_instance:
name: worker_instance_aspect
description: worker_instance scaling aspect
max_scale_level: 2
step_deltas:
- delta_1
- VDU2_initial_delta:
type: tosca.policies.nfv.VduInitialDelta
properties:
initial_delta:
number_of_instances: 1
targets: [ VDU2 ]
- VDU2_scaling_aspect_deltas:
type: tosca.policies.nfv.VduScalingAspectDeltas
properties:
aspect: worker_instance
deltas:
delta_1:
number_of_instances: 1
targets: [ VDU2 ]
- instantiation_levels:
type: tosca.policies.nfv.InstantiationLevels
properties:
levels:
instantiation_level_1:
description: Smallest size
scale_info:
worker_instance:
scale_level: 0
instantiation_level_2:
description: Largest size
scale_info:
worker_instance:
scale_level: 2
default_level: instantiation_level_1
- VDU1_instantiation_levels:
type: tosca.policies.nfv.VduInstantiationLevels
properties:
levels:
instantiation_level_1:
number_of_instances: 1
instantiation_level_2:
number_of_instances: 3
targets: [ VDU1 ]
- VDU2_instantiation_levels:
type: tosca.policies.nfv.VduInstantiationLevels
properties:
levels:
instantiation_level_1:
number_of_instances: 1
instantiation_level_2:
number_of_instances: 1
targets: [ VDU2 ]
- internalVL2_instantiation_levels:
type: tosca.policies.nfv.VirtualLinkInstantiationLevels
properties:
levels:
instantiation_level_1:
bitrate_requirements:
root: 1048576
leaf: 1048576
instantiation_level_2:
bitrate_requirements:
root: 1048576
leaf: 1048576
targets: [ internalVL2 ]

View File

@ -0,0 +1,19 @@
configurable_properties:
_VAR_user: 'some_user'
_VAR_password: 'password'
_VAR_vdu_password: 'password'
vdus:
VDU1:
config:
order: 1
vm_app_config:
type: ansible
instantiation:
- path: _VAR_vnf_package_path/Scripts/complex/instantiation_end.yaml
params:
ansible_password: _VAR_password
order: 0
username: _VAR_user
password: _VAR_vdu_password

View File

@ -0,0 +1,10 @@
# This playbook prints a simple debug message
- name: Echo
hosts: 127.0.0.1
connection: local
tasks:
- name: Print debug message
debug:
msg: Complex INSTANTIATION END Hello, world!

View File

@ -258,3 +258,88 @@ class MgmtVnfLcmDriverTest(db_base.SqlTestCase):
vnf_instance_obj, vnf_dict,
instantiate_vnf_req_obj)
shutil.rmtree(fake_csar)
@mock.patch('tacker.vnflcm.utils.get_default_scale_status')
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
@mock.patch.object(VnfLcmDriver, '_init_mgmt_driver_hash')
@mock.patch.object(TackerManager, 'get_service_plugins',
return_value={'VNFM': FakeVNFMPlugin()})
@mock.patch.object(objects.VnfResource, 'create')
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id')
@mock.patch.object(objects.VnfInstance, "save")
def test_instantiate_multi(self, mock_vnf_instance_save,
mock_vnf_package_vnfd, mock_create,
mock_get_service_plugins, mock_init_hash,
mock_final_vnf_dict, mock_default_status):
mock_init_hash.return_value = {
"vnflcm_noop": "10edbecaa6df7e782c610ef4cc5e57"
"e2b0405869a559e2f4cb40e6b11e367547"
}
vnf_package_vnfd = fakes.return_vnf_package_vnfd()
vnf_package_id = vnf_package_vnfd.package_uuid
mock_vnf_package_vnfd.return_value = vnf_package_vnfd
instantiate_vnf_req_dict = fakes.get_dummy_instantiate_vnf_request()
instantiate_vnf_req_obj = \
objects.InstantiateVnfRequest.obj_from_primitive(
instantiate_vnf_req_dict, self.context)
vnf_instance_obj = fakes.return_vnf_instance()
mock_default_status.return_value = None
fake_csar = os.path.join(self.temp_dir, vnf_package_id)
cfg.CONF.set_override('vnf_package_csar_path', self.temp_dir,
group='vnf_package')
test_utils.copy_csar_files(fake_csar, "multi_flavour_deployment")
self._mock_vnf_manager()
driver = vnflcm_driver.VnfLcmDriver()
vnf_dict = {
"vnfd": {"attributes": {}}, "attributes": {},
"before_error_point": fields.ErrorPoint.VNF_CONFIG_START}
driver.instantiate_vnf(self.context, vnf_instance_obj, vnf_dict,
instantiate_vnf_req_obj)
self.assertEqual(1, mock_vnf_instance_save.call_count)
self.assertEqual(6, self._vnf_manager.invoke.call_count)
shutil.rmtree(fake_csar)
@mock.patch('tacker.vnflcm.utils.get_default_scale_status')
@mock.patch('tacker.vnflcm.utils._make_final_vnf_dict')
@mock.patch.object(VnfLcmDriver, '_init_mgmt_driver_hash')
@mock.patch.object(TackerManager, 'get_service_plugins',
return_value={'VNFM': FakeVNFMPlugin()})
@mock.patch.object(objects.VnfResource, 'create')
@mock.patch.object(objects.VnfPackageVnfd, 'get_by_id')
@mock.patch.object(objects.VnfInstance, "save")
def test_instantiate_multi_invalid(self, mock_vnf_instance_save,
mock_vnf_package_vnfd, mock_create,
mock_get_service_plugins, mock_init_hash,
mock_final_vnf_dict, mock_default_status):
mock_init_hash.return_value = {
"vnflcm_noop": "ffea638bfdbde3fb01f191bbe75b031859"
"b18d663b127100eb72b19eecd7ed51"
}
vnf_package_vnfd = fakes.return_vnf_package_vnfd()
vnf_package_id = vnf_package_vnfd.package_uuid
mock_vnf_package_vnfd.return_value = vnf_package_vnfd
instantiate_vnf_req_dict = fakes.get_dummy_instantiate_vnf_request()
instantiate_vnf_req_obj = \
objects.InstantiateVnfRequest.obj_from_primitive(
instantiate_vnf_req_dict, self.context)
vnf_instance_obj = fakes.return_vnf_instance()
mock_default_status.return_value = None
fake_csar = os.path.join(self.temp_dir, vnf_package_id)
cfg.CONF.set_override('vnf_package_csar_path', self.temp_dir,
group='vnf_package')
test_utils.copy_csar_files(fake_csar,
"multi_flavour_deployment_invalid")
self._mock_vnf_manager()
driver = vnflcm_driver.VnfLcmDriver()
vnf_dict = {
"vnfd": {"attributes": {}}, "attributes": {},
"before_error_point": fields.ErrorPoint.VNF_CONFIG_START}
self.assertRaises(exceptions.MgmtDriverInconsistent,
driver.instantiate_vnf, self.context,
vnf_instance_obj, vnf_dict,
instantiate_vnf_req_obj)
shutil.rmtree(fake_csar)

View File

@ -458,15 +458,28 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
return hash_obj.hexdigest()
def _check_mgmt_driver(self, artifact_mgmt_driver, artifacts_value,
vnf_package_path):
vnf_package_path,
artifact_mgmt_driver_dependency=None):
# check implementation and artifacts exist in cfg.CONF.tacker
if artifact_mgmt_driver not in self._mgmt_driver_hash:
LOG.error('The {} specified in the VNFD '
'is inconsistent with the MgmtDriver in '
'the configuration file.'.format(artifact_mgmt_driver))
LOG.error('The management driver {} specified in the VNFD '
'at vnf package path {} is inconsistent with '
'the MgmtDriver in the configuration file {}.'
.format(artifact_mgmt_driver, vnf_package_path,
cfg.CONF.default_config_files))
raise exceptions.MgmtDriverInconsistent(
MgmtDriver=artifact_mgmt_driver)
if artifact_mgmt_driver_dependency is not None:
if artifact_mgmt_driver_dependency in self._mgmt_driver_hash:
LOG.error('The management driver dependencies {} specified in '
'the VNFD at vnf package path {} is inconsistent '
' with the MgmtDriver in the configuration file {}.'
.format(artifact_mgmt_driver, vnf_package_path,
cfg.CONF.default_config_files))
raise exceptions.MgmtDriverInconsistent(
MgmtDriver=artifact_mgmt_driver_dependency)
# check file content
pkg_mgmt_driver_path = os.path.join(vnf_package_path,
artifacts_value[artifact_mgmt_driver]['file'])
@ -497,8 +510,25 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
artifact_mgmt_driver = interfaces_vnflcm_value.get(
method_name).get('implementation')
if artifact_mgmt_driver:
tacker_mgmt_driver = self._check_mgmt_driver(
artifact_mgmt_driver, artifacts_value, vnf_package_path)
# TODO(w-juso): Dependencies are defined List type in OASIS.
# This function handles dependencies as a List type, however
# currently only a single parameter in List can be read.
# If necessary, we need to implement the ability to load
# multiple definitions.
if isinstance(artifact_mgmt_driver, dict):
primary = artifact_mgmt_driver.get('primary')
dependencies = artifact_mgmt_driver.get('dependencies')
if not isinstance(dependencies, list):
dependencies = [dependencies]
for dependency in dependencies:
tacker_mgmt_driver = self._check_mgmt_driver(
primary, artifacts_value,
vnf_package_path, dependency)
else:
tacker_mgmt_driver = self._check_mgmt_driver(
artifact_mgmt_driver, artifacts_value,
vnf_package_path)
return tacker_mgmt_driver