ETSI-NFV SOL 001 translation: ScalingPolicy

Currently heat-translator supports translation of TOSCA Simple Profile
for YAML[1] and TOSCA Simple Profile for NFV[2] only.
This commit enables to translation of the follwoing type defined in
ETSI NFV-SOL 001[3].
- tosca.policies.nfv.InstantiationLevels
- tosca.policies.nfv.ScalingAspects
- tosca.policies.nfv.VduInitialDelta
- tosca.policies.nfv.VduInstantiationLevels
- tosca.policies.nfv.VduScalingAspectDeltas
- tosca.policies.nfv.VirtualLinkInstantiationLevels

[1] http://docs.oasis-open.org/tosca/tosca-nfv/v1.0/tosca-nfv-v1.0.html
[2] http://docs.oasis-open.org/tosca/TOSCA-Simple-Profile-YAML/v1.0/TOSCA-Simple-Profile-YAML-v1.0.html
[3] https://www.etsi.org/deliver/etsi_gs/NFV-SOL/001_099/001/02.06.01_60/gs_NFV-SOL001v020601p.pdf

Change-Id: Ifdb287c84dfb19d25b519a2e23f1b82ccc3f4088
Story: 2006372
Task: 37622
This commit is contained in:
Hiroo Kitamura 2019-11-28 13:08:31 +09:00
parent 59c61d71eb
commit 292248be2c
38 changed files with 2086 additions and 70 deletions

View File

@ -12,6 +12,8 @@
# under the License.
from collections import OrderedDict
import yaml
import logging
import os
import six
@ -27,11 +29,20 @@ SECTIONS = (TYPE, PROPERTIES, MEDADATA, DEPENDS_ON, UPDATE_POLICY,
('type', 'properties', 'metadata',
'depends_on', 'update_policy', 'deletion_policy')
HEAT_TEMPLATE_VERSION = '2013-05-23'
HEAT_DESCRIPTION = 'Scaling template'
policy_type = ['tosca.policies.Placement',
'tosca.policies.Scaling',
'tosca.policies.Scaling.Cluster',
'tosca.policies.Monitoring',
'tosca.policies.Reservation']
'tosca.policies.Reservation',
'tosca.policies.nfv.InstantiationLevels',
'tosca.policies.nfv.ScalingAspects',
'tosca.policies.nfv.VduInitialDelta',
'tosca.policies.nfv.VduInstantiationLevels',
'tosca.policies.nfv.VduScalingAspectDeltas',
'tosca.policies.nfv.VirtualLinkInstantiationLevels']
log = logging.getLogger('heat-translator')
@ -465,6 +476,47 @@ class HotResource(object):
tosca_props[prop.name] = prop.value
return tosca_props
def represent_ordereddict(self, dumper, data):
nodes = []
for key, value in data.items():
node_key = dumper.represent_data(key)
node_value = dumper.represent_data(value)
nodes.append((node_key, node_value))
return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', nodes)
def _handle_nested_template(self, scale_res, yaml_name,
hot_template_parameters,
parameters=None):
template_dict = OrderedDict()
template_dict['heat_template_version'] = HEAT_TEMPLATE_VERSION
template_dict['description'] = HEAT_DESCRIPTION
if parameters is not None:
template_dict['parameters'] = parameters
if hot_template_parameters:
all_params = OrderedDict()
for parameter in hot_template_parameters:
all_params.update(parameter.get_dict_output())
template_dict.update({'parameters': all_params})
template_dict["resources"] = {}
dict_res = OrderedDict()
for res in scale_res:
dict_res = res.get_dict_output()
res_name = list(dict_res.keys())[0]
template_dict["resources"][res_name] = \
dict_res[res_name]
yaml.add_representer(OrderedDict, self.represent_ordereddict)
yaml.add_representer(dict, self.represent_ordereddict)
yaml_string = yaml.dump(template_dict, default_flow_style=False)
yaml_string = yaml_string.replace('\'', '').replace('\n\n', '\n')
nested_template = {
yaml_name: yaml_string
}
return nested_template
def remove_depends_on(self, depends_on_set):
# Remove all depends_on including depends_on_set.
for rel, node in self.nodetemplate.relationships.items():

View File

