Implement SOL001 features to MgmtDriver
* Enable VNF vendors to customize configuration methods for applications via MgmtDriver * Load LCM interface from vnfd file * Call LCM methods from vnflcm_driver * Fix unitentional mgmt_calls in vnflcm_driver._scale_vnf_pre Note: * For UT, sqlalchemy is used, which calls functions in pymysql.py, so the dependency module PyMySQL needs to be added. * The previous implementation of ``cfg.CONF.tacker.infra_driver`` depends on the default config in legacy ``VNFMPlugin`` class in tacker/vnfm/plugin.py, so we need to fix this here. * Due to drop unitentional mgmt_calls, it makes compatibility breakage for some scale actions calls and third party driver support. This backward incompatibility was decided to keep since it is not long time since last change(Victoria release) Change-Id: Ib4ad3eb9e0a84d1a5e807d2e6004e6b2c02bf3cf
This commit is contained in:
parent
8a56f1ec53
commit
f88022cdc2
@ -94,6 +94,7 @@ pycadf==2.7.0
|
||||
pycparser==2.18
|
||||
Pygments==2.2.0
|
||||
pyinotify==0.9.6
|
||||
PyMySQL==0.10.1
|
||||
PyNaCl==1.2.1
|
||||
pyOpenSSL==17.5.0
|
||||
pyparsing==2.2.0
|
||||
|
@ -0,0 +1,10 @@
|
||||
---
|
||||
features:
|
||||
- |
|
||||
Enable VNF vendors to customize configuration methods
|
||||
for applications via MgmtDriver. These customizations
|
||||
are specified by "interface" definition in ETSI
|
||||
NFV-SOL001 v2.6.1. With MgmtDriver, users can execute
|
||||
preamble and postamble of the base LCM operation.
|
||||
Customization of LCM itself is not supported by
|
||||
MgmtDriver.
|
@ -50,6 +50,7 @@ kubernetes>=11.0.0 # Apache-2.0
|
||||
setuptools!=24.0.0,!=34.0.0,!=34.0.1,!=34.0.2,!=34.0.3,!=34.1.0,!=34.1.1,!=34.2.0,!=34.3.0,!=34.3.1,!=34.3.2,!=36.2.0,>=21.0.0 # PSF/ZPL
|
||||
tooz>=1.58.0 # Apache-2.0
|
||||
PyYAML>=5.1 # MIT
|
||||
PyMySQL>=0.10.1 # MIT
|
||||
|
||||
# Glance Store
|
||||
glance-store>=2.4.0 # Apache-2.0
|
||||
|
@ -61,6 +61,7 @@ tacker.tacker.vnfm.drivers =
|
||||
tacker.tacker.mgmt.drivers =
|
||||
noop = tacker.vnfm.mgmt_drivers.noop:VnfMgmtNoop
|
||||
openwrt = tacker.vnfm.mgmt_drivers.openwrt.openwrt:VnfMgmtOpenWRT
|
||||
vnflcm_noop = tacker.vnfm.mgmt_drivers.vnflcm_noop:VnflcmMgmtNoop
|
||||
tacker.tacker.monitor.drivers =
|
||||
ping = tacker.vnfm.monitor_drivers.ping.ping:VNFMonitorPing
|
||||
http_ping = tacker.vnfm.monitor_drivers.http_ping.http_ping:VNFMonitorHTTPPing
|
||||
@ -92,6 +93,7 @@ oslo.config.opts =
|
||||
tacker.vnfm.monitor_drivers.ping.ping = tacker.vnfm.monitor_drivers.ping.ping:config_opts
|
||||
tacker.vnfm.monitor_drivers.ceilometer.ceilometer = tacker.vnfm.monitor_drivers.ceilometer.ceilometer:config_opts
|
||||
tacker.vnfm.monitor_drivers.zabbix.zabbix = tacker.vnfm.monitor_drivers.zabbix.zabbix:config_opts
|
||||
tacker.vnflcm.vnflcm_drivers = tacker.vnflcm.vnflcm_drivers:config_opts
|
||||
tacker.alarm_receiver = tacker.alarm_receiver:config_opts
|
||||
tacker.plugins.fenix = tacker.plugins.fenix:config_opts
|
||||
|
||||
|
@ -376,3 +376,33 @@ class DBAccessError(TackerException):
|
||||
|
||||
class SeeOther(TackerException):
|
||||
code = 303
|
||||
|
||||
|
||||
class MgmtDriverHashMatchFailure(TackerException):
|
||||
message = _('The hash verification of VNF Package MgmtDriver '
|
||||
'and Tacker MgmtDriver does not match.')
|
||||
|
||||
|
||||
class MgmtDriverInconsistent(TackerException):
|
||||
message = _('The %(MgmtDriver)s specified in the VNFD is inconsistent '
|
||||
'with the MgmtDriver in the configuration file.')
|
||||
|
||||
|
||||
class MgmtDriverNotFound(TackerException):
|
||||
message = _('The %(param)s in the additionalParams does not exist.')
|
||||
|
||||
|
||||
class MgmtDriverParamInvalid(TackerException):
|
||||
message = _('The %(param)s in the additionalParams is invalid.')
|
||||
|
||||
|
||||
class MgmtDriverRemoteCommandError(TackerException):
|
||||
message = _('Failed to execute remote command.')
|
||||
|
||||
|
||||
class MgmtDriverRemoteCommandTimeOut(TackerException):
|
||||
message = _('The execution of the remote command timed out.')
|
||||
|
||||
|
||||
class MgmtDriverOtherError(TackerException):
|
||||
message = _('An error occurred in MgmtDriver: %(error_message)s.')
|
||||
|
@ -0,0 +1,269 @@
|
||||
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:
|
||||
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:
|
||||
# supporting only 'instantiate', 'terminate', 'modify'
|
||||
# not supporting LCM script, supporting only default LCM
|
||||
instantiate: []
|
||||
instantiate_start:
|
||||
implementation: vnflcm_noop
|
||||
instantiate_end:
|
||||
implementation: vnflcm_noop
|
||||
terminate: []
|
||||
terminate_start:
|
||||
implementation: vnflcm_noop
|
||||
terminate_end:
|
||||
implementation: vnflcm_noop
|
||||
artifacts:
|
||||
vnflcm_noop:
|
||||
description: Management driver instantiate
|
||||
type: tosca.artifacts.Implementation.Python
|
||||
file: Drivers/vnflcm_noop.py
|
||||
|
||||
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:
|
||||
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
|
||||
|
||||
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.4.0'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d
|
||||
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.4.0-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 ]
|
@ -0,0 +1,65 @@
|
||||
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:
|
||||
id:
|
||||
type: string
|
||||
description: ID of this VNF
|
||||
default: vnf_id
|
||||
vendor:
|
||||
type: string
|
||||
description: name of the vendor who generate this VNF
|
||||
default: vendor
|
||||
version:
|
||||
type: version
|
||||
description: version of the software for this VNF
|
||||
default: 1.0
|
||||
descriptor_id:
|
||||
type: string
|
||||
constraints: [ valid_values: [ b1bb0ce7-ebca-4fa7-95ed-4840d7000000 ] ]
|
||||
default: b1bb0ce7-ebca-4fa7-95ed-4840d7000000
|
||||
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
|
@ -0,0 +1,68 @@
|
||||
# Copyright (C) 2020 FUJITSU
|
||||
# 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
|
@ -0,0 +1,269 @@
|
||||
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:
|
||||
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:
|
||||
# supporting only 'instantiate', 'terminate', 'modify'
|
||||
# not supporting LCM script, supporting only default LCM
|
||||
instantiate: []
|
||||
instantiate_start:
|
||||
implementation: vnflcm_noop_false
|
||||
instantiate_end:
|
||||
implementation: vnflcm_noop_false
|
||||
terminate: []
|
||||
terminate_start:
|
||||
implementation: vnflcm_noop_false
|
||||
terminate_end:
|
||||
implementation: vnflcm_noop_false
|
||||
artifacts:
|
||||
vnflcm_noop:
|
||||
description: Management driver instantiate
|
||||
type: tosca.artifacts.Implementation.Python
|
||||
file: Drivers/vnflcm_noop_false.py
|
||||
|
||||
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:
|
||||
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
|
||||
|
||||
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.4.0'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d
|
||||
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.4.0-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 ]
|
@ -0,0 +1,88 @@
|
||||
# Copyright (C) 2020 FUJITSU
|
||||
# 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 oslo_log import log as logging
|
||||
|
||||
from tacker.vnfm.mgmt_drivers import vnflcm_abstract_driver
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
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'
|
||||
|
||||
def instantiate_start(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('instantiate_start %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def instantiate_end(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('instantiate_end %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def terminate_start(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('terminate_start %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def terminate_end(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('terminate_end %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def scale_start(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('scale_start %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def scale_end(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('scale_end %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def heal_start(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('heal_start %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def heal_end(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('heal_end %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
@ -0,0 +1,269 @@
|
||||
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:
|
||||
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:
|
||||
# supporting only 'instantiate', 'terminate', 'modify'
|
||||
# not supporting LCM script, supporting only default LCM
|
||||
instantiate: []
|
||||
instantiate_start:
|
||||
implementation: vnflcm_noop
|
||||
instantiate_end:
|
||||
implementation: vnflcm_noop
|
||||
terminate: []
|
||||
terminate_start:
|
||||
implementation: vnflcm_noop
|
||||
terminate_end:
|
||||
implementation: vnflcm_noop
|
||||
artifacts:
|
||||
vnflcm_noop:
|
||||
description: Management driver instantiate
|
||||
type: tosca.artifacts.Implementation.Python
|
||||
file: Drivers/vnflcm_noop.py
|
||||
|
||||
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:
|
||||
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
|
||||
|
||||
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.4.0'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d
|
||||
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.4.0-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 ]
|
@ -0,0 +1,81 @@
|
||||
# Copyright (C) 2020 FUJITSU
|
||||
# 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 oslo_log import log as logging
|
||||
|
||||
from tacker.vnfm.mgmt_drivers import vnflcm_abstract_driver
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VnflcmMgmtNoop(vnflcm_abstract_driver.VnflcmMgmtAbstractDriver):
|
||||
|
||||
# instantiate start
|
||||
def instantiate_start(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('instantiate_start %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def instantiate_end(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('instantiate_end %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def terminate_start(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('terminate_start %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def terminate_end(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('terminate_end %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def scale_start(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('scale_start %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def scale_end(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('scale_end %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def heal_start(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('heal_start %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
||||
|
||||
def heal_end(self, vnf_instance, additional_params, **kwargs):
|
||||
LOG.debug('heal_end %(vnf_instance)s '
|
||||
'%(additional_params)s %(kwargs)s',
|
||||
{'vnf_instance': vnf_instance,
|
||||
'additional_params': additional_params, 'kwargs': kwargs})
|
||||
pass
|
@ -0,0 +1,206 @@
|
||||
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: []
|
||||
terminate: []
|
||||
terminate_start: []
|
||||
terminate_end: []
|
||||
instantiate_start:
|
||||
implementation: vnflcm_noop
|
||||
instantiate_end:
|
||||
implementation: vnflcm_noop
|
||||
artifacts:
|
||||
vnflcm_noop:
|
||||
description: Management driver for vnflcm_noop
|
||||
type: tosca.artifacts.Implementation.Python
|
||||
file: Scripts/vnflcm_noop.py
|
||||
|
||||
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: 3
|
||||
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
virtual_memory:
|
||||
virtual_mem_size: 512 MB
|
||||
virtual_cpu:
|
||||
num_virtual_cpu: 1
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 3 GB
|
||||
requirements:
|
||||
- virtual_storage: VirtualStorage
|
||||
|
||||
VirtualStorage:
|
||||
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
||||
properties:
|
||||
virtual_block_storage_data:
|
||||
size_of_storage: 3 GB
|
||||
rdma_enabled: true
|
||||
sw_image_data:
|
||||
name: VirtualStorage
|
||||
version: '0.4.0'
|
||||
checksum:
|
||||
algorithm: sha-512
|
||||
hash: 6513f21e44aa3da349f248188a44bc304a3653a04122d8fb4535423c8e1d14cd6a153f735bb0982e2161b5b5186106570c17a9e58b64dd39390617cd5a350f78
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 2 GB
|
||||
min_ram: 256 MB
|
||||
size: 1 GB
|
||||
artifacts:
|
||||
sw_image:
|
||||
type: tosca.artifacts.nfv.SwImage
|
||||
file: ../Files/images/cirros-0.4.0-x86_64-disk.img
|
||||
|
||||
CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
properties:
|
||||
layer_protocols: [ ipv4 ]
|
||||
order: 2
|
||||
requirements:
|
||||
- virtual_binding: VDU1
|
||||
- virtual_link: internalVL1
|
||||
|
||||
internalVL1:
|
||||
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: 33.33.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
|
||||
|
||||
- VDU1_initial_delta:
|
||||
type: tosca.policies.nfv.VduInitialDelta
|
||||
properties:
|
||||
initial_delta:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- VDU1_scaling_aspect_deltas:
|
||||
type: tosca.policies.nfv.VduScalingAspectDeltas
|
||||
properties:
|
||||
aspect: worker_instance
|
||||
deltas:
|
||||
delta_1:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- 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 ]
|
||||
|
||||
- VDU1_instantiation_levels:
|
||||
type: tosca.policies.nfv.VduInstantiationLevels
|
||||
properties:
|
||||
levels:
|
||||
instantiation_level_1:
|
||||
number_of_instances: 1
|
||||
instantiation_level_2:
|
||||
number_of_instances: 1
|
||||
targets: [ VDU1 ]
|
||||
|
||||
- internalVL1_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: [ internalVL1 ]
|
@ -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-4840d7000000
|
||||
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
|
@ -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-4840d7000000 ] ]
|
||||
default: b1bb0ce7-ebca-4fa7-95ed-4840d7000000
|
||||
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: "falvour"
|
||||
requirements:
|
||||
- virtual_link_external:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
- virtual_link_internal:
|
||||
capability: tosca.capabilities.nfv.VirtualLinkable
|
||||
interfaces:
|
||||
Vnflcm:
|
||||
type: tosca.interfaces.nfv.Vnflcm
|
@ -0,0 +1,68 @@
|
||||
# Copyright (C) 2020 FUJITSU
|
||||
# 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
|
@ -0,0 +1,12 @@
|
||||
TOSCA-Meta-File-Version: 1.0
|
||||
Created-by: dummy_user
|
||||
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
|
||||
|
||||
Name: Scripts/vnflcm_noop.py
|
||||
Content-Type: text/x-python
|
||||
Algorithm: SHA-256
|
||||
Hash: ffea638bfdbde3fb01f191bbe75b031859b18d663b127100eb72b19eecd7ed51
|
294
tacker/tests/functional/sol/vnflcm/test_vnflcm_noop.py
Normal file
294
tacker/tests/functional/sol/vnflcm/test_vnflcm_noop.py
Normal file
@ -0,0 +1,294 @@
|
||||
# Copyright (C) 2020 FUJITSU
|
||||
# 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.
|
||||
|
||||
import os
|
||||
import time
|
||||
|
||||
from oslo_serialization import jsonutils
|
||||
from oslo_utils import uuidutils
|
||||
from sqlalchemy import desc
|
||||
from sqlalchemy.orm import joinedload
|
||||
|
||||
from tacker.common import exceptions
|
||||
from tacker import context as t_context
|
||||
from tacker.db import api as db_api
|
||||
from tacker.db.db_sqlalchemy import api
|
||||
from tacker.db.db_sqlalchemy import models
|
||||
from tacker.objects import fields
|
||||
from tacker.tests.functional import base
|
||||
from tacker.tests import utils
|
||||
|
||||
VNF_PACKAGE_UPLOAD_TIMEOUT = 300
|
||||
VNF_INSTANTIATE_TIMEOUT = 600
|
||||
VNF_TERMINATE_TIMEOUT = 600
|
||||
VNF_HEAL_TIMEOUT = 600
|
||||
RETRY_WAIT_TIME = 5
|
||||
|
||||
|
||||
def _create_and_upload_vnf_package(tacker_client, csar_package_name,
|
||||
user_defined_data):
|
||||
# create vnf package
|
||||
body = jsonutils.dumps({"userDefinedData": user_defined_data})
|
||||
resp, vnf_package = tacker_client.do_request(
|
||||
'/vnfpkgm/v1/vnf_packages', "POST", body=body)
|
||||
|
||||
# upload vnf package
|
||||
csar_package_path = "../../../etc/samples/etsi/nfv/%s" % csar_package_name
|
||||
file_path = os.path.abspath(os.path.join(os.path.dirname(__file__),
|
||||
csar_package_path))
|
||||
|
||||
# Generating unique vnfd id. This is required when multiple workers
|
||||
# are running concurrently. The call below creates a new temporary
|
||||
# CSAR with unique vnfd id.
|
||||
file_path, uniqueid = utils.create_csar_with_unique_vnfd_id(file_path)
|
||||
|
||||
with open(file_path, 'rb') as file_object:
|
||||
resp, resp_body = tacker_client.do_request(
|
||||
'/vnfpkgm/v1/vnf_packages/{id}/package_content'.format(
|
||||
id=vnf_package['id']),
|
||||
"PUT", body=file_object, content_type='application/zip')
|
||||
|
||||
# wait for onboard
|
||||
timeout = VNF_PACKAGE_UPLOAD_TIMEOUT
|
||||
start_time = int(time.time())
|
||||
show_url = os.path.join('/vnfpkgm/v1/vnf_packages', vnf_package['id'])
|
||||
vnfd_id = None
|
||||
while True:
|
||||
resp, body = tacker_client.do_request(show_url, "GET")
|
||||
if body['onboardingState'] == "ONBOARDED":
|
||||
vnfd_id = body['vnfdId']
|
||||
break
|
||||
|
||||
if ((int(time.time()) - start_time) > timeout):
|
||||
raise Exception("Failed to onboard vnf package")
|
||||
|
||||
time.sleep(1)
|
||||
|
||||
# remove temporarily created CSAR file
|
||||
os.remove(file_path)
|
||||
return vnf_package['id'], vnfd_id
|
||||
|
||||
|
||||
class VnfLcmTest(base.BaseTackerTest):
|
||||
|
||||
@classmethod
|
||||
def setUpClass(cls):
|
||||
cls.tacker_client = base.BaseTackerTest.tacker_http_client()
|
||||
|
||||
cls.vnf_package, cls.vnfd_id = \
|
||||
_create_and_upload_vnf_package(
|
||||
cls.tacker_client, "test_inst_terminate_vnf_with_vnflcmnoop",
|
||||
{"key": "file_functional"})
|
||||
|
||||
super(VnfLcmTest, cls).setUpClass()
|
||||
|
||||
@classmethod
|
||||
def tearDownClass(cls):
|
||||
# Update vnf package operational state to DISABLED
|
||||
update_req_body = jsonutils.dumps({
|
||||
"operationalState": "DISABLED"})
|
||||
base_path = "/vnfpkgm/v1/vnf_packages"
|
||||
for package_id in [cls.vnf_package]:
|
||||
resp, resp_body = cls.tacker_client.do_request(
|
||||
'{base_path}/{id}'.format(id=package_id,
|
||||
base_path=base_path),
|
||||
"PATCH", content_type='application/json',
|
||||
body=update_req_body)
|
||||
|
||||
# Delete vnf package
|
||||
url = '/vnfpkgm/v1/vnf_packages/%s' % package_id
|
||||
cls.tacker_client.do_request(url, "DELETE")
|
||||
|
||||
super(VnfLcmTest, cls).tearDownClass()
|
||||
|
||||
def setUp(self):
|
||||
super(VnfLcmTest, self).setUp()
|
||||
self.base_url = "/vnflcm/v1/vnf_instances"
|
||||
self.context = t_context.get_admin_context()
|
||||
|
||||
vim_list = self.client.list_vims()
|
||||
if not vim_list:
|
||||
self.skipTest("Vims are not configured")
|
||||
|
||||
vim_id = 'VIM0'
|
||||
vim = self.get_vim(vim_list, vim_id)
|
||||
if not vim:
|
||||
self.skipTest("Openstack VIM '%s' is missing" % vim_id)
|
||||
self.vim_id = vim['id']
|
||||
|
||||
def _instantiate_vnf_instance_request(
|
||||
self, flavour_id, vim_id=None, additional_param=None):
|
||||
request_body = {"flavourId": flavour_id}
|
||||
|
||||
if vim_id:
|
||||
request_body["vimConnectionInfo"] = [
|
||||
{"id": uuidutils.generate_uuid(),
|
||||
"vimId": vim_id,
|
||||
"vimType": "openstack"}]
|
||||
|
||||
if additional_param:
|
||||
request_body["additionalParams"] = additional_param
|
||||
|
||||
return request_body
|
||||
|
||||
def _create_vnf_instance(self, vnfd_id, vnf_instance_name=None,
|
||||
vnf_instance_description=None):
|
||||
request_body = {'vnfdId': vnfd_id}
|
||||
if vnf_instance_name:
|
||||
request_body['vnfInstanceName'] = vnf_instance_name
|
||||
|
||||
if vnf_instance_description:
|
||||
request_body['vnfInstanceDescription'] = vnf_instance_description
|
||||
|
||||
resp, response_body = self.http_client.do_request(
|
||||
self.base_url, "POST", body=jsonutils.dumps(request_body))
|
||||
return resp, response_body
|
||||
|
||||
def _delete_wait_vnf_instance(self, id):
|
||||
timeout = VNF_TERMINATE_TIMEOUT
|
||||
url = os.path.join(self.base_url, id)
|
||||
start_time = int(time.time())
|
||||
while True:
|
||||
resp, body = self.http_client.do_request(url, "DELETE")
|
||||
if 204 == resp.status_code:
|
||||
break
|
||||
|
||||
if ((int(time.time()) - start_time) > timeout):
|
||||
error = "Failed to delete vnf instance %s"
|
||||
self.fail(error % id)
|
||||
|
||||
time.sleep(RETRY_WAIT_TIME)
|
||||
|
||||
def _delete_vnf_instance(self, id):
|
||||
self._delete_wait_vnf_instance(id)
|
||||
|
||||
# verify vnf instance is deleted
|
||||
url = os.path.join(self.base_url, id)
|
||||
resp, body = self.http_client.do_request(url, "GET")
|
||||
self.assertEqual(404, resp.status_code)
|
||||
|
||||
def _show_vnf_instance(self, id, expected_result=None):
|
||||
show_url = os.path.join(self.base_url, id)
|
||||
resp, vnf_instance = self.http_client.do_request(show_url, "GET")
|
||||
self.assertEqual(200, resp.status_code)
|
||||
|
||||
if expected_result:
|
||||
self.assertDictSupersetOf(expected_result, vnf_instance)
|
||||
|
||||
return vnf_instance
|
||||
|
||||
def _vnf_instance_wait(
|
||||
self, id,
|
||||
instantiation_state=fields.VnfInstanceState.INSTANTIATED,
|
||||
timeout=VNF_INSTANTIATE_TIMEOUT):
|
||||
show_url = os.path.join(self.base_url, id)
|
||||
start_time = int(time.time())
|
||||
while True:
|
||||
resp, body = self.http_client.do_request(show_url, "GET")
|
||||
if body['instantiationState'] == instantiation_state:
|
||||
break
|
||||
|
||||
if ((int(time.time()) - start_time) > timeout):
|
||||
error = ("Vnf instance %(id)s status is %(current)s, "
|
||||
"expected status should be %(expected)s")
|
||||
self.fail(error % {"id": id,
|
||||
"current": body['instantiationState'],
|
||||
"expected": instantiation_state})
|
||||
|
||||
time.sleep(RETRY_WAIT_TIME)
|
||||
|
||||
def _instantiate_vnf_instance(self, id, request_body):
|
||||
url = os.path.join(self.base_url, id, "instantiate")
|
||||
resp, body = self.http_client.do_request(
|
||||
url, "POST", body=jsonutils.dumps(request_body))
|
||||
self.assertEqual(202, resp.status_code)
|
||||
self._vnf_instance_wait(id)
|
||||
|
||||
def _terminate_vnf_instance(self, id, request_body):
|
||||
url = os.path.join(self.base_url, id, "terminate")
|
||||
resp, body = self.http_client.do_request(
|
||||
url, "POST", body=jsonutils.dumps(request_body))
|
||||
self.assertEqual(202, resp.status_code)
|
||||
|
||||
timeout = request_body.get('gracefulTerminationTimeout')
|
||||
start_time = int(time.time())
|
||||
|
||||
self._vnf_instance_wait(
|
||||
id, instantiation_state=fields.VnfInstanceState.NOT_INSTANTIATED,
|
||||
timeout=VNF_TERMINATE_TIMEOUT)
|
||||
|
||||
# If gracefulTerminationTimeout is set, check whether vnf
|
||||
# instantiation_state is set to NOT_INSTANTIATED after
|
||||
# gracefulTerminationTimeout seconds.
|
||||
if timeout and int(time.time()) - start_time < timeout:
|
||||
self.fail("Vnf is terminated before graceful termination "
|
||||
"timeout period")
|
||||
|
||||
@db_api.context_manager.reader
|
||||
def _vnf_notify_get_by_id(self, context, vnf_instance_id,
|
||||
columns_to_join=None):
|
||||
query = api.model_query(
|
||||
context, models.VnfLcmOpOccs,
|
||||
read_deleted="no", project_only=True).filter_by(
|
||||
vnf_instance_id=vnf_instance_id).order_by(
|
||||
desc("created_at"))
|
||||
|
||||
if columns_to_join:
|
||||
for column in columns_to_join:
|
||||
query = query.options(joinedload(column))
|
||||
|
||||
result = query.first()
|
||||
|
||||
if not result:
|
||||
raise exceptions.VnfInstanceNotFound(id=vnf_instance_id)
|
||||
|
||||
return result
|
||||
|
||||
def test_instantiate_terminate_vnf_with_vnflcmnoop(self):
|
||||
# create vnf instance
|
||||
vnf_instance_name = "vnf_with_instantiation_level-%s" % \
|
||||
uuidutils.generate_uuid()
|
||||
vnf_instance_description = "vnf with instantiation level 1"
|
||||
resp, vnf_instance = self._create_vnf_instance(
|
||||
self.vnfd_id,
|
||||
vnf_instance_name=vnf_instance_name,
|
||||
vnf_instance_description=vnf_instance_description)
|
||||
self.assertIsNotNone(vnf_instance['id'])
|
||||
self.assertEqual(201, resp.status_code)
|
||||
# instantiate vnf instance
|
||||
request_body = self._instantiate_vnf_instance_request(
|
||||
"simple", vim_id=self.vim_id)
|
||||
self._instantiate_vnf_instance(vnf_instance['id'], request_body)
|
||||
time.sleep(20)
|
||||
# show vnf instance
|
||||
vnf_instance = self._show_vnf_instance(vnf_instance['id'])
|
||||
self.assertEqual(vnf_instance['instantiationState'], 'INSTANTIATED')
|
||||
vnflcm_op_occ_ins = self._vnf_notify_get_by_id(
|
||||
self.context, vnf_instance['id'], columns_to_join=None)
|
||||
self.assertEqual(vnflcm_op_occ_ins.operation_state, 'COMPLETED')
|
||||
self.assertEqual(vnflcm_op_occ_ins.operation, 'INSTANTIATE')
|
||||
time.sleep(20)
|
||||
# terminate vnf instance
|
||||
terminate_req_body = {
|
||||
"terminationType": fields.VnfInstanceTerminationType.FORCEFUL,
|
||||
}
|
||||
self._terminate_vnf_instance(vnf_instance['id'], terminate_req_body)
|
||||
time.sleep(20)
|
||||
vnflcm_op_occ_term = self._vnf_notify_get_by_id(
|
||||
self.context, vnf_instance['id'], columns_to_join=None)
|
||||
self.assertEqual(vnflcm_op_occ_term.operation_state, 'COMPLETED')
|
||||
self.assertEqual(vnflcm_op_occ_term.operation, 'TERMINATE')
|
||||
# delete vnf instance
|
||||
self._delete_vnf_instance(vnf_instance['id'])
|
@ -39,6 +39,11 @@ import tacker.conf
|
||||
CONF = tacker.conf.CONF
|
||||
|
||||
|
||||
def return_vnf_interfaces():
|
||||
vnf_interface = 'vnflcm_noop'
|
||||
return vnf_interface
|
||||
|
||||
|
||||
def return_default_vim():
|
||||
default_vim = {
|
||||
'vim_auth': {
|
||||
|
248
tacker/tests/unit/vnflcm/test_load_vnf_interfaces.py
Normal file
248
tacker/tests/unit/vnflcm/test_load_vnf_interfaces.py
Normal file
@ -0,0 +1,248 @@
|
||||
# Copyright (C) 2020 FUJITSU
|
||||
# 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.
|
||||
|
||||
|
||||
import fixtures
|
||||
import os
|
||||
import shutil
|
||||
|
||||
from oslo_config import cfg
|
||||
from oslo_utils import uuidutils
|
||||
|
||||
from tacker.common import exceptions
|
||||
from tacker import context
|
||||
from tacker.manager import TackerManager
|
||||
from tacker import objects
|
||||
from tacker.tests.unit.db import base as db_base
|
||||
from tacker.tests.unit.nfvo.test_nfvo_plugin import FakeVNFMPlugin
|
||||
from tacker.tests.unit.vnflcm import fakes
|
||||
from tacker.tests import utils as test_utils
|
||||
from tacker.tests import uuidsentinel
|
||||
from tacker.vnflcm import vnflcm_driver
|
||||
from tacker.vnflcm.vnflcm_driver import VnfLcmDriver
|
||||
from unittest import mock
|
||||
|
||||
|
||||
vnf_dict = {
|
||||
'id': uuidutils.generate_uuid(),
|
||||
'mgmt_ip_address': '{"VDU1": "a.b.c.d"}',
|
||||
'vim_id': '6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
'instance_id': 'a737497c-761c-11e5-89c3-9cb6541d805d',
|
||||
'vnfd': {
|
||||
'attributes': {
|
||||
'heat_template': {
|
||||
'resources': {
|
||||
'VDU1': {
|
||||
'properties': {
|
||||
'networks': [{'port': {'get_resource': 'CP1'}}]}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
class InfraDriverException(Exception):
|
||||
pass
|
||||
|
||||
|
||||
class FakeDriverManager(mock.Mock):
|
||||
def __init__(self, fail_method_name=None, vnf_resource_count=1):
|
||||
super(FakeDriverManager, self).__init__()
|
||||
self.fail_method_name = fail_method_name
|
||||
self.vnf_resource_count = vnf_resource_count
|
||||
|
||||
def invoke(self, *args, **kwargs):
|
||||
if 'pre_instantiation_vnf' in args:
|
||||
vnf_resource_list = [fakes.return_vnf_resource() for index in
|
||||
range(self.vnf_resource_count)]
|
||||
return {'node_name': vnf_resource_list}
|
||||
if 'instantiate_vnf' in args:
|
||||
if self.fail_method_name and \
|
||||
self.fail_method_name == 'instantiate_vnf':
|
||||
raise InfraDriverException("instantiate_vnf failed")
|
||||
|
||||
instance_id = uuidsentinel.instance_id
|
||||
vnfd_dict = kwargs.get('vnfd_dict')
|
||||
vnfd_dict['instance_id'] = instance_id
|
||||
return instance_id
|
||||
if 'create_wait' in args:
|
||||
if self.fail_method_name and \
|
||||
self.fail_method_name == 'create_wait':
|
||||
raise InfraDriverException("create_wait failed")
|
||||
elif 'post_vnf_instantiation' in args:
|
||||
pass
|
||||
if 'mgmt-drivers-custom' in args:
|
||||
if self.fail_method_name and \
|
||||
self.fail_method_name == 'mgmt-drivers-custom':
|
||||
raise InfraDriverException("mgmt-drivers-custom failed")
|
||||
|
||||
|
||||
class FakeVimClient(mock.Mock):
|
||||
pass
|
||||
|
||||
|
||||
class FakeTackerManager(mock.MagicMock):
|
||||
pass
|
||||
|
||||
|
||||
class MgmtVnfLcmDriverTest(db_base.SqlTestCase):
|
||||
|
||||
def setUp(self):
|
||||
super(MgmtVnfLcmDriverTest, self).setUp()
|
||||
self.addCleanup(mock.patch.stopall)
|
||||
self.context = context.get_admin_context()
|
||||
self._mock_vim_client()
|
||||
self._stub_get_vim()
|
||||
self.temp_dir = self.useFixture(fixtures.TempDir()).path
|
||||
|
||||
def _mock_vnf_manager(self, fail_method_name=None, vnf_resource_count=1):
|
||||
self._vnf_manager = mock.Mock(wraps=FakeDriverManager(
|
||||
fail_method_name=fail_method_name,
|
||||
vnf_resource_count=vnf_resource_count))
|
||||
self._vnf_manager.__contains__ = mock.Mock(
|
||||
return_value=True)
|
||||
fake_vnf_manager = mock.Mock()
|
||||
fake_vnf_manager.return_value = self._vnf_manager
|
||||
self._mock(
|
||||
'tacker.common.driver_manager.DriverManager', fake_vnf_manager)
|
||||
|
||||
def _mock_vim_client(self):
|
||||
self.vim_client = mock.Mock(wraps=FakeVimClient())
|
||||
fake_vim_client = mock.Mock()
|
||||
fake_vim_client.return_value = self.vim_client
|
||||
self._mock(
|
||||
'tacker.vnfm.vim_client.VimClient', fake_vim_client)
|
||||
|
||||
def _stub_get_vim(self):
|
||||
vim_obj = {'vim_id': '6261579e-d6f3-49ad-8bc3-a9cb974778ff',
|
||||
'vim_name': 'fake_vim', 'vim_auth':
|
||||
{'auth_url': 'http://localhost/identity', 'password':
|
||||
'test_pw', 'username': 'test_user', 'project_name':
|
||||
'test_project'}, 'vim_type': 'openstack'}
|
||||
self.vim_client.get_vim.return_value = vim_obj
|
||||
|
||||
@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_vnf(self, mock_vnf_instance_save,
|
||||
mock_vnf_package_vnfd, mock_create,
|
||||
mock_get_service_plugins, mock_init_hash,
|
||||
mock_final_vnf_dict):
|
||||
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()
|
||||
|
||||
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, "refactor_mgmt_driver1")
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
vnf_dict = {"vnfd": {"attributes": {}}, "attributes": {}}
|
||||
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(5, self._vnf_manager.invoke.call_count)
|
||||
shutil.rmtree(fake_csar)
|
||||
|
||||
@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_vnf_py_name_false(
|
||||
self, mock_vnf_instance_save, mock_vnf_package_vnfd,
|
||||
mock_create, mock_get_service_plugins, mock_init_hash,
|
||||
mock_final_vnf_dict):
|
||||
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()
|
||||
|
||||
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, "refactor_mgmt_driver2")
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
vnf_dict = {"vnfd": {"attributes": {}}, "attributes": {}}
|
||||
self.assertRaises(exceptions.MgmtDriverInconsistent,
|
||||
driver.instantiate_vnf, self.context,
|
||||
vnf_instance_obj, vnf_dict,
|
||||
instantiate_vnf_req_obj)
|
||||
shutil.rmtree(fake_csar)
|
||||
|
||||
@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_vnf_py_hash_false(
|
||||
self, mock_vnf_instance_save, mock_vnf_package_vnfd,
|
||||
mock_create, mock_get_service_plugins, mock_init_hash,
|
||||
mock_final_vnf_dict):
|
||||
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()
|
||||
|
||||
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, "refactor_mgmt_driver3")
|
||||
self._mock_vnf_manager()
|
||||
driver = vnflcm_driver.VnfLcmDriver()
|
||||
vnf_dict = {"vnfd": {"attributes": {}}, "attributes": {}}
|
||||
self.assertRaises(exceptions.MgmtDriverHashMatchFailure,
|
||||
driver.instantiate_vnf, self.context,
|
||||
vnf_instance_obj, vnf_dict,
|
||||
instantiate_vnf_req_obj)
|
||||
shutil.rmtree(fake_csar)
|
File diff suppressed because it is too large
Load Diff
@ -16,7 +16,9 @@
|
||||
import copy
|
||||
from datetime import datetime
|
||||
import functools
|
||||
import hashlib
|
||||
import inspect
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import traceback
|
||||
@ -28,10 +30,9 @@ from oslo_serialization import jsonutils
|
||||
from oslo_utils import encodeutils
|
||||
from oslo_utils import excutils
|
||||
|
||||
from tacker.common import log
|
||||
|
||||
from tacker.common import driver_manager
|
||||
from tacker.common import exceptions
|
||||
from tacker.common import log
|
||||
from tacker.common import safe_utils
|
||||
from tacker.common import utils
|
||||
from tacker.conductor.conductorrpc import vnf_lcm_rpc
|
||||
@ -40,10 +41,10 @@ from tacker import objects
|
||||
from tacker.objects import fields
|
||||
from tacker.vnflcm import abstract_driver
|
||||
from tacker.vnflcm import utils as vnflcm_utils
|
||||
from tacker.vnfm.mgmt_drivers import constants as mgmt_constants
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
CONF = cfg.CONF
|
||||
DEFAULT_VNFLCM_MGMT_DRIVER = "vnflcm_noop"
|
||||
|
||||
|
||||
@utils.expects_func_args('vnf_info', 'vnf_instance', 'scale_vnf_request')
|
||||
@ -281,7 +282,24 @@ def revert_to_error_rollback(function):
|
||||
return decorated_function
|
||||
|
||||
|
||||
def config_opts():
|
||||
return [('tacker', VnfLcmDriver.OPTS)]
|
||||
|
||||
|
||||
class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
OPTS = [
|
||||
cfg.ListOpt(
|
||||
'vnflcm_infra_driver', default=['openstack', 'kubernetes'],
|
||||
help=_('Hosting vnf drivers tacker plugin will use')
|
||||
),
|
||||
cfg.ListOpt(
|
||||
'vnflcm_mgmt_driver', default=[DEFAULT_VNFLCM_MGMT_DRIVER],
|
||||
help=_('MGMT driver to communicate with '
|
||||
'Hosting VNF/logical service '
|
||||
'instance tacker plugin will use')
|
||||
)
|
||||
]
|
||||
cfg.CONF.register_opts(OPTS, 'tacker')
|
||||
|
||||
def __init__(self):
|
||||
super(VnfLcmDriver, self).__init__()
|
||||
@ -289,7 +307,18 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
self._vnfm_plugin = manager.TackerManager.get_service_plugins()['VNFM']
|
||||
self._vnf_manager = driver_manager.DriverManager(
|
||||
'tacker.tacker.vnfm.drivers',
|
||||
cfg.CONF.tacker.infra_driver)
|
||||
cfg.CONF.tacker.vnflcm_infra_driver)
|
||||
self._mgmt_manager = driver_manager.DriverManager(
|
||||
'tacker.tacker.mgmt.drivers', cfg.CONF.tacker.vnflcm_mgmt_driver)
|
||||
self._mgmt_driver_hash = self._init_mgmt_driver_hash()
|
||||
|
||||
def _init_mgmt_driver_hash(self):
|
||||
|
||||
driver_hash = {}
|
||||
for mgmt_driver in cfg.CONF.tacker.vnflcm_mgmt_driver:
|
||||
path = inspect.getfile(self._mgmt_manager[mgmt_driver].__class__)
|
||||
driver_hash[mgmt_driver] = self._get_file_hash(path)
|
||||
return driver_hash
|
||||
|
||||
def _vnf_instance_update(self, context, vnf_instance, **kwargs):
|
||||
"""Update vnf instance in the database using kwargs as value."""
|
||||
@ -377,6 +406,57 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
id=vnf_instance.id,
|
||||
error=encodeutils.exception_to_unicode(exp))
|
||||
|
||||
def _get_file_hash(self, path):
|
||||
hash_obj = hashlib.sha256()
|
||||
with open(path) as f:
|
||||
hash_obj.update(f.read().encode('utf-8'))
|
||||
return hash_obj.hexdigest()
|
||||
|
||||
def _check_mgmt_driver(self, artifact_mgmt_driver, artifacts_value,
|
||||
vnf_package_path):
|
||||
# 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))
|
||||
raise exceptions.MgmtDriverInconsistent(
|
||||
MgmtDriver=artifact_mgmt_driver)
|
||||
|
||||
# check file content
|
||||
pkg_mgmt_driver_path = os.path.join(vnf_package_path,
|
||||
artifacts_value[artifact_mgmt_driver]['file'])
|
||||
pkg_mgmt_driver_hash = self._get_file_hash(pkg_mgmt_driver_path)
|
||||
if pkg_mgmt_driver_hash == \
|
||||
self._mgmt_driver_hash[artifact_mgmt_driver]:
|
||||
return artifact_mgmt_driver
|
||||
else:
|
||||
LOG.error('The hash verification of VNF Package MgmtDriver '
|
||||
'and Tacker MgmtDriver does not match.')
|
||||
raise exceptions.MgmtDriverHashMatchFailure()
|
||||
|
||||
def _load_vnf_interface(self, context, method_name,
|
||||
vnf_instance, vnfd_dict):
|
||||
VNF_value = vnfd_dict['topology_template']['node_templates']['VNF']
|
||||
tacker_mgmt_driver = DEFAULT_VNFLCM_MGMT_DRIVER
|
||||
interfaces_vnflcm_value = \
|
||||
VNF_value.get('interfaces', {}).get('Vnflcm', {})
|
||||
if not interfaces_vnflcm_value:
|
||||
return tacker_mgmt_driver
|
||||
artifacts_value = VNF_value.get('artifacts')
|
||||
if not artifacts_value:
|
||||
return tacker_mgmt_driver
|
||||
vnf_package_path = vnflcm_utils._get_vnf_package_path(
|
||||
context, vnf_instance.vnfd_id)
|
||||
|
||||
if interfaces_vnflcm_value.get(method_name):
|
||||
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)
|
||||
|
||||
return tacker_mgmt_driver
|
||||
|
||||
@log.log
|
||||
def instantiate_vnf(self, context, vnf_instance, vnf_dict,
|
||||
instantiate_vnf_req):
|
||||
@ -394,9 +474,26 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
vim_connection_info = objects.VimConnectionInfo.obj_from_primitive(
|
||||
vim_info, context)
|
||||
|
||||
vnfd_dict = vnflcm_utils._get_vnfd_dict(
|
||||
context, vnf_instance.vnfd_id, instantiate_vnf_req.flavour_id)
|
||||
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'instantiate_start', vnf_instance, vnfd_dict),
|
||||
'instantiate_start', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=instantiate_vnf_req.additional_params)
|
||||
|
||||
self._instantiate_vnf(context, vnf_instance, vnf_dict,
|
||||
vim_connection_info, instantiate_vnf_req)
|
||||
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'instantiate_end', vnf_instance, vnfd_dict),
|
||||
'instantiate_end', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=instantiate_vnf_req.additional_params)
|
||||
|
||||
@log.log
|
||||
@revert_to_error_task_state
|
||||
def terminate_vnf(self, context, vnf_instance, terminate_vnf_req):
|
||||
@ -407,6 +504,16 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
vim_connection_info = objects.VimConnectionInfo.obj_from_primitive(
|
||||
vim_info, context)
|
||||
|
||||
vnfd_dict = vnflcm_utils._get_vnfd_dict(
|
||||
context, vnf_instance.vnfd_id,
|
||||
vnf_instance.instantiated_vnf_info.flavour_id)
|
||||
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'terminate_start', vnf_instance, vnfd_dict),
|
||||
'terminate_start', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=terminate_vnf_req.additional_params)
|
||||
LOG.info("Terminating vnf %s", vnf_instance.id)
|
||||
try:
|
||||
self._delete_vnf_instance_resources(context, vnf_instance,
|
||||
@ -422,6 +529,12 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
LOG.error("Unable to terminate vnf '%s' instance. "
|
||||
"Error: %s", vnf_instance.id,
|
||||
encodeutils.exception_to_unicode(exp))
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'terminate_end', vnf_instance, vnfd_dict),
|
||||
'terminate_end', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=terminate_vnf_req.additional_params)
|
||||
|
||||
def _delete_vnf_instance_resources(self, context, vnf_instance,
|
||||
vim_connection_info, terminate_vnf_req=None,
|
||||
@ -578,6 +691,17 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
vim_connection_info = objects.VimConnectionInfo.obj_from_primitive(
|
||||
vim_info, context)
|
||||
|
||||
vnfd_dict = vnflcm_utils._get_vnfd_dict(
|
||||
context, vnf_instance.vnfd_id,
|
||||
vnf_instance.instantiated_vnf_info.flavour_id)
|
||||
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'heal_start', vnf_instance, vnfd_dict),
|
||||
'heal_start', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=heal_vnf_request.additional_params)
|
||||
|
||||
if not heal_vnf_request.vnfc_instance_id:
|
||||
self._respawn_vnf(context, vnf_instance, vnf_dict,
|
||||
vim_connection_info, heal_vnf_request)
|
||||
@ -587,6 +711,12 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
|
||||
LOG.info("Request received for healing vnf '%s' is completed "
|
||||
"successfully", vnf_instance.id)
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'heal_end', vnf_instance, vnfd_dict),
|
||||
'heal_end', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=heal_vnf_request.additional_params)
|
||||
|
||||
def _scale_vnf_pre(self, context, vnf_info, vnf_instance,
|
||||
scale_vnf_request, vim_connection_info):
|
||||
@ -600,15 +730,10 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
grp_id = None
|
||||
vnf_info['policy_name'] = scale_vnf_request.aspect_id
|
||||
if scale_vnf_request.type == 'SCALE_IN':
|
||||
vnfd_yaml = vnf_info['vnfd']['attributes'].get(
|
||||
'vnfd_' + vnf_instance.instantiated_vnf_info.flavour_id, '')
|
||||
vnfd_dict = yaml.safe_load(vnfd_yaml)
|
||||
# mgmt_driver from vnfd
|
||||
vnf_node = self._get_node_template_for_vnf(vnfd_dict)
|
||||
if vnf_node and vnf_node.get('interfaces'):
|
||||
if vnf_node['interfaces']['Vnflcm']['scale_start']:
|
||||
vnf_info['vnfd']['mgmt_driver'] = \
|
||||
vnf_node['interfaces']['Vnflcm']['scale_start']
|
||||
vnfd_dict = vnflcm_utils._get_vnfd_dict(
|
||||
context, vnf_instance.vnfd_id,
|
||||
vnf_instance.instantiated_vnf_info.flavour_id)
|
||||
|
||||
vnf_info['action'] = 'in'
|
||||
scale_id_list, scale_name_list, grp_id, res_num = \
|
||||
self._vnf_manager.invoke(
|
||||
@ -627,21 +752,13 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
vnf_info['res_num'] = res_num
|
||||
|
||||
# mgmt_driver pre
|
||||
if len(scale_id_list) != 0 and vnf_info['vnfd'].get('mgmt_driver'):
|
||||
if len(scale_id_list) > 1:
|
||||
stack_value = []
|
||||
stack_value = scale_id_list
|
||||
else:
|
||||
stack_value = scale_id_list[0]
|
||||
kwargs = {
|
||||
mgmt_constants.KEY_ACTION:
|
||||
mgmt_constants.ACTION_SCALE_IN_VNF,
|
||||
mgmt_constants.KEY_KWARGS:
|
||||
{'vnf': vnf_info},
|
||||
mgmt_constants.KEY_SCALE:
|
||||
stack_value,
|
||||
}
|
||||
self._vnfm_plugin.mgmt_call(context, vnf_info, kwargs)
|
||||
if len(scale_id_list) != 0:
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'scale_start', vnf_instance, vnfd_dict),
|
||||
'scale_start', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=scale_vnf_request.additional_params)
|
||||
else:
|
||||
vnf_info['action'] = 'out'
|
||||
scale_id_list = self._vnf_manager.invoke(
|
||||
@ -672,18 +789,10 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
vnf_lcm_op_occ = vnf_info['vnf_lcm_op_occ']
|
||||
vnf_lcm_op_occ.error_point = 6
|
||||
if scale_vnf_request.type == 'SCALE_OUT':
|
||||
vnfd_yaml =\
|
||||
vnf_info['vnfd']['attributes'].\
|
||||
get('vnfd_' + vnf_instance.instantiated_vnf_info.flavour_id,
|
||||
'')
|
||||
vnf_info['policy_name'] = scale_vnf_request.aspect_id
|
||||
vnfd_dict = yaml.safe_load(vnfd_yaml)
|
||||
# mgmt_driver from vnfd
|
||||
vnf_node = self._get_node_template_for_vnf(vnfd_dict)
|
||||
if vnf_node and vnf_node.get('interfaces'):
|
||||
if vnf_node['interfaces']['Vnflcm']['scale_end']:
|
||||
vnf_info['vnfd']['mgmt_driver'] = \
|
||||
vnf_node['interfaces']['Vnflcm']['scale_end']
|
||||
vnfd_dict = vnflcm_utils._get_vnfd_dict(
|
||||
context, vnf_instance.vnfd_id,
|
||||
vnf_instance.instantiated_vnf_info.flavour_id)
|
||||
|
||||
scale_id_after = self._vnf_manager.invoke(
|
||||
vim_connection_info.vim_type,
|
||||
'get_scale_ids',
|
||||
@ -696,21 +805,13 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
id_list = []
|
||||
id_list = list(set(scale_id_after) - set(scale_id_list))
|
||||
vnf_info['res_num'] = len(scale_id_after)
|
||||
if len(id_list) != 0 and vnf_info['vnfd'].get('mgmt_driver'):
|
||||
if len(id_list) > 1:
|
||||
stack_value = []
|
||||
stack_value = id_list
|
||||
else:
|
||||
stack_value = id_list[0]
|
||||
kwargs = {
|
||||
mgmt_constants.KEY_ACTION:
|
||||
mgmt_constants.ACTION_SCALE_OUT_VNF,
|
||||
mgmt_constants.KEY_KWARGS:
|
||||
{'vnf': vnf_info},
|
||||
mgmt_constants.KEY_SCALE:
|
||||
stack_value,
|
||||
}
|
||||
self._vnfm_plugin.mgmt_call(context, vnf_info, kwargs)
|
||||
if len(id_list) != 0:
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'scale_end', vnf_instance, vnfd_dict),
|
||||
'scale_end', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=scale_vnf_request.additional_params)
|
||||
vnf_lcm_op_occ.error_point = 7
|
||||
vnf_instance.instantiated_vnf_info.scale_level =\
|
||||
vnf_info['after_scale_level']
|
||||
@ -1214,57 +1315,32 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
)
|
||||
if vnf_lcm_op_occs.error_point == 7:
|
||||
if vnf_lcm_op_occs.operation == 'SCALE':
|
||||
vnfd_yaml = vnf_info['vnfd']['attributes'].\
|
||||
get('vnfd_' +
|
||||
vnf_instance.instantiated_vnf_info.flavour_id, '')
|
||||
vnfd_dict = yaml.safe_load(vnfd_yaml)
|
||||
# mgmt_driver from vnfd
|
||||
vnf_node = self._get_node_template_for_vnf(vnfd_dict)
|
||||
if vnf_node and vnf_node.get('interfaces'):
|
||||
if vnf_node['interfaces'].get('Vnflcm'):
|
||||
if vnf_node['interfaces']['Vnflcm'].get('scale_start'):
|
||||
vnf_info['vnfd']['mgmt_driver'] = \
|
||||
vnf_node['interfaces']['Vnflcm']['scale_start']
|
||||
vnfd_dict = vnflcm_utils._get_vnfd_dict(
|
||||
context, vnf_instance.vnfd_id,
|
||||
vnf_instance.instantiated_vnf_info.flavour_id)
|
||||
|
||||
vnf_info['action'] = 'in'
|
||||
if len(scale_id_list) != 0 and vnf_info['vnfd'].get(
|
||||
'mgmt_driver'):
|
||||
if len(scale_id_list) > 1:
|
||||
stack_value = []
|
||||
stack_value = scale_id_list
|
||||
else:
|
||||
stack_value = scale_id_list[0]
|
||||
kwargs = {
|
||||
mgmt_constants.KEY_ACTION:
|
||||
mgmt_constants.ACTION_SCALE_IN_VNF,
|
||||
mgmt_constants.KEY_KWARGS:
|
||||
{'vnf': vnf_info},
|
||||
mgmt_constants.KEY_SCALE:
|
||||
stack_value,
|
||||
}
|
||||
self._rollback_mgmt_call(context, vnf_info, kwargs)
|
||||
if len(scale_id_list) != 0:
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(context, 'scale_start',
|
||||
vnf_instance, vnfd_dict),
|
||||
'scale_start', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=scale_vnf_request.additional_params)
|
||||
|
||||
else:
|
||||
vnfd_yaml = vnf_info['vnfd']['attributes'].\
|
||||
get('vnfd_' +
|
||||
vnf_instance.instantiated_vnf_info.flavour_id, '')
|
||||
vnfd_dict = yaml.safe_load(vnfd_yaml)
|
||||
# mgmt_driver from vnfd
|
||||
vnf_node = self._get_node_template_for_vnf(vnfd_dict)
|
||||
if vnf_node and vnf_node.get('interfaces'):
|
||||
if vnf_node['interfaces'].get('Vnflcm'):
|
||||
if vnf_node['interfaces']['Vnflcm'].get(
|
||||
'termination_start'):
|
||||
vnf_info['vnfd']['mgmt_driver'] = vnf_node[
|
||||
'interfaces']['Vnflcm']['termination_start']
|
||||
if len(scale_id_list) != 0 and vnf_info['vnfd'].get(
|
||||
'mgmt_driver'):
|
||||
kwargs = {
|
||||
mgmt_constants.KEY_ACTION:
|
||||
mgmt_constants.ACTION_DELETE_VNF,
|
||||
mgmt_constants.KEY_KWARGS:
|
||||
{'vnf': vnf_info}
|
||||
}
|
||||
self._rollback_mgmt_call(context, vnf_info, kwargs)
|
||||
vnfd_dict = vnflcm_utils._get_vnfd_dict(
|
||||
context, vnf_instance.vnfd_id,
|
||||
vnf_instance.instantiated_vnf_info.flavour_id)
|
||||
|
||||
if len(scale_id_list) != 0:
|
||||
self._mgmt_manager.invoke(
|
||||
self._load_vnf_interface(
|
||||
context, 'terminate_start',
|
||||
vnf_instance, vnfd_dict),
|
||||
'terminate_start', context=context,
|
||||
vnf_instance=vnf_instance,
|
||||
additional_params=scale_vnf_request.additional_params)
|
||||
vnf_lcm_op_occs.error_point = 6
|
||||
|
||||
return scale_name_list, grp_id
|
||||
@ -1336,9 +1412,6 @@ class VnfLcmDriver(abstract_driver.VnfInstanceAbstractDriver):
|
||||
def _update_vnf_rollback_status_err(self, context, vnf_info):
|
||||
self._vnfm_plugin.update_vnf_rollback_status_err(context, vnf_info)
|
||||
|
||||
def _rollback_mgmt_call(self, context, vnf_info, kwargs):
|
||||
self._vnfm_plugin.mgmt_call(context, vnf_info, kwargs)
|
||||
|
||||
def _rollback_vnf_post(
|
||||
self,
|
||||
context,
|
||||
|
77
tacker/vnfm/mgmt_drivers/vnflcm_abstract_driver.py
Normal file
77
tacker/vnfm/mgmt_drivers/vnflcm_abstract_driver.py
Normal file
@ -0,0 +1,77 @@
|
||||
# Copyright (C) 2020 FUJITSU
|
||||
# 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.
|
||||
|
||||
import abc
|
||||
|
||||
from oslo_log import log as logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class VnflcmMgmtAbstractDriver(metaclass=abc.ABCMeta):
|
||||
@abc.abstractmethod
|
||||
def get_type(self):
|
||||
"""Return one of predefined type of the hosting vnf drivers."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_name(self):
|
||||
"""Return a symbolic name for the service VM plugin."""
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def get_description(self):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def instantiate_start(self, context, vnf_instance,
|
||||
additional_params, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def instantiate_end(self, context, vnf_instance,
|
||||
additional_params, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def terminate_start(self, context, vnf_instance,
|
||||
additional_params, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def terminate_end(self, context, vnf_instance,
|
||||
additional_params, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def scale_start(self, context, vnf_instance,
|
||||
additional_params, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def scale_end(self, context, vnf_instance,
|
||||
additional_params, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def heal_start(self, context, vnf_instance,
|
||||
additional_params, **kwargs):
|
||||
pass
|
||||
|
||||
@abc.abstractmethod
|
||||
def heal_end(self, context, vnf_instance,
|
||||
additional_params, **kwargs):
|
||||
pass
|
68
tacker/vnfm/mgmt_drivers/vnflcm_noop.py
Normal file
68
tacker/vnfm/mgmt_drivers/vnflcm_noop.py
Normal file
@ -0,0 +1,68 @@
|
||||
# Copyright (C) 2020 FUJITSU
|
||||
# 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
|
@ -20,3 +20,4 @@ WebTest>=2.0.27 # MIT
|
||||
python-barbicanclient>=4.5.2 # Apache-2.0
|
||||
python-blazarclient>=1.0.1 # Apache-2.0
|
||||
requests-mock>=1.2.0 # Apache-2.0
|
||||
PyMySQL>=0.10.1 # MIT
|
||||
|
Loading…
Reference in New Issue
Block a user