Merge "Implement VNFC support"

This commit is contained in:
Jenkins 2017-02-10 06:53:57 +00:00 committed by Gerrit Code Review
commit 4349df4ece
14 changed files with 414 additions and 1 deletions

View File

@ -0,0 +1,57 @@
========================
VNF Component in Tacker
========================
This section will cover how to deploy `vnf component` in Tacker with the
examples of how to write VNF descriptors.
Sample TOSCA with vnfc
=======================
The following example shows vnfc resource using TOSCA template.
The target (VDU1) of the 'firewall_vnfc' in this example need to be
described firstly like other TOSCA templates in Tacker.
.. code-block:: yaml
topology_template:
node_templates:
firewall_vnfc:
type: tosca.nodes.nfv.VNFC.Tacker
requirements:
- host: VDU1
interfaces:
Standard:
create: install_vnfc.sh
Every vnfc node must be of type 'tosca.nodes.nfv.VNFC.Tacker'. It takes
two parameters:
1) requirements: This node will accept list of hosts on which VNFC has to be
installed.
2) interfaces: This node will accept the absolute path of shell script to be run
on the VDUs. This shell script should reside in the machine where tacker
server is running.
How to setup environment
~~~~~~~~~~~~~~~~~~~~~~~~~
To make use of VNFC in Tacker, we have to upload the image to the glance in
which heat-config and heat-config agents are installed. The installation steps
can be referred `here <https://github.com/openstack/heat-templates/blob/master/
hot/software-config/elements/README.rst>`_.
Currently VNFC feature works by using `heat software config <http://docs.openstack.org/
developer/heat/template_guide/openstack.html#OS::Heat::SoftwareConfig>`_ which
makes use of heat API.
So the glance images which has heat-config agents installed are only to be
passed to VDU.
Known Limitations
~~~~~~~~~~~~~~~~~
1) Only one VNFC is supported for one VDU. Multiple VNFC per VDU will
be introduced in future.
2) The shell script for vnfc has to be placed in the machine where tacker
server is running.

View File

@ -61,6 +61,7 @@ Feature Documentation
devref/vnffgd_template_description.rst
devref/vnffg_usage_guide.rst
devref/nsd_usage_guide.rst
devref/vnf_component_usage_guide.rst
API Documentation
=================

View File

@ -0,0 +1,8 @@
---
features:
- Add support to pass shell script to install VNF
components in the tosca template
other:
- Only one VNFC is supported for one VDU. Multiple VNFC per VDU will
be introduced in future.
- The shell script for vnfc has to be placed in the machine where tacker server is running

View File

@ -0,0 +1,40 @@
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
metadata:
template_name: sample-tosca-vnfd-for-vnfc
topology_template:
node_templates:
firewall_vnfc:
type: tosca.nodes.nfv.VNFC.Tacker
requirements:
- host: VDU1
interfaces:
Standard:
create: install_vnfc.sh
VDU1:
type: tosca.nodes.nfv.VDU.Tacker
properties:
image: fedora-software-config
flavor: m1.small
mgmt_driver: noop
key_name: stack_key
config: |
param0: key1
param1: key2
CP1:
type: tosca.nodes.nfv.CP.Tacker
properties:
management: true
anti_spoofing_protection: false
requirements:
- virtualLink:
node: VL1
- virtualBinding:
node: VDU1
VL1:
type: tosca.nodes.nfv.VL
properties:
network_name: net1
vendor: Tacker

View File

@ -0,0 +1,63 @@
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
metadata:
template_name: sample-tosca-vnfd-for-vnfc
topology_template:
node_templates:
firewall_vnfc:
type: tosca.nodes.nfv.VNFC.Tacker
requirements:
- host: VDU1
- host: VDU2
interfaces:
Standard:
create: /home/bharatht/install_vnfc.sh
VDU1:
type: tosca.nodes.nfv.VDU.Tacker
properties:
image: fedora-software-config
flavor: m1.small
mgmt_driver: noop
key_name: stack_key
config: |
param0: key1
param1: key2
CP1:
type: tosca.nodes.nfv.CP.Tacker
properties:
management: true
anti_spoofing_protection: false
requirements:
- virtualLink:
node: VL1
- virtualBinding:
node: VDU1
VDU2:
type: tosca.nodes.nfv.VDU.Tacker
properties:
image: fedora-software-config
flavor: m1.small
mgmt_driver: noop
key_name: stack_key
config: |
param0: key1
param1: key2
CP2:
type: tosca.nodes.nfv.CP.Tacker
properties:
management: true
anti_spoofing_protection: false
requirements:
- virtualLink:
node: VL1
- virtualBinding:
node: VDU2
VL1:
type: tosca.nodes.nfv.VL
properties:
network_name: private
vendor: Tacker