@ -0,0 +1,227 @@
#
# 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 itertools import chain
import logging
from translator.hot.syntax.hot_resource import HotResource
log = logging.getLogger('heat-translator')
# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'ToscaNfvScalingAspect'
HEAT_NON_SCALING_RESOURCES = ['OS::Heat::ScalingPolicy',
'OS::Heat::AutoScalingGroup']
HOT_FLAVOR = 'OS::Nova::Flavor'
SCALING_ASPECT_DELTA = 'tosca.policies.nfv.VduScalingAspectDeltas'
VDU_CP = 'tosca.nodes.nfv.VduCp'
VDU_INITIAL_DELTA = 'tosca.policies.nfv.VduInitialDelta'
class ToscaNfvScalingAspect(HotResource):
"""Translate TOSCA policy type tosca.policies.nfv.ScalingAspects."""
toscatype = 'tosca.policies.nfv.ScalingAspects'
DESIRED_CAPACITY = 'DESIRED_CAPACITY'
def __init__(self, policy, aspect_name, csar_dir=None,
hot_template_parameters=None):
hot_type = "OS::Heat::ScalingPolicy"
self.aspect_name = aspect_name
super(ToscaNfvScalingAspect, self).__init__(
policy,
name=self.aspect_name,
type=hot_type,
csar_dir=csar_dir)
self.policy = policy
self.hot_template_parameters = hot_template_parameters
# default
self.scaling_adjustment = None
self.vdu_name = None
self.delta_name = None
def handle_properties(self, resources):
# Resources of non HotResource
# (Exclude derived)
non_hot_rsrcs = [r for r in resources if type(r) is not HotResource]
# Extract resource name from VduScalingAspectDeltas
vsad_rsrcs = [
r for r in non_hot_rsrcs if r.toscatype == SCALING_ASPECT_DELTA]
vsad_rsrcs = [
r for r in vsad_rsrcs if r.aspect == self.aspect_name]
vsad_rsrc = vsad_rsrcs[0]
# The names of the resource associated with the VDU.
# Supporting resources below.
# - tosca.nodes.nfv.Vdu.Compute
# - tosca.nodes.nfv.VduCp
# - tosca.nodes.nfv.Vdu.VirtualBlockStorage
vdu_infos = [
r for r in resources
if vsad_rsrc.targets is not None and r.name in vsad_rsrc.targets]
if vdu_infos == []:
log.warning('Can not create %s node '
'because target vdu does not defined.'
% self.aspect_name)
related_rsrc_names = []
related_vl_names = []
for vdu_info in vdu_infos:
vdu_name = vdu_info.name
port_rsrc_names = [p.name for p in vdu_info.assoc_port_resources]
strg_rsrc_names = [s for s in vdu_info.virtual_storages]
related_rsrc_names.append(vdu_name)
related_rsrc_names.extend(port_rsrc_names)
related_rsrc_names.extend(strg_rsrc_names)
# Extract virtual_link mapping to vdu_name
cp_rsrcs = [
r for r in non_hot_rsrcs
if r.toscatype == VDU_CP and r.virtual_binding == vdu_name]
related_vl_names.extend([
cp.virtual_link for cp in cp_rsrcs
if cp.virtual_link is not None])
# Parameters defined in referenced YAML
parameters = {}
# Resources of scaling/non-scaling
scl_rsrcs = []
non_scl_rsrcs = []
# Properties of :AutoScalingGroup
asg_props = {}
# Resources which are contain related_rsrc_names are not
# call handle_expansion(), so call here and add resources.
related_rsrcs = [
r for r in resources if r.name in related_rsrc_names]
exp_rsrcs = list(
chain.from_iterable([
r.handle_expansion()
for r in related_rsrcs
if r.handle_expansion() is not None]))
# Allocate resources generated by handle_expansion()
# to scaling or non-scaling resource.
# Flavor is non-scaling resource.
scl_rsrcs.extend([
r for r in exp_rsrcs
if r.type != HOT_FLAVOR])
non_scl_rsrcs.extend([
r for r in exp_rsrcs
if r.type == HOT_FLAVOR])
for resource in resources:
# Allocate resources to scaling or non-scaling resource.
if resource.type not in HEAT_NON_SCALING_RESOURCES and \
resource.name in related_rsrc_names:
scl_rsrcs.append(resource)
else:
non_scl_rsrcs.append(resource)
# Processing for VDU
if resource.name in related_rsrc_names and \
resource.type == 'OS::Nova::Server':
self.vdu_name = resource.name
# Target aspect
target_aspect = \
self.policy.properties['aspects'][self.aspect_name]
# Extract scaling_adjustment from VduScalingAspectDeltas.
# VduScalingAspectDeltas can specify a delta for each scaling
# step but only the first one is used and others are ignored.
delta_names = target_aspect['step_deltas']
self.delta_name = delta_names[0]
self.scaling_adjustment = vsad_rsrc.deltas.get(self.delta_name)
# Extract min_size from VduInitialDelta
vid_rsrcs = [
r for r in non_hot_rsrcs
if r.toscatype == VDU_INITIAL_DELTA]
initial_deltas = [
r for r in vid_rsrcs
if r.targets is not None and self.vdu_name in r.targets]
min_size = None \
if initial_deltas == [] else initial_deltas[0].num
res = {}
if min_size is not None and \
self.scaling_adjustment is not None:
# Calculate max_size
max_scale_level = target_aspect['max_scale_level']
max_size = \
min_size + max_scale_level * self.scaling_adjustment
res["min_size"] = min_size
res["max_size"] = max_size
else:
log.warning('No min_size or(and) max_size is found for '
'aspect_name:%s, VDU:%s' % (
self.aspect_name, self.vdu_name))
# desired_capacity needs to be replaced by users because it is
# calculated using scaling aspect and instantiation level given
# in instantiation VNF request.
res["desired_capacity"] = self.DESIRED_CAPACITY
res['resource'] = {'type': self.aspect_name + '.hot.yaml'}
props = {}
props['type'] = resource.type
props['properties'] = resource.properties
for vl_name in related_vl_names:
vl_id = '%s_id' % (vl_name.lower())
asg_props.update({
vl_id: '{ get_resource: %s }' % (vl_name)})
# Replace flavor id
flvr_name = resource.flavor_resource_name
flvr_id = '%s_id' % (flvr_name.lower())
asg_props.update({
flvr_id: '{ get_resource: %s }' % (flvr_name)})
resource.properties['flavor'] = \
'{ get_param: %s }' % (flvr_id)
parameters[flvr_id] = {'type': 'string'}
res['resource'].update({
'properties': asg_props
})
non_scl_rsrcs.append(
HotResource(resource,
type='OS::Heat::AutoScalingGroup',
name=self.aspect_name,
properties=res))
# Processing for CP related to target VDU
elif resource.name in related_rsrc_names and \
resource.type == 'OS::Neutron::Port':
for vl_name in related_vl_names:
if vl_name == resource.virtual_link:
# Replace network id
vl_id = '%s_id' % (vl_name.lower())
resource.properties['network'] = \
'{ get_param: %s }' % (vl_id)
parameters[vl_id] = {'type': 'string'}
# Create referenced YAML which is defined scaling resources
yaml_name = self.aspect_name + '.hot.yaml'
parameters = None if parameters == {} else parameters
nested_template = self._handle_nested_template(
scl_rsrcs,
yaml_name,
self.hot_template_parameters,
parameters=parameters)
return non_scl_rsrcs, nested_template

View File

@ -0,0 +1,33 @@
#
# 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 translator.hot.syntax.hot_resource import HotResource
# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'ToscaNfvInstantiationLevels'
class ToscaNfvInstantiationLevels(HotResource):
"""Translate TOSCA policy type tosca.policies.nfv.InstantiationLevels."""
toscatype = 'tosca.policies.nfv.InstantiationLevels'
def __init__(self, policy, csar_dir=None, hot_template_parameters=None):
super(ToscaNfvInstantiationLevels, self).__init__(
policy,
csar_dir=csar_dir)
self.policy = policy
self.hot_template_parameters = hot_template_parameters
def handle_properties(self):
pass

View File

