Merge "Implement SOL001 features to MgmtDriver"
This commit is contained in:
commit
22d69f971a
|
@ -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
|
|
@ -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': {
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
|
@ -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