View File

@ -13,6 +13,7 @@
POLICY_ALARMING = 'tosca.policies.tacker.Alarming'
DEFAULT_ALARM_ACTIONS = ['respawn', 'log', 'log_and_kill', 'notify']
VNF_CIRROS_CREATE_TIMEOUT = 300
VNFC_CREATE_TIMEOUT = 600
VNF_CIRROS_DELETE_TIMEOUT = 300
VNF_CIRROS_DEAD_TIMEOUT = 250
ACTIVE_SLEEP_TIME = 3

View File

@ -0,0 +1,2 @@
#!/bin/sh
echo "Successfully installed VNFC" > /tacker

View File

@ -0,0 +1,42 @@
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
metadata:
template_name: sample-tosca-vnfd-for-vnfc
topology_template:
node_templates:
firewall_vnfc:
type: tosca.nodes.nfv.VNFC.Tacker
requirements:
- host: VDU1
interfaces:
Standard:
create: install_vnfc.sh
VDU1:
type: tosca.nodes.nfv.VDU.Tacker
properties:
flavor: m1.small
mgmt_driver: noop
config: |
param0: key1
param1: key2
artifacts:
fedora:
type: tosca.artifacts.Deployment.Image.VM
file: https://github.com/bharaththiruveedula/dotfiles/raw/master/fedora-sw.qcow2
CP1:
type: tosca.nodes.nfv.CP.Tacker
properties:
management: true
anti_spoofing_protection: false
requirements:
- virtualLink:
node: VL1
- virtualBinding:
node: VDU1
VL1:
type: tosca.nodes.nfv.VL
properties:
network_name: private
vendor: Tacker

View File

@ -0,0 +1,110 @@
# 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
from oslo_config import cfg
from toscaparser import tosca_template
import yaml
from tacker.common import utils
from tacker.plugins.common import constants as evt_constants
from tacker.tests import constants
from tacker.tests.functional import base
from tacker.tests.utils import read_file
from tacker.vnfm.tosca import utils as toscautils
CONF = cfg.CONF
SOFTWARE_DEPLOYMENT = 'OS::Heat::SoftwareDeployment'
class VnfTestToscaVNFC(base.BaseTackerTest):
def test_create_delete_tosca_vnfc(self):
input_yaml = read_file('sample_tosca_vnfc.yaml')
tosca_dict = yaml.safe_load(input_yaml)
path = os.path.abspath(os.path.join(
os.path.dirname(__file__), "../../etc/samples"))
vnfd_name = 'sample-tosca-vnfc'
tosca_dict['topology_template']['node_templates'
]['firewall_vnfc'
]['interfaces'
]['Standard']['create'] = path \
+ '/install_vnfc.sh'
tosca_arg = {'vnfd': {'name': vnfd_name,
'attributes': {'vnfd': tosca_dict}}}
# Create vnfd with tosca template
vnfd_instance = self.client.create_vnfd(body=tosca_arg)
self.assertIsNotNone(vnfd_instance)
# Create vnf with vnfd_id
vnfd_id = vnfd_instance['vnfd']['id']
vnf_arg = {'vnf': {'vnfd_id': vnfd_id, 'name':
"test_tosca_vnfc"}}
vnf_instance = self.client.create_vnf(body=vnf_arg)
vnf_id = vnf_instance['vnf']['id']
self.wait_until_vnf_active(vnf_id,
constants.VNFC_CREATE_TIMEOUT,
constants.ACTIVE_SLEEP_TIME)
self.assertEqual('ACTIVE',
self.client.show_vnf(vnf_id)['vnf']['status'])
self.validate_vnf_instance(vnfd_instance, vnf_instance)
self.verify_vnf_crud_events(
vnf_id, evt_constants.RES_EVT_CREATE, evt_constants.PENDING_CREATE,
cnt=2)
self.verify_vnf_crud_events(
vnf_id, evt_constants.RES_EVT_CREATE, evt_constants.ACTIVE)
# Validate mgmt_url with input yaml file
mgmt_url = self.client.show_vnf(vnf_id)['vnf']['mgmt_url']
self.assertIsNotNone(mgmt_url)
mgmt_dict = yaml.load(str(mgmt_url))
input_dict = yaml.load(input_yaml)
toscautils.updateimports(input_dict)
tosca = tosca_template.ToscaTemplate(parsed_params={}, a_file=False,
yaml_dict_tpl=input_dict)
vdus = toscautils.findvdus(tosca)
self.assertEqual(len(vdus), len(mgmt_dict.keys()))
for vdu in vdus:
self.assertIsNotNone(mgmt_dict[vdu.name])
self.assertEqual(True, utils.is_valid_ipv4(mgmt_dict[vdu.name]))
# Check the status of SoftwareDeployment
heat_stack_id = self.client.show_vnf(vnf_id)['vnf']['instance_id']
resource_types = self.h_client.resources
resources = resource_types.list(stack_id=heat_stack_id)
for resource in resources:
resource = resource.to_dict()
if resource['resource_type'] == \
SOFTWARE_DEPLOYMENT:
self.assertEqual('CREATE_COMPLETE',
resource['resource_status'])
break
# Delete vnf_instance with vnf_id
try:
self.client.delete_vnf(vnf_id)
except Exception:
assert False, "vnf Delete of test_vnf_with_multiple_vdus failed"
self.wait_until_vnf_delete(vnf_id,
constants.VNF_CIRROS_DELETE_TIMEOUT)
self.verify_vnf_crud_events(vnf_id, evt_constants.RES_EVT_DELETE,
evt_constants.PENDING_DELETE, cnt=2)
# Delete vnfd_instance
self.addCleanup(self.client.delete_vnfd, vnfd_id)