@ -0,0 +1,124 @@
#
# 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 logging
from translator.hot.syntax.hot_resource import HotResource
from translator.hot.tosca.etsi_nfv.scalingaspect.\
tosca_policies_nfv_scalingaspect import ToscaNfvScalingAspect
log = logging.getLogger('heat-translator')
# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'ToscaNfvScalingAspects'
class ToscaNfvScalingAspects(HotResource):
"""Translate TOSCA policy type tosca.policies.nfv.ScalingAspects."""
toscatype = 'tosca.policies.nfv.ScalingAspects'
def __init__(self, policy, csar_dir=None, hot_template_parameters=None,
nested_template=None,
extra_flg=None):
hot_type = "OS::Heat::ScalingPolicy"
if extra_flg is None:
# Multi aspects support
self.aspect_names = policy.properties['aspects'].keys()
self.scaling_aspect_objs = []
for aspect_name in self.aspect_names:
self.scaling_aspect_objs.append(
ToscaNfvScalingAspect(policy,
aspect_name,
csar_dir,
hot_template_parameters)
)
super(ToscaNfvScalingAspects, self).__init__(
policy,
type=hot_type,
csar_dir=csar_dir)
self.policy = policy
self.hot_template_parameters = hot_template_parameters
self.multi_nested_templates = {}
self.nested_template = \
{} if nested_template is None else nested_template
def handle_properties(self, resources):
for aspect_obj in self.scaling_aspect_objs:
resources, nstd_tmpt = aspect_obj.handle_properties(resources)
self.multi_nested_templates[aspect_obj.aspect_name] = nstd_tmpt
resources = self._create_scale_out_in_resources(resources)
return resources
def extract_substack_templates(self, base_filename, hot_template_version):
return self.nested_template
def _create_scale_out_in_resources(self, resources):
for asp_obj in self.scaling_aspect_objs:
asp_name = asp_obj.aspect_name
# Create scale_out and scale_in resources
scl_out_rsrc = ToscaNfvScalingAspects(
self.policy,
csar_dir=self.csar_dir,
hot_template_parameters=self.
hot_template_parameters,
nested_template=self.
multi_nested_templates[asp_name],
extra_flg=True
)
scl_in_rsrc = ToscaNfvScalingAspects(
self.policy,
csar_dir=self.csar_dir,
hot_template_parameters=self.
hot_template_parameters,
nested_template=self.
multi_nested_templates[asp_name],
extra_flg=True
)
scl_out_rsrc.name = asp_name + '_scale_out'
scl_in_rsrc.name = asp_name + '_scale_in'
if asp_obj.scaling_adjustment is not None:
scaling_adjustment = \
int(asp_obj.scaling_adjustment)
scl_out_rsrc.properties['scaling_adjustment'] = \
scaling_adjustment
scl_in_rsrc.properties['scaling_adjustment'] = \
-1 * scaling_adjustment
else:
log.warning('No ScalingAspectDelta for %s of %s, %s is found'
% (asp_obj.vdu_name, asp_name, asp_obj.delta_name))
scl_out_rsrc.properties["auto_scaling_group_id"] = {
'get_resource': asp_name
}
scl_out_rsrc.properties["adjustment_type"] = \
"change_in_capacity"
resources.append(scl_out_rsrc)
scl_in_rsrc.properties["auto_scaling_group_id"] = {
'get_resource': asp_name
}
scl_in_rsrc.properties["adjustment_type"] = \
"change_in_capacity"
resources.append(scl_in_rsrc)
# This resource has already created scale_out and
# scale_in resources, so remove it.
resources.remove(self)
return resources

View File

@ -0,0 +1,40 @@
#
# 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 translator.hot.syntax.hot_resource import HotResource
# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'ToscaNfvVduInitialDelta'
class ToscaNfvVduInitialDelta(HotResource):
"""Translate TOSCA policy type tosca.policies.nfv.VduInitialDelta."""
toscatype = 'tosca.policies.nfv.VduInitialDelta'
def __init__(self, policy, csar_dir=None, hot_template_parameters=None):
super(ToscaNfvVduInitialDelta, self).__init__(
policy,
csar_dir=csar_dir)
self.policy = policy
self.hot_template_parameters = hot_template_parameters
# Extract number_of_instances
tosca_props = self.get_tosca_props()
self.num = tosca_props['initial_delta']['number_of_instances']
# Extract targets
self.targets = self.policy.targets
def handle_properties(self):
pass

View File

@ -0,0 +1,36 @@
#
# 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 translator.hot.syntax.hot_resource import HotResource
# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'ToscaNfvVduInstantiationLevels'
class ToscaNfvVduInstantiationLevels(HotResource):
"""Translate TOSCA policy type
tosca.policies.nfv.VduInstantiationLevels.
"""
toscatype = 'tosca.policies.nfv.VduInstantiationLevels'
def __init__(self, policy, csar_dir=None, hot_template_parameters=None):
super(ToscaNfvVduInstantiationLevels, self).__init__(
policy,
csar_dir=csar_dir)
self.policy = policy
self.hot_template_parameters = hot_template_parameters
def handle_properties(self):
pass

View File

@ -0,0 +1,46 @@
#
# 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 translator.hot.syntax.hot_resource import HotResource
# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'ToscaNfvVduScalingAspectDeltas'
class ToscaNfvVduScalingAspectDeltas(HotResource):
"""Translate TOSCA policy type
tosca.policies.nfv.VduScalingAspectDeltas.
"""
toscatype = 'tosca.policies.nfv.VduScalingAspectDeltas'
def __init__(self, policy, csar_dir=None, hot_template_parameters=None):
super(ToscaNfvVduScalingAspectDeltas, self).__init__(
policy,
csar_dir=csar_dir)
self.policy = policy
self.hot_template_parameters = hot_template_parameters
# Extract aspect name and deltas
tosca_props = self.get_tosca_props()
self.aspect = tosca_props['aspect']
self.deltas = {}
for key, val in tosca_props['deltas'].items():
self.deltas[key] = val['number_of_instances']
# Extract target VDUs
self.targets = self.policy.targets
def handle_properties(self):
pass

View File

@ -0,0 +1,36 @@
#
# 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 translator.hot.syntax.hot_resource import HotResource
# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'VirtualLinkInstantiationLevels'
class VirtualLinkInstantiationLevels(HotResource):
"""Translate TOSCA policy type
tosca.policies.nfv.VirtualLinkInstantiationLevels.
"""
toscatype = 'tosca.policies.nfv.VirtualLinkInstantiationLevels'
def __init__(self, policy, csar_dir=None, hot_template_parameters=None):
super(VirtualLinkInstantiationLevels, self).__init__(
policy,
csar_dir=csar_dir)
self.policy = policy
self.hot_template_parameters = hot_template_parameters
def handle_properties(self):
pass

View File

@ -138,7 +138,7 @@ class AutoscalingTest(TestCase):
expected_nested_resource = {'heat_template_version':
datetime.date(2013, 5, 23),
'description':
'Tacker Scaling template',
'Scaling template',
'parameters':
{'flavor':
{'default': 'm1.tiny',

View File

@ -11,16 +11,9 @@
# License for the specific language governing permissions and limitations
# under the License.
from collections import OrderedDict
import yaml
from translator.hot.syntax.hot_resource import HotResource
# Name used to dynamically load appropriate map class.
TARGET_CLASS_NAME = 'ToscaAutoscaling'
HEAT_TEMPLATE_BASE = """
heat_template_version: 2013-05-23
"""
ALARM_STATISTIC = {'mean': 'mean', 'median': 'median', 'summary': 'sum',
'maximum': 'max', 'minimum': 'min', 'last': 'last',
'std': 'std', 'first': 'first', 'count': 'count'}
@ -66,39 +59,6 @@ class ToscaAutoscaling(HotResource):
hot_resources = [ceilometer_resources]
return hot_resources
def represent_ordereddict(self, dumper, data):
nodes = []
for key, value in data.items():
node_key = dumper.represent_data(key)
node_value = dumper.represent_data(value)
nodes.append((node_key, node_value))
return yaml.nodes.MappingNode(u'tag:yaml.org,2002:map', nodes)
def _handle_nested_template(self, scale_res):
template_dict = yaml.safe_load(HEAT_TEMPLATE_BASE)
template_dict['description'] = 'Tacker Scaling template'
if self.hot_template_parameters:
all_params = OrderedDict()
for parameter in self.hot_template_parameters:
all_params.update(parameter.get_dict_output())
template_dict.update({'parameters': all_params})
template_dict["resources"] = {}
dict_res = OrderedDict()
for res in scale_res:
dict_res = res.get_dict_output()
res_name = list(dict_res.keys())[0]
template_dict["resources"][res_name] = \
dict_res[res_name]
yaml.add_representer(OrderedDict, self.represent_ordereddict)
yaml.add_representer(dict, self.represent_ordereddict)
yaml_string = yaml.dump(template_dict, default_flow_style=False)
yaml_string = yaml_string.replace('\'', '').replace('\n\n', '\n')
self.nested_template = {
self.policy.name + '_res.yaml': yaml_string
}
def handle_properties(self, resources):
self.properties = {}
self.properties["auto_scaling_group_id"] = {
@ -133,7 +93,11 @@ class ToscaAutoscaling(HotResource):
if resource.type not in SCALING_RESOURCES:
delete_res_names.append(resource.name)
scale_res.append(resource)
self._handle_nested_template(scale_res)
yaml_name = self.policy.name + '_res.yaml'
self.nested_template = self._handle_nested_template(
scale_res,
yaml_name,
self.hot_template_parameters)
resources = [tmp_res
for tmp_res in resources
if tmp_res.name not in delete_res_names]

View File

@ -141,9 +141,18 @@ TOSCA_TO_HOT_TYPE = _generate_type_map()
BASE_TYPES = six.string_types + six.integer_types + (dict, OrderedDict)
BASE_POLICY_TYPES = [
'tosca.policies.Scaling',
'tosca.policies.Monitoring',
'tosca.policies.Placement',
'tosca.policies.Reservation',
]
HOT_SCALING_POLICY_TYPE = ["OS::Heat::AutoScalingGroup",
"OS::Senlin::Profile"]
TOSCA_SA = 'tosca.policies.nfv.ScalingAspects'
class TranslateNodeTemplates(object):
'''Translate TOSCA NodeTemplates to Heat Resources.'''
@ -188,7 +197,8 @@ class TranslateNodeTemplates(object):
resource.handle_properties(self.hot_resources)
extra_hot_resources = []
for res in self.hot_resources:
if res.type == 'OS::Heat::ScalingPolicy':
if res.type == 'OS::Heat::ScalingPolicy' and\
res.toscatype != TOSCA_SA:
extra_res = copy.deepcopy(res)
scaling_adjustment = res.properties['scaling_adjustment']
if scaling_adjustment < 0:
@ -265,30 +275,26 @@ class TranslateNodeTemplates(object):
for policy in self.policies:
policy_type = policy.type_definition
if policy.is_derived_from('tosca.policies.Scaling') and \
policy_type.type != 'tosca.policies.Scaling.Cluster':
TOSCA_TO_HOT_TYPE[policy_type.type] = \
TOSCA_TO_HOT_TYPE['tosca.policies.Scaling']
if policy.is_derived_from('tosca.policies.Monitoring'):
TOSCA_TO_HOT_TYPE[policy_type.type] = \
TOSCA_TO_HOT_TYPE['tosca.policies.Monitoring']
if policy.is_derived_from('tosca.policies.Placement'):
TOSCA_TO_HOT_TYPE[policy_type.type] = \
TOSCA_TO_HOT_TYPE['tosca.policies.Placement']
if policy.is_derived_from('tosca.policies.Reservation'):
TOSCA_TO_HOT_TYPE[policy_type.type] = \
TOSCA_TO_HOT_TYPE['tosca.policies.Reservation']
if policy_type.type not in TOSCA_TO_HOT_TYPE:
raise UnsupportedTypeError(type=_('%s') % policy_type.type)
elif policy_type.type == 'tosca.policies.Scaling.Cluster':
own_policy_type = policy_type.type
base_policy_type = self._get_supported_type(policy)
if base_policy_type in BASE_POLICY_TYPES and \
own_policy_type != 'tosca.policies.Scaling.Cluster':
TOSCA_TO_HOT_TYPE[own_policy_type] = \
TOSCA_TO_HOT_TYPE[base_policy_type]
if own_policy_type == 'tosca.policies.Scaling.Cluster':
self.hot_template_version = '2016-04-08'
if policy.is_derived_from('tosca.policies.Scaling') and \
policy_type.type != 'tosca.policies.Scaling.Cluster':
policy_node = TOSCA_TO_HOT_TYPE[policy_type.type](
if (base_policy_type == 'tosca.policies.Scaling' or
base_policy_type == 'tosca.policies.tacker.Scaling') and \
own_policy_type != 'tosca.policies.Scaling.Cluster':
policy_node = TOSCA_TO_HOT_TYPE[own_policy_type](
policy,
hot_template_parameters=self.hot_template.parameters)
else:
policy_node = TOSCA_TO_HOT_TYPE[policy_type.type](policy)
policy_node = TOSCA_TO_HOT_TYPE[own_policy_type](policy)
self.hot_resources.append(policy_node)
# Handle life cycle operations: this may expand each node

View File

@ -0,0 +1,112 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: >
Template for scaling which deltas is not defined in tosca.policies.nfv.VduScalingAspectDeltas.
(Defined delta_2 in tosca.policies.nfv.ScalingAspects,
but defined delta_1 in tosca.policies.nfv.VduScalingAspectDeltas.)
In Addition, the following properties are not set in
<aspect_name>_scale_in and <aspect_name>_scale_out nodes.
->scaling_adjustment
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
topology_template:
node_templates:
VDU1:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU1
description: VDU1 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
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 GiB
size: 1 GiB
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 MiB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GiB
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
vnic_type: direct-physical
requirements:
- virtual_binding: VDU1
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_2
- 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 ]

View File

@ -0,0 +1,112 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: >
Template for scaling which targets is not set in tosca.policies.nfv.VduScalingAspectDeltas.
The following nodes are not set in hot.
->OS::Heat::AutoScalingGroup
And create empty <aspect_name>.yaml.
In Addition, the following properties are not set in
<aspect_name>_scale_in and <aspect_name>_scale_out nodes.
->scaling_adjustment
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
topology_template:
node_templates:
VDU1:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU1
description: VDU1 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
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 GiB
size: 1 GiB
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 MiB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GiB
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
vnic_type: direct-physical
requirements:
- virtual_binding: VDU1
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
- 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 ]

View File

@ -0,0 +1,109 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: >
Template for scaling which targets is not set in tosca.policies.nfv.VduInitialDelta.
The following properties are not set in <aspect_name>.
->min_size
->max_size
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
topology_template:
node_templates:
VDU1:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU1
description: VDU1 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
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 GiB
size: 1 GiB
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 MiB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GiB
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
vnic_type: direct-physical
requirements:
- virtual_binding: VDU1
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
- 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 ]

View File

@ -0,0 +1,182 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: >
Template for deploying two VDU and two CP and one VirtualLink with scaling.
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
topology_template:
node_templates:
VDU1:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU1
description: VDU1 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
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 GiB
size: 1 GiB
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 MiB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GiB
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
requirements:
- virtual_binding: VDU1
- virtual_link: VL1
VL1:
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
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
sw_image_data:
name: Software of VDU2
version: '0.4.0'
checksum:
algorithm: sha-256
hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d
container_format: bare
disk_format: qcow2
min_disk: 1 GiB
size: 1 GiB
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 MiB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GiB
CP2:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
requirements:
- virtual_binding: VDU2
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
- VDU_initial_delta:
type: tosca.policies.nfv.VduInitialDelta
properties:
initial_delta:
number_of_instances: 1
targets: [ VDU1, VDU2 ]
- VDU_scaling_aspect_deltas:
type: tosca.policies.nfv.VduScalingAspectDeltas
properties:
aspect: worker_instance
deltas:
delta_1:
number_of_instances: 1
targets: [ VDU1, 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
- VDU_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 ]
- VL1_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: [ VL1 ]

View File

@ -0,0 +1,187 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: >
Template for deploying one VDU and one CP with scaling.
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
topology_template:
node_templates:
VDU1:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU1
description: VDU1 compute node
vdu_profile:
min_number_of_instances: 1
max_number_of_instances: 3
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 GiB
size: 1 GiB
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 MiB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GiB
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
vnic_type: direct-physical
requirements:
- virtual_binding: VDU1
VDU2:
type: tosca.nodes.nfv.Vdu.Compute
properties:
name: VDU2
description: VDU2 compute node
vdu_profile:
min_number_of_instances: 2
max_number_of_instances: 10
sw_image_data:
name: Software of VDU2
version: '0.4.0'
checksum:
algorithm: sha-256
hash: b9c3036539fd7a5f87a1bf38eb05fdde8b556a1a7e664dbeda90ed3cd74b4f9d
container_format: bare
disk_format: qcow2
min_disk: 1 GiB
size: 1 GiB
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 MiB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GiB
CP2:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 1
vnic_type: direct-physical
requirements:
- virtual_binding: VDU2
policies:
- scaling_aspects:
type: tosca.policies.nfv.ScalingAspects
properties:
aspects:
worker_instance1:
name: worker_instance1_aspect
description: worker_instance1 scaling aspect
max_scale_level: 2
step_deltas:
- delta_1
worker_instance2:
name: worker_instance2_aspect
description: worker_instance2 scaling aspect
max_scale_level: 4
step_deltas:
- delta_2
- 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_instance1
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_instance1:
scale_level: 0
instantiation_level_2:
description: Middle size
scale_info:
worker_instance1:
scale_level: 2
instantiation_level_3:
description: Largest size
scale_info:
worker_instance1:
scale_level: 4
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_initial_delta:
type: tosca.policies.nfv.VduInitialDelta
properties:
initial_delta:
number_of_instances: 2
targets: [ VDU2 ]
- VDU2_scaling_aspect_deltas:
type: tosca.policies.nfv.VduScalingAspectDeltas
properties:
aspect: worker_instance2
deltas:
delta_2:
number_of_instances: 2
targets: [ VDU2 ]
- VDU2_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 ]

View File

@ -0,0 +1,169 @@
tosca_definitions_version: tosca_simple_yaml_1_2
description: >
Template for deploying one VNF and one VDU and one CP and one VirtualLink and BlockStorage with scaling.
imports:
- etsi_nfv_sol001_common_types.yaml
- etsi_nfv_sol001_vnfd_types.yaml
topology_template:
inputs:
selected_flavour:
type: string
default: simple
description: VNF deployment flavour selected by the consumer. It is provided in the API
node_templates:
VNF:
type: tosca.nodes.nfv.VNF
properties:
flavour_id: { get_input: selected_flavour }
descriptor_id: b1bb0ce7-ebca-4fa7-95ed-4840d70a1177
provider: Sample company
product_name: Sample VNF
software_version: '1.0'
descriptor_version: '1.0'
vnfm_info:
- 00:sampleVNFM
flavour_description: A simple flavour
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
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 GiB
size: 1 GiB
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 MiB
virtual_cpu:
num_virtual_cpu: 1
virtual_local_storage:
- size_of_storage: 1 GiB
requirements:
- virtual_storage: VirtualStorage
VirtualStorage:
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
properties:
virtual_block_storage_data:
size_of_storage: 30 GiB
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 GiB
min_ram: 8192 MiB
size: 2 GiB
artifacts:
sw_image:
type: tosca.artifacts.nfv.SwImage
file: cirros-0.4.0-x86_64-disk.qcow2
CP1:
type: tosca.nodes.nfv.VduCp
properties:
layer_protocols: [ ipv4 ]
order: 0
requirements:
- virtual_binding: VDU1
- virtual_link: VL1
VL1:
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
- 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 ]