View File

@ -0,0 +1,36 @@
heat_template_version: 2013-05-23
parameters: {}
resources:
VDU1:
type: OS::Nova::Server
properties:
config_drive: false
flavor: m1.small
image: Fedora
networks:
- port:
get_resource: CP1
user_data_format: SOFTWARE_CONFIG
CP1:
type: OS::Neutron::Port
properties:
network: existing_network_1
port_security_enabled: false
firewall_vnfc_create_config:
type: OS::Heat::SoftwareConfig
properties:
config: 'echo "Test case for Tacker";'
group: script
firewall_vnfc_create_deploy:
type: OS::Heat::SoftwareDeployment
properties:
config: {get_resource: firewall_vnfc_create_config}
server: {get_resource: VDU1}
depends_on:
- VDU1
outputs:
mgmt_ip-VDU1:
value:
get_attr: [CP1, fixed_ips, 0, ip_address]

View File

@ -0,0 +1,39 @@
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
metadata:
template_name: sample-tosca-vnfd-for-vnfc
topology_template:
node_templates:
firewall_vnfc:
type: tosca.nodes.nfv.VNFC.Tacker
requirements:
- host: VDU1
interfaces:
Standard:
create: install_vnfc.sh
VDU1:
type: tosca.nodes.nfv.VDU.Tacker
properties:
image: Fedora
flavor: m1.small
mgmt_driver: noop
config: |
param0: key1
param1: key2
CP1:
type: tosca.nodes.nfv.CP.Tacker
properties:
management: true
anti_spoofing_protection: false
requirements:
- virtualLink:
node: VL1
- virtualBinding:
node: VDU1
VL1:
type: tosca.nodes.nfv.VL
properties:
network_name: net1
vendor: Tacker

View File

@ -39,7 +39,7 @@ OPTS = [
help=_("Number of attempts to retry for stack"
" creation/deletion")),
cfg.IntOpt('stack_retry_wait',
default=5,
default=10,
help=_("Wait time (in seconds) between consecutive stack"
" create/delete retries")),
]

View File

@ -257,3 +257,9 @@ node_types:
required: true
entry_schema:
type: tosca.nfv.datatypes.pathType
tosca.nodes.nfv.VNFC.Tacker:
derived_from: tosca.nodes.SoftwareComponent
requirements:
- host:
node: tosca.nodes.nfv.VDU.Tacker
relationship: tosca.relationships.HostedOn

View File

@ -35,6 +35,7 @@ TACKERVDU = 'tosca.nodes.nfv.VDU.Tacker'
TOSCA_BINDS_TO = 'tosca.relationships.network.BindsTo'
VDU = 'tosca.nodes.nfv.VDU'
IMAGE = 'tosca.artifacts.Deployment.Image.VM'
HEAT_SOFTWARE_CONFIG = 'OS::Heat::SoftwareConfig'
OS_RESOURCES = {
'flavor': 'get_flavor_dict',
'image': 'get_image_dict'
@ -254,6 +255,13 @@ def post_process_heat_template(heat_tpl, mgmt_ports, metadata,
metadata_dict
add_resources_tpl(heat_dict, res_tpl)
for res in heat_dict["resources"].values():
if not res['type'] == HEAT_SOFTWARE_CONFIG:
continue
config = res["properties"]["config"]
if 'get_file' in config:
res["properties"]["config"] = open(config["get_file"]).read()
if unsupported_res_prop:
convert_unsupported_res_prop(heat_dict, unsupported_res_prop)
return yaml.dump(heat_dict)