View File

@ -1,5 +1,5 @@
heat_template_version: 2013-05-23
description: Tacker Scaling template
description: Scaling template
resources:
my_server_1:
type: OS::Nova::Server

View File

@ -0,0 +1,37 @@
heat_template_version: 2013-05-23
description: >
Template for scaling which deltas is not defined in tosca.policies.nfv.VduScalingAspectDeltas.
(Defined delta_2 in tosca.policies.nfv.ScalingAspects,
but defined delta_1 in tosca.policies.nfv.VduScalingAspectDeltas.)
In Addition, the following properties are not set in
<aspect_name>_scale_in and <aspect_name>_scale_out nodes.
->scaling_adjustment
parameters: {}
resources:
VDU1_flavor:
type: OS::Nova::Flavor
properties:
ram: 512
vcpus: 1
disk: 1
worker_instance:
type: OS::Heat::AutoScalingGroup
properties:
resource:
type: worker_instance.hot.yaml
properties:
vdu1_flavor_id: { get_resource: VDU1_flavor }
desired_capacity: DESIRED_CAPACITY
worker_instance_scale_out:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
worker_instance_scale_in:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
outputs: {}

View File

@ -0,0 +1,19 @@
heat_template_version: 2013-05-23
description: Scaling template
parameters:
vdu1_flavor_id:
type: string
resources:
CP1:
type: OS::Neutron::Port
properties:
network: #ADD_YOUR_NETWORK_HERE
binding:vnic_type: direct-physical
VDU1:
type: OS::Nova::Server
properties:
flavor: { get_param: vdu1_flavor_id }
name: VDU1
image: #ADD_YOUR_IMAGE_HERE
networks:
- port: { get_resource: CP1 }

View File

@ -0,0 +1,43 @@
heat_template_version: 2013-05-23
description: >
Template for scaling which targets is not set in tosca.policies.nfv.VduScalingAspectDeltas.
The following nodes are not set in hot.
->OS::Heat::AutoScalingGroup
And create empty <aspect_name>.yaml.
In Addition, the following properties are not set in
<aspect_name>_scale_in and <aspect_name>_scale_out nodes.
->scaling_adjustment
parameters: {}
resources:
CP1:
type: OS::Neutron::Port
properties:
network: #ADD_YOUR_NETWORK_HERE
binding:vnic_type: direct-physical
VDU1:
type: OS::Nova::Server
properties:
flavor: { get_resource: VDU1_flavor }
name: VDU1
image: #ADD_YOUR_IMAGE_HERE
networks:
- port: { get_resource: CP1 }
VDU1_flavor:
type: OS::Nova::Flavor
properties:
ram: 512
vcpus: 1
disk: 1
worker_instance_scale_out:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
worker_instance_scale_in:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
outputs: {}

View File

@ -0,0 +1,3 @@
heat_template_version: 2013-05-23
description: Scaling template
resources: {}

View File

@ -0,0 +1,37 @@
heat_template_version: 2013-05-23
description: >
Template for scaling which targets is not set in tosca.policies.nfv.VduInitialDelta.
The following properties are not set in <aspect_name>.
->min_size
->max_size
parameters: {}
resources:
VDU1_flavor:
type: OS::Nova::Flavor
properties:
ram: 512
vcpus: 1
disk: 1
worker_instance:
type: OS::Heat::AutoScalingGroup
properties:
resource:
type: worker_instance.hot.yaml
properties:
vdu1_flavor_id: { get_resource: VDU1_flavor }
desired_capacity: DESIRED_CAPACITY
worker_instance_scale_out:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
scaling_adjustment: 1
worker_instance_scale_in:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
scaling_adjustment: -1
outputs: {}

View File

@ -0,0 +1,19 @@
heat_template_version: 2013-05-23
description: Scaling template
parameters:
vdu1_flavor_id:
type: string
resources:
CP1:
type: OS::Neutron::Port
properties:
network: #ADD_YOUR_NETWORK_HERE
binding:vnic_type: direct-physical
VDU1:
type: OS::Nova::Server
properties:
flavor: { get_param: vdu1_flavor_id }
name: VDU1
image: #ADD_YOUR_IMAGE_HERE
networks:
- port: { get_resource: CP1 }

View File

@ -0,0 +1,61 @@
heat_template_version: 2013-05-23
description: >
Template for deploying two VDU and two CP and one VirtualLink with scaling.
parameters: {}
resources:
VDU1_flavor:
type: OS::Nova::Flavor
properties:
ram: 512
vcpus: 1
disk: 1
VDU2_flavor:
type: OS::Nova::Flavor
properties:
ram: 512
vcpus: 1
disk: 1
VL1:
type: OS::Neutron::Net
properties:
qos_policy: { get_resource: VL1_qospolicy }
VL1_subnet:
type: OS::Neutron::Subnet
properties:
network: { get_resource: VL1 }
ip_version: 4
cidr: 11.11.0.0/24
VL1_bandwidth:
type: OS::Neutron::QoSBandwidthLimitRule
properties:
max_kbps: 1024
policy: { get_resource: VL1_qospolicy }
VL1_qospolicy:
type: OS::Neutron::QoSPolicy
worker_instance:
type: OS::Heat::AutoScalingGroup
properties:
min_size: 1
max_size: 3
resource:
type: worker_instance.hot.yaml
properties:
vl1_id: { get_resource: VL1 }
vdu1_flavor_id: { get_resource: VDU1_flavor }
vdu2_flavor_id: { get_resource: VDU2_flavor }
desired_capacity: DESIRED_CAPACITY
worker_instance_scale_out:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
scaling_adjustment: 1
worker_instance_scale_in:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
scaling_adjustment: -1
outputs: {}

View File

@ -0,0 +1,34 @@
heat_template_version: 2013-05-23
description: Scaling template
parameters:
vl1_id:
type: string
vdu1_flavor_id:
type: string
vdu2_flavor_id:
type: string
resources:
CP1:
type: OS::Neutron::Port
properties:
network: { get_param: vl1_id }
VDU1:
type: OS::Nova::Server
properties:
flavor: { get_param: vdu1_flavor_id }
name: VDU1
image: #ADD_YOUR_IMAGE_HERE
networks:
- port: { get_resource: CP1 }
CP2:
type: OS::Neutron::Port
properties:
network: #ADD_YOUR_NETWORK_HERE
VDU2:
type: OS::Nova::Server
properties:
flavor: { get_param: vdu2_flavor_id }
name: VDU2
image: #ADD_YOUR_IMAGE_HERE
networks:
- port: { get_resource: CP2 }

View File

@ -0,0 +1,67 @@
heat_template_version: 2013-05-23
description: >
Template for deploying one VDU and one CP with scaling.
parameters: {}
resources:
VDU1_flavor:
type: OS::Nova::Flavor
properties:
ram: 512
vcpus: 1
disk: 1
worker_instance1:
type: OS::Heat::AutoScalingGroup
properties:
min_size: 1
max_size: 3
resource:
type: worker_instance1.hot.yaml
properties:
vdu1_flavor_id: { get_resource: VDU1_flavor }
desired_capacity: DESIRED_CAPACITY
worker_instance1_scale_out:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance1
scaling_adjustment: 1
worker_instance1_scale_in:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance1
scaling_adjustment: -1
VDU2_flavor:
type: OS::Nova::Flavor
properties:
ram: 512
vcpus: 1
disk: 1
worker_instance2:
type: OS::Heat::AutoScalingGroup
properties:
min_size: 2
max_size: 10
resource:
type: worker_instance2.hot.yaml
properties:
vdu2_flavor_id: { get_resource: VDU2_flavor }
desired_capacity: DESIRED_CAPACITY
worker_instance2_scale_out:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance2
scaling_adjustment: 2
worker_instance2_scale_in:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance2
scaling_adjustment: -2
outputs: {}

View File

@ -0,0 +1,19 @@
heat_template_version: 2013-05-23
description: Scaling template
parameters:
vdu1_flavor_id:
type: string
resources:
CP1:
type: OS::Neutron::Port
properties:
network: #ADD_YOUR_NETWORK_HERE
binding:vnic_type: direct-physical
VDU1:
type: OS::Nova::Server
properties:
flavor: { get_param: vdu1_flavor_id }
name: VDU1
image: #ADD_YOUR_IMAGE_HERE
networks:
- port: { get_resource: CP1 }

View File

@ -0,0 +1,19 @@
heat_template_version: 2013-05-23
description: Scaling template
parameters:
vdu2_flavor_id:
type: string
resources:
CP2:
type: OS::Neutron::Port
properties:
network: #ADD_YOUR_NETWORK_HERE
binding:vnic_type: direct-physical
VDU2:
type: OS::Nova::Server
properties:
flavor: { get_param: vdu2_flavor_id }
name: VDU2
image: #ADD_YOUR_IMAGE_HERE
networks:
- port: { get_resource: CP2 }

View File

@ -0,0 +1,59 @@
heat_template_version: 2013-05-23
description: >
Template for deploying one VNF and one VDU and one CP and one VirtualLink and BlockStorage with scaling.
parameters:
selected_flavour:
type: string
description: VNF deployment flavour selected by the consumer. It is provided in
the API
default: simple
resources:
VDU1_flavor:
type: OS::Nova::Flavor
properties:
ram: 512
vcpus: 1
disk: 1
VL1:
type: OS::Neutron::Net
properties:
qos_policy: { get_resource: VL1_qospolicy }
VL1_subnet:
type: OS::Neutron::Subnet
properties:
network: { get_resource: VL1 }
ip_version: 4
cidr: 11.11.0.0/24
VL1_bandwidth:
type: OS::Neutron::QoSBandwidthLimitRule
properties:
max_kbps: 1024
policy: { get_resource: VL1_qospolicy }
VL1_qospolicy:
type: OS::Neutron::QoSPolicy
worker_instance:
type: OS::Heat::AutoScalingGroup
properties:
min_size: 1
max_size: 3
resource:
type: worker_instance.hot.yaml
properties:
vl1_id: { get_resource: VL1 }
vdu1_flavor_id: { get_resource: VDU1_flavor }
desired_capacity: DESIRED_CAPACITY
worker_instance_scale_out:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
scaling_adjustment: 1
worker_instance_scale_in:
type: OS::Heat::ScalingPolicy
properties:
adjustment_type: change_in_capacity
auto_scaling_group_id:
get_resource: worker_instance
scaling_adjustment: -1
outputs: {}

View File

@ -0,0 +1,27 @@
heat_template_version: 2013-05-23
description: Scaling template
parameters:
vl1_id:
type: string
vdu1_flavor_id:
type: string
resources:
CP1:
type: OS::Neutron::Port
properties:
network: { get_param: vl1_id }
VDU1:
type: OS::Nova::Server
properties:
flavor: { get_param: vdu1_flavor_id }
name: VDU1
image: #ADD_YOUR_IMAGE_HERE
networks:
- port: { get_resource: CP1 }
block_device_mapping_v2:
- volume_id: { get_resource: VirtualStorage }
VirtualStorage:
type: OS::Cinder::Volume
properties:
size: 30
image: #ADD_YOUR_IMAGE_HERE

View File

@ -1,5 +1,5 @@
heat_template_version: 2013-05-23
description: Tacker Scaling template
description: Scaling template
resources:
my_server_1:
type: OS::Nova::Server

View File

@ -1,5 +1,5 @@
heat_template_version: 2013-05-23
description: Tacker Scaling template
description: Scaling template
resources:
VDU1:
type: OS::Nova::Server

View File

@ -1,5 +1,5 @@
heat_template_version: 2013-05-23
description: Tacker Scaling template
description: Scaling template
parameters:
flavor: {type: string, default: m1.tiny, description: Flavor Information}

View File

@ -1,6 +1,6 @@
heat_template_version: 2013-05-23
description: Tacker Scaling template
description: Scaling template
parameters:
flavor: {type: string, description: Flavor Information}

View File

@ -200,3 +200,134 @@ class EtsiToscaHotTranslationTest(TestCase):
'hot_nfv_blockstorage.yaml',
]
self._test_successful_translation(tosca_file, hot_files, params={})
def test_hot_translate_etsi_nfv_vnf_vdu_cp_vl_blockstorage_with_scaling(
self):
tosca_file = '../tests/data/etsi_nfv/' \
'tosca_nfv_vnf_vdu_cp_vl_blockstorage_with_scaling.yaml'
hot_files = [
'../tests/data/hot_output/etsi_nfv/'
'vnf_vdu_cp_vl_blockstorage_with_scaling/'
'hot_nfv_vnf_vdu_cp_vl_blockstorage_with_scaling.yaml',
'../tests/data/hot_output/etsi_nfv/'
'vnf_vdu_cp_vl_blockstorage_with_scaling/'
'worker_instance.hot.yaml',
]
self._test_successful_translation(tosca_file, hot_files, params={})
def test_hot_translate_etsi_nfv_vdu_cp_vl_with_mixed_scaling(
self):
tosca_file = '../tests/data/etsi_nfv/' \
'tosca_nfv_vdu_cp_vl_with_mixed_scaling.yaml'
hot_files = [
'../tests/data/hot_output/etsi_nfv/'
'vdu_cp_vl_with_mixed_scaling/'
'hot_nfv_vdu_cp_vl_with_mixed_scaling.yaml',
'../tests/data/hot_output/etsi_nfv/'
'vdu_cp_vl_with_mixed_scaling/'
'worker_instance.hot.yaml',
]
self._test_successful_translation(tosca_file, hot_files, params={})
def test_hot_translate_etsi_nfv_vdu_cp_with_scaling_multi_aspects(
self):
tosca_file = '../tests/data/etsi_nfv/' \
'tosca_nfv_vdu_cp_with_scaling_multi_aspects.yaml'
hot_files = [
'../tests/data/hot_output/etsi_nfv/'
'vdu_cp_with_scaling_multi_aspects/'
'hot_nfv_vdu_cp_with_scaling_multi_aspects.yaml',
'../tests/data/hot_output/etsi_nfv/'
'vdu_cp_with_scaling_multi_aspects/'
'worker_instance1.hot.yaml',
'../tests/data/hot_output/etsi_nfv/'
'vdu_cp_with_scaling_multi_aspects/'
'worker_instance2.hot.yaml',
]
self._test_successful_translation(tosca_file, hot_files, params={})
def test_hot_translate_etsi_nfv_scaling_non_target_vdu_in_initial_delta(
self):
aspect_name = 'worker_instance'
vdu_name = 'VDU1'
tosca_file = '../tests/data/etsi_nfv/' \
'tosca_nfv_scaling_non_target_vdu_in_initial_delta.yaml'
hot_files = [
'../tests/data/hot_output/etsi_nfv/'
'scaling_non_target_vdu_in_initial_delta/'
'hot_nfv_scaling_non_target_vdu_in_initial_delta.yaml',
'../tests/data/hot_output/etsi_nfv/'
'scaling_non_target_vdu_in_initial_delta/'
'worker_instance.hot.yaml',
]
expected_msgs = (
'Can not set the required properties '
'min_size and max_size on HOT.'
'aspect_name:%s' % aspect_name,
)
expected_msgs = (
'No min_size or(and) max_size is found for '
'aspect_name:%s, VDU:%s' % (
aspect_name, vdu_name)
)
self._test_successful_translation(tosca_file, hot_files, params={})
for expected_msg in expected_msgs:
self.assertIn(
expected_msg,
self.log_fixture.output
)
def test_hot_translate_etsi_nfv_scaling_non_target_vdu_in_aspect_delta(
self):
aspect_name = 'worker_instance'
vdu_name = None
delta_name = None
tosca_file = '../tests/data/etsi_nfv/' \
'tosca_nfv_scaling_non_target_vdu_in_aspect_delta.yaml'
hot_files = [
'../tests/data/hot_output/etsi_nfv/'
'scaling_non_target_vdu_in_aspect_delta/'
'hot_nfv_scaling_non_target_vdu_in_aspect_delta.yaml',
'../tests/data/hot_output/etsi_nfv/'
'scaling_non_target_vdu_in_aspect_delta/'
'worker_instance.hot.yaml',
]
expected_msgs = (
'Can not create %s node '
'because target vdu does not defined.'
% aspect_name,
'No ScalingAspectDelta for %s of %s, %s is '
'found' % (vdu_name, aspect_name, delta_name)
)
self._test_successful_translation(tosca_file, hot_files, params={})
for expected_msg in expected_msgs:
self.assertIn(
expected_msg,
self.log_fixture.output
)
def test_hot_translate_etsi_nfv_scaling_non_deltas_in_aspect_delta(self):
aspect_name = 'worker_instance'
vdu_name = 'VDU1'
delta_name = 'delta_2'
tosca_file = '../tests/data/etsi_nfv/' \
'tosca_nfv_scaling_non_deltas_in_aspect_delta.yaml'
hot_files = [
'../tests/data/hot_output/etsi_nfv/'
'scaling_non_deltas_in_aspect_delta/'
'hot_nfv_scaling_non_deltas_in_aspect_delta.yaml',
'../tests/data/hot_output/etsi_nfv/'
'scaling_non_deltas_in_aspect_delta/'
'worker_instance.hot.yaml',
]
expected_msgs = (
'No ScalingAspectDelta for %s of %s, %s is '
'found' % (vdu_name, aspect_name, delta_name)
)
self._test_successful_translation(tosca_file, hot_files, params={})
for expected_msg in expected_msgs:
self.assertIn(
expected_msg,
self.log_fixture.output
)

View File

@ -38,7 +38,13 @@ class TranslateNodeTemplatesTest(TestCase):
'tosca.nodes.nfv.Vdu.Compute',
'tosca.nodes.nfv.Vdu.VirtualBlockStorage',
'tosca.nodes.nfv.VduCp',
'tosca.nodes.nfv.VnfVirtualLink'
'tosca.nodes.nfv.VnfVirtualLink',
'tosca.policies.nfv.InstantiationLevels',
'tosca.policies.nfv.ScalingAspects',
'tosca.policies.nfv.VduInitialDelta',
'tosca.policies.nfv.VduInstantiationLevels',
'tosca.policies.nfv.VduScalingAspectDeltas',
'tosca.policies.nfv.VirtualLinkInstantiationLevels'
]
actual_type_list = list(_generate_type_map())