Refactor scaling and monitoring policies in Tacker
1. scaling and monitoring policy nodes got failed From tosca-parser 0.8.0, tosca nodes required to be validated. Unfortunately, the scaling and monitoring policies are not fully leveraged tosca-parser. This patch will fix this issue. 2. Multiple alarm actions support Closes-bug: #1682098 Change-Id: I29cb35edfe2447628fa93c64583e5cb4f7bee2f8
This commit is contained in:
@@ -248,9 +248,9 @@ function configure_tacker {
|
|||||||
|
|
||||||
# Experimental settings for monitor alarm auth settings,
|
# Experimental settings for monitor alarm auth settings,
|
||||||
# Will be changed according to new implementation.
|
# Will be changed according to new implementation.
|
||||||
iniset $TACKER_CONF alarm_auth username tacker
|
iniset $TACKER_CONF alarm_auth username admin
|
||||||
iniset $TACKER_CONF alarm_auth password "$SERVICE_PASSWORD"
|
iniset $TACKER_CONF alarm_auth password "$ADMIN_PASSWORD"
|
||||||
iniset $TACKER_CONF alarm_auth project_name "$SERVICE_PROJECT_NAME"
|
iniset $TACKER_CONF alarm_auth project_name admin
|
||||||
iniset $TACKER_CONF alarm_auth url http://$SERVICE_HOST:35357/v3
|
iniset $TACKER_CONF alarm_auth url http://$SERVICE_HOST:35357/v3
|
||||||
|
|
||||||
echo "Creating bridge"
|
echo "Creating bridge"
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||||
|
description: Demo example
|
||||||
|
|
||||||
|
metadata:
|
||||||
|
template_name: sample-tosca-vnfd
|
||||||
|
|
||||||
|
topology_template:
|
||||||
|
node_templates:
|
||||||
|
VDU1:
|
||||||
|
type: tosca.nodes.nfv.VDU.Tacker
|
||||||
|
capabilities:
|
||||||
|
nfv_compute:
|
||||||
|
properties:
|
||||||
|
disk_size: 1 GB
|
||||||
|
mem_size: 512 MB
|
||||||
|
num_cpus: 2
|
||||||
|
properties:
|
||||||
|
image: cirros-0.3.5-x86_64-disk
|
||||||
|
mgmt_driver: noop
|
||||||
|
availability_zone: nova
|
||||||
|
metadata: {metering.vnf: VDU1}
|
||||||
|
|
||||||
|
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: net_mgmt
|
||||||
|
vendor: Tacker
|
||||||
|
|
||||||
|
policies:
|
||||||
|
- vdu1_cpu_usage_monitoring_policy:
|
||||||
|
type: tosca.policies.tacker.Alarming
|
||||||
|
triggers:
|
||||||
|
vdu_hcpu_usage_respawning:
|
||||||
|
event_type:
|
||||||
|
type: tosca.events.resource.utilization
|
||||||
|
implementation: ceilometer
|
||||||
|
meter_name: cpu_util
|
||||||
|
condition:
|
||||||
|
threshold: 50
|
||||||
|
constraint: utilization greater_than 50%
|
||||||
|
period: 600
|
||||||
|
evaluations: 1
|
||||||
|
method: average
|
||||||
|
comparison_operator: gt
|
||||||
|
metadata: VDU1
|
||||||
|
action: [respawn, log]
|
||||||
@@ -45,13 +45,13 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: VDU1
|
metadata: VDU1
|
||||||
actions: [respawn]
|
action: [respawn]
|
||||||
|
|||||||
@@ -64,13 +64,13 @@ topology_template:
|
|||||||
policies:
|
policies:
|
||||||
- SP1:
|
- SP1:
|
||||||
type: tosca.policies.tacker.Scaling
|
type: tosca.policies.tacker.Scaling
|
||||||
|
targets: [VDU1,VDU2]
|
||||||
properties:
|
properties:
|
||||||
increment: 1
|
increment: 1
|
||||||
cooldown: 120
|
cooldown: 120
|
||||||
min_instances: 1
|
min_instances: 1
|
||||||
max_instances: 3
|
max_instances: 3
|
||||||
default_instances: 2
|
default_instances: 2
|
||||||
targets: [VDU1,VDU2]
|
|
||||||
|
|
||||||
- vdu_cpu_usage_monitoring_policy:
|
- vdu_cpu_usage_monitoring_policy:
|
||||||
type: tosca.policies.tacker.Alarming
|
type: tosca.policies.tacker.Alarming
|
||||||
@@ -79,29 +79,28 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: SG1
|
metadata: SG1
|
||||||
actions: [SP1]
|
action: [SP1]
|
||||||
|
|
||||||
vdu_lcpu_usage_scaling_in:
|
vdu_lcpu_usage_scaling_in:
|
||||||
targets: [VDU1, VDU2]
|
|
||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 10
|
threshold: 10
|
||||||
constraint: utilization less_than 10%
|
constraint: utilization less_than 10%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: lt
|
comparison_operator: lt
|
||||||
metadata: SG1
|
metadata: SG1
|
||||||
actions: [SP1]
|
action: [SP1]
|
||||||
|
|||||||
@@ -56,10 +56,10 @@ topology_template:
|
|||||||
policies:
|
policies:
|
||||||
- SP1:
|
- SP1:
|
||||||
type: tosca.policies.tacker.Scaling
|
type: tosca.policies.tacker.Scaling
|
||||||
|
targets: [VDU1, VDU2]
|
||||||
properties:
|
properties:
|
||||||
increment: 1
|
increment: 1
|
||||||
cooldown: 120
|
cooldown: 120
|
||||||
min_instances: 1
|
min_instances: 1
|
||||||
max_instances: 3
|
max_instances: 3
|
||||||
default_instances: 2
|
default_instances: 2
|
||||||
targets: [VDU1, VDU2]
|
|
||||||
|
|||||||
@@ -63,7 +63,7 @@ tacker.tacker.alarm_monitor.drivers =
|
|||||||
tacker.tacker.policy.actions =
|
tacker.tacker.policy.actions =
|
||||||
autoscaling = tacker.vnfm.policy_actions.autoscaling.autoscaling:VNFActionAutoscaling
|
autoscaling = tacker.vnfm.policy_actions.autoscaling.autoscaling:VNFActionAutoscaling
|
||||||
respawn = tacker.vnfm.policy_actions.respawn.respawn:VNFActionRespawn
|
respawn = tacker.vnfm.policy_actions.respawn.respawn:VNFActionRespawn
|
||||||
log_only = tacker.vnfm.policy_actions.log.log:VNFActionLogOnly
|
log = tacker.vnfm.policy_actions.log.log:VNFActionLog
|
||||||
log_and_kill = tacker.vnfm.policy_actions.log.log:VNFActionLogAndKill
|
log_and_kill = tacker.vnfm.policy_actions.log.log:VNFActionLogAndKill
|
||||||
oslo.config.opts =
|
oslo.config.opts =
|
||||||
tacker.common.config = tacker.common.config:config_opts
|
tacker.common.config = tacker.common.config:config_opts
|
||||||
|
|||||||
@@ -14,7 +14,7 @@
|
|||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
from six.moves.urllib import parse as urlparse
|
from six.moves.urllib import parse
|
||||||
from tacker.vnfm.monitor_drivers.token import Token
|
from tacker.vnfm.monitor_drivers.token import Token
|
||||||
from tacker import wsgi
|
from tacker import wsgi
|
||||||
# check alarm url with db --> move to plugin
|
# check alarm url with db --> move to plugin
|
||||||
@@ -23,14 +23,12 @@ from tacker import wsgi
|
|||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
|
|
||||||
OPTS = [
|
OPTS = [
|
||||||
cfg.StrOpt('username', default='tacker',
|
cfg.StrOpt('username', default='admin',
|
||||||
help=_('User name for alarm monitoring')),
|
help=_('User name for alarm monitoring')),
|
||||||
cfg.StrOpt('password', default='nomoresecret',
|
cfg.StrOpt('password', default='devstack',
|
||||||
help=_('password for alarm monitoring')),
|
help=_('password for alarm monitoring')),
|
||||||
cfg.StrOpt('project_name', default='service',
|
cfg.StrOpt('project_name', default='admin',
|
||||||
help=_('project name for alarm monitoring')),
|
help=_('project name for alarm monitoring')),
|
||||||
cfg.StrOpt('url', default='http://localhost:35357/v3',
|
|
||||||
help=_('url for alarm monitoring')),
|
|
||||||
]
|
]
|
||||||
|
|
||||||
cfg.CONF.register_opts(OPTS, 'alarm_auth')
|
cfg.CONF.register_opts(OPTS, 'alarm_auth')
|
||||||
@@ -49,10 +47,11 @@ class AlarmReceiver(wsgi.Middleware):
|
|||||||
if not self.handle_url(url):
|
if not self.handle_url(url):
|
||||||
return
|
return
|
||||||
prefix, info, params = self.handle_url(req.url)
|
prefix, info, params = self.handle_url(req.url)
|
||||||
|
auth = cfg.CONF.keystone_authtoken
|
||||||
token = Token(username=cfg.CONF.alarm_auth.username,
|
token = Token(username=cfg.CONF.alarm_auth.username,
|
||||||
password=cfg.CONF.alarm_auth.password,
|
password=cfg.CONF.alarm_auth.password,
|
||||||
project_name=cfg.CONF.alarm_auth.project_name,
|
project_name=cfg.CONF.alarm_auth.project_name,
|
||||||
auth_url=cfg.CONF.alarm_auth.url,
|
auth_url=auth.auth_url + '/v3',
|
||||||
user_domain_name='default',
|
user_domain_name='default',
|
||||||
project_domain_name='default')
|
project_domain_name='default')
|
||||||
|
|
||||||
@@ -79,14 +78,16 @@ class AlarmReceiver(wsgi.Middleware):
|
|||||||
|
|
||||||
def handle_url(self, url):
|
def handle_url(self, url):
|
||||||
# alarm_url = 'http://host:port/v1.0/vnfs/vnf-uuid/mon-policy-name/action-name/8ef785' # noqa
|
# alarm_url = 'http://host:port/v1.0/vnfs/vnf-uuid/mon-policy-name/action-name/8ef785' # noqa
|
||||||
parts = urlparse.urlparse(url)
|
parts = parse.urlparse(url)
|
||||||
p = parts.path.split('/')
|
p = parts.path.split('/')
|
||||||
if len(p) != 7:
|
if len(p) != 7:
|
||||||
return None
|
return None
|
||||||
|
|
||||||
if any((p[0] != '', p[2] != 'vnfs')):
|
if any((p[0] != '', p[2] != 'vnfs')):
|
||||||
return None
|
return None
|
||||||
qs = urlparse.parse_qs(parts.query)
|
# decode action name: respawn%25log
|
||||||
|
p[5] = parse.unquote(p[5])
|
||||||
|
qs = parse.parse_qs(parts.query)
|
||||||
params = dict((k, v[0]) for k, v in qs.items())
|
params = dict((k, v[0]) for k, v in qs.items())
|
||||||
prefix_url = '/%(collec)s/%(vnf_uuid)s/' % {'collec': p[2],
|
prefix_url = '/%(collec)s/%(vnf_uuid)s/' % {'collec': p[2],
|
||||||
'vnf_uuid': p[3]}
|
'vnf_uuid': p[3]}
|
||||||
|
|||||||
@@ -45,13 +45,13 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: VDU1
|
metadata: VDU1
|
||||||
actions: [respawn]
|
action: [respawn]
|
||||||
|
|||||||
@@ -40,13 +40,13 @@ topology_template:
|
|||||||
policies:
|
policies:
|
||||||
- SP1:
|
- SP1:
|
||||||
type: tosca.policies.tacker.Scaling
|
type: tosca.policies.tacker.Scaling
|
||||||
|
targets: [VDU1]
|
||||||
properties:
|
properties:
|
||||||
increment: 1
|
increment: 1
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
min_instances: 1
|
min_instances: 1
|
||||||
max_instances: 3
|
max_instances: 3
|
||||||
default_instances: 2
|
default_instances: 2
|
||||||
targets: [VDU1]
|
|
||||||
|
|
||||||
- vdu_cpu_usage_monitoring_policy:
|
- vdu_cpu_usage_monitoring_policy:
|
||||||
type: tosca.policies.tacker.Alarming
|
type: tosca.policies.tacker.Alarming
|
||||||
@@ -55,28 +55,28 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: SG1
|
metadata: SG1
|
||||||
actions: [SP1]
|
action: [SP1]
|
||||||
|
|
||||||
vdu_hcpu_usage_scaling_in:
|
vdu_hcpu_usage_scaling_in:
|
||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 10
|
threshold: 10
|
||||||
constraint: utilization less_than 10%
|
constraint: utilization less_than 10%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: lt
|
comparison_operator: lt
|
||||||
metadata: SG1
|
metadata: SG1
|
||||||
actions: [SP1]
|
action: [SP1]
|
||||||
|
|||||||
@@ -41,10 +41,10 @@ topology_template:
|
|||||||
policies:
|
policies:
|
||||||
- SP1:
|
- SP1:
|
||||||
type: tosca.policies.tacker.Scaling
|
type: tosca.policies.tacker.Scaling
|
||||||
|
targets: [VDU1]
|
||||||
properties:
|
properties:
|
||||||
increment: 1
|
increment: 1
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
min_instances: 1
|
min_instances: 1
|
||||||
max_instances: 3
|
max_instances: 3
|
||||||
default_instances: 2
|
default_instances: 2
|
||||||
targets: [VDU1]
|
|
||||||
|
|||||||
@@ -75,9 +75,9 @@ class VnfTestAlarmMonitor(base.BaseTackerTest):
|
|||||||
if policy['type'] == constants.POLICY_ALARMING:
|
if policy['type'] == constants.POLICY_ALARMING:
|
||||||
triggers = policy['triggers']
|
triggers = policy['triggers']
|
||||||
for trigger_name, trigger_dict in triggers.items():
|
for trigger_name, trigger_dict in triggers.items():
|
||||||
policy_action_list = trigger_dict['actions']
|
policy_action_list = trigger_dict['action']
|
||||||
for policy_action in policy_action_list:
|
for policy_action_name in policy_action_list:
|
||||||
mon_policy[trigger_name] = policy_action
|
mon_policy[trigger_name] = policy_action_name
|
||||||
return mon_policy
|
return mon_policy
|
||||||
|
|
||||||
def verify_policy(policy_dict, kw_policy):
|
def verify_policy(policy_dict, kw_policy):
|
||||||
@@ -139,13 +139,12 @@ class VnfTestAlarmMonitor(base.BaseTackerTest):
|
|||||||
self.addCleanup(self.wait_until_vnf_delete, vnf_id,
|
self.addCleanup(self.wait_until_vnf_delete, vnf_id,
|
||||||
constants.VNF_CIRROS_DELETE_TIMEOUT)
|
constants.VNF_CIRROS_DELETE_TIMEOUT)
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
|
||||||
def test_vnf_alarm_respawn(self):
|
def test_vnf_alarm_respawn(self):
|
||||||
self._test_vnf_tosca_alarm(
|
self._test_vnf_tosca_alarm(
|
||||||
'sample-tosca-alarm-respawn.yaml',
|
'sample-tosca-alarm-respawn.yaml',
|
||||||
'alarm and respawn vnf')
|
'alarm and respawn vnf')
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
@unittest.skip("Skip and wait for releasing Heat Translator")
|
||||||
def test_vnf_alarm_scale(self):
|
def test_vnf_alarm_scale(self):
|
||||||
self._test_vnf_tosca_alarm(
|
self._test_vnf_tosca_alarm(
|
||||||
'sample-tosca-alarm-scale.yaml',
|
'sample-tosca-alarm-scale.yaml',
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ CONF = cfg.CONF
|
|||||||
|
|
||||||
|
|
||||||
class VnfTestToscaScale(base.BaseTackerTest):
|
class VnfTestToscaScale(base.BaseTackerTest):
|
||||||
@unittest.skip("Related Bug 1682098")
|
@unittest.skip("Skip and wait for releasing Heat Translator")
|
||||||
def test_vnf_tosca_scale(self):
|
def test_vnf_tosca_scale(self):
|
||||||
data = dict()
|
data = dict()
|
||||||
data['tosca'] = read_file('sample-tosca-scale-all.yaml')
|
data['tosca'] = read_file('sample-tosca-scale-all.yaml')
|
||||||
@@ -71,7 +71,7 @@ class VnfTestToscaScale(base.BaseTackerTest):
|
|||||||
self.assertIn('VDU1', resources_list)
|
self.assertIn('VDU1', resources_list)
|
||||||
|
|
||||||
self.assertIn('CP1', resources_list)
|
self.assertIn('CP1', resources_list)
|
||||||
self.assertIn('G1', resources_list)
|
self.assertIn('SP1_group', resources_list)
|
||||||
|
|
||||||
def _scale(type, count):
|
def _scale(type, count):
|
||||||
body = {"scale": {'type': type, 'policy': 'SP1'}}
|
body = {"scale": {'type': type, 'policy': 'SP1'}}
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ vnfd_alarm_respawn_tosca_template = _get_template(
|
|||||||
'test_tosca_vnfd_alarm_respawn.yaml')
|
'test_tosca_vnfd_alarm_respawn.yaml')
|
||||||
vnfd_alarm_scale_tosca_template = _get_template(
|
vnfd_alarm_scale_tosca_template = _get_template(
|
||||||
'test_tosca_vnfd_alarm_scale.yaml')
|
'test_tosca_vnfd_alarm_scale.yaml')
|
||||||
|
vnfd_alarm_multi_actions_tosca_template = _get_template(
|
||||||
|
'test_tosca_vnfd_alarm_multi_actions.yaml')
|
||||||
nsd_tosca_template = yaml.safe_load(_get_template('tosca_nsd_template.yaml'))
|
nsd_tosca_template = yaml.safe_load(_get_template('tosca_nsd_template.yaml'))
|
||||||
vnffgd_wrong_cp_number_template = yaml.safe_load(_get_template(
|
vnffgd_wrong_cp_number_template = yaml.safe_load(_get_template(
|
||||||
'tosca_vnffgd_wrong_cp_number_template.yaml'))
|
'tosca_vnffgd_wrong_cp_number_template.yaml'))
|
||||||
|
|||||||
@@ -13,7 +13,6 @@
|
|||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import unittest
|
|
||||||
|
|
||||||
import testtools
|
import testtools
|
||||||
from toscaparser import tosca_template
|
from toscaparser import tosca_template
|
||||||
@@ -80,15 +79,12 @@ class TestSamples(testtools.TestCase):
|
|||||||
hot,
|
hot,
|
||||||
"Heat-translator failed to translate %s" % f)
|
"Heat-translator failed to translate %s" % f)
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
|
||||||
def test_scale_sample(self, tosca_file=['tosca-vnfd-scale.yaml']):
|
def test_scale_sample(self, tosca_file=['tosca-vnfd-scale.yaml']):
|
||||||
self._test_samples(tosca_file)
|
self._test_samples(tosca_file)
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
|
||||||
def test_alarm_sample(self, tosca_file=['tosca-vnfd-alarm-scale.yaml']):
|
def test_alarm_sample(self, tosca_file=['tosca-vnfd-alarm-scale.yaml']):
|
||||||
self._test_samples(tosca_file)
|
self._test_samples(tosca_file)
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
|
||||||
def test_list_samples(self,
|
def test_list_samples(self,
|
||||||
files=['tosca-vnfd-scale.yaml',
|
files=['tosca-vnfd-scale.yaml',
|
||||||
'tosca-vnfd-alarm-scale.yaml']):
|
'tosca-vnfd-alarm-scale.yaml']):
|
||||||
|
|||||||
@@ -1,24 +1,26 @@
|
|||||||
heat_template_version: 2013-05-23
|
|
||||||
description: 'sample-tosca-vnfd-scaling
|
|
||||||
|
|
||||||
'
|
|
||||||
outputs:
|
outputs:
|
||||||
mgmt_ip-VDU1:
|
mgmt_ip-VDU1:
|
||||||
value:
|
value:
|
||||||
get_attr: [CP1, fixed_ips, 0, ip_address]
|
get_attr: [CP1, fixed_ips, 0, ip_address]
|
||||||
parameters: {}
|
|
||||||
resources:
|
resources:
|
||||||
CP1:
|
|
||||||
properties: {network: net_mgmt, port_security_enabled: false}
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
VDU1:
|
VDU1:
|
||||||
|
type: OS::Nova::Server
|
||||||
properties:
|
properties:
|
||||||
availability_zone: nova
|
availability_zone: nova
|
||||||
config_drive: false
|
|
||||||
flavor: m1.tiny
|
|
||||||
image: cirros-0.3.5-x86_64-disk
|
|
||||||
metadata: {metering.vnf: SG1}
|
|
||||||
networks:
|
|
||||||
- port: {get_resource: CP1}
|
|
||||||
user_data_format: SOFTWARE_CONFIG
|
user_data_format: SOFTWARE_CONFIG
|
||||||
type: OS::Nova::Server
|
config_drive: false
|
||||||
|
networks:
|
||||||
|
- port: { get_resource: CP1 }
|
||||||
|
image: cirros-0.3.5-x86_64-disk
|
||||||
|
flavor: m1.tiny
|
||||||
|
metadata: {metering.vnf: SG1}
|
||||||
|
VL1:
|
||||||
|
type: OS::Neutron::Net
|
||||||
|
CP1:
|
||||||
|
type: OS::Neutron::Port
|
||||||
|
properties:
|
||||||
|
network: net_mgmt
|
||||||
|
port_security_enabled: false
|
||||||
|
heat_template_version: 2013-05-23
|
||||||
|
description: Tacker Scaling template
|
||||||
@@ -1,23 +1,25 @@
|
|||||||
heat_template_version: 2013-05-23
|
|
||||||
description: 'sample-tosca-vnfd-scaling
|
|
||||||
|
|
||||||
'
|
|
||||||
outputs:
|
outputs:
|
||||||
mgmt_ip-VDU1:
|
mgmt_ip-VDU1:
|
||||||
value:
|
value:
|
||||||
get_attr: [CP1, fixed_ips, 0, ip_address]
|
get_attr: [CP1, fixed_ips, 0, ip_address]
|
||||||
parameters: {}
|
|
||||||
resources:
|
resources:
|
||||||
CP1:
|
|
||||||
properties: {network: net_mgmt, port_security_enabled: false}
|
|
||||||
type: OS::Neutron::Port
|
|
||||||
VDU1:
|
VDU1:
|
||||||
|
type: OS::Nova::Server
|
||||||
properties:
|
properties:
|
||||||
availability_zone: nova
|
availability_zone: nova
|
||||||
config_drive: false
|
|
||||||
flavor: m1.tiny
|
|
||||||
image: cirros-0.3.5-x86_64-disk
|
|
||||||
networks:
|
|
||||||
- port: {get_resource: CP1}
|
|
||||||
user_data_format: SOFTWARE_CONFIG
|
user_data_format: SOFTWARE_CONFIG
|
||||||
type: OS::Nova::Server
|
config_drive: false
|
||||||
|
networks:
|
||||||
|
- port: { get_resource: CP1 }
|
||||||
|
image: cirros-0.3.5-x86_64-disk
|
||||||
|
flavor: m1.tiny
|
||||||
|
VL1:
|
||||||
|
type: OS::Neutron::Net
|
||||||
|
CP1:
|
||||||
|
type: OS::Neutron::Port
|
||||||
|
properties:
|
||||||
|
network: net_mgmt
|
||||||
|
port_security_enabled: false
|
||||||
|
heat_template_version: 2013-05-23
|
||||||
|
description: Tacker Scaling template
|
||||||
@@ -1,26 +1,30 @@
|
|||||||
heat_template_version: 2013-05-23
|
heat_template_version: 2013-05-23
|
||||||
description: Tacker scaling template
|
description: 'sample-tosca-vnfd-scaling
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
parameters: {}
|
parameters: {}
|
||||||
|
outputs: {}
|
||||||
resources:
|
resources:
|
||||||
G1:
|
SP1_group:
|
||||||
properties:
|
properties:
|
||||||
cooldown: 60
|
|
||||||
desired_capacity: 2
|
desired_capacity: 2
|
||||||
max_size: 3
|
max_size: 3
|
||||||
min_size: 1
|
min_size: 1
|
||||||
resource: {type: scaling.yaml}
|
cooldown: 60
|
||||||
|
resource: {type: SP1_res.yaml}
|
||||||
type: OS::Heat::AutoScalingGroup
|
type: OS::Heat::AutoScalingGroup
|
||||||
SP1_scale_in:
|
SP1_scale_in:
|
||||||
properties:
|
properties:
|
||||||
adjustment_type: change_in_capacity
|
adjustment_type: change_in_capacity
|
||||||
auto_scaling_group_id: {get_resource: G1}
|
auto_scaling_group_id: {get_resource: SP1_group}
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
scaling_adjustment: '-1'
|
scaling_adjustment: -1
|
||||||
type: OS::Heat::ScalingPolicy
|
type: OS::Heat::ScalingPolicy
|
||||||
SP1_scale_out:
|
SP1_scale_out:
|
||||||
properties:
|
properties:
|
||||||
adjustment_type: change_in_capacity
|
adjustment_type: change_in_capacity
|
||||||
auto_scaling_group_id: {get_resource: G1}
|
auto_scaling_group_id: {get_resource: SP1_group}
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
scaling_adjustment: 1
|
scaling_adjustment: 1
|
||||||
type: OS::Heat::ScalingPolicy
|
type: OS::Heat::ScalingPolicy
|
||||||
|
|||||||
@@ -35,7 +35,7 @@ resources:
|
|||||||
meter_name: cpu_util
|
meter_name: cpu_util
|
||||||
threshold: 50
|
threshold: 50
|
||||||
period: 60
|
period: 60
|
||||||
statistic: average
|
statistic: avg
|
||||||
evaluation_periods: 1
|
evaluation_periods: 1
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
'matching_metadata': {'metadata.user_metadata.vnf': 'VDU1'}
|
'matching_metadata': {'metadata.user_metadata.vnf': 'VDU1'}
|
||||||
|
|||||||
@@ -36,7 +36,7 @@ resources:
|
|||||||
meter_name: cpu_util
|
meter_name: cpu_util
|
||||||
threshold: 50
|
threshold: 50
|
||||||
period: 60
|
period: 60
|
||||||
statistic: average
|
statistic: avg
|
||||||
evaluation_periods: 1
|
evaluation_periods: 1
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
'matching_metadata': {'metadata.user_metadata.vnf': 'VDU1'}
|
'matching_metadata': {'metadata.user_metadata.vnf': 'VDU1'}
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
heat_template_version: 2013-05-23
|
heat_template_version: 2013-05-23
|
||||||
description: Tacker scaling template
|
description: 'sample-tosca-vnfd-scaling
|
||||||
|
|
||||||
|
'
|
||||||
|
|
||||||
parameters: {}
|
parameters: {}
|
||||||
|
outputs: {}
|
||||||
resources:
|
resources:
|
||||||
G1:
|
SP1_group:
|
||||||
properties:
|
properties:
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
desired_capacity: 2
|
desired_capacity: 2
|
||||||
max_size: 3
|
max_size: 3
|
||||||
min_size: 1
|
min_size: 1
|
||||||
resource: {type: scaling.yaml}
|
resource: {type: SP1_res.yaml}
|
||||||
type: OS::Heat::AutoScalingGroup
|
type: OS::Heat::AutoScalingGroup
|
||||||
SP1_scale_in:
|
SP1_scale_in:
|
||||||
properties:
|
properties:
|
||||||
adjustment_type: change_in_capacity
|
adjustment_type: change_in_capacity
|
||||||
auto_scaling_group_id: {get_resource: G1}
|
auto_scaling_group_id: {get_resource: SP1_group}
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
scaling_adjustment: '-1'
|
scaling_adjustment: -1
|
||||||
type: OS::Heat::ScalingPolicy
|
type: OS::Heat::ScalingPolicy
|
||||||
SP1_scale_out:
|
SP1_scale_out:
|
||||||
properties:
|
properties:
|
||||||
adjustment_type: change_in_capacity
|
adjustment_type: change_in_capacity
|
||||||
auto_scaling_group_id: {get_resource: G1}
|
auto_scaling_group_id: {get_resource: SP1_group}
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
scaling_adjustment: 1
|
scaling_adjustment: 1
|
||||||
type: OS::Heat::ScalingPolicy
|
type: OS::Heat::ScalingPolicy
|
||||||
|
|||||||
@@ -0,0 +1,57 @@
|
|||||||
|
tosca_definitions_version: tosca_simple_profile_for_nfv_1_0_0
|
||||||
|
description: Demo example
|
||||||
|
|
||||||
|
metadata:
|
||||||
|
template_name: sample-tosca-vnfd
|
||||||
|
|
||||||
|
topology_template:
|
||||||
|
node_templates:
|
||||||
|
VDU1:
|
||||||
|
type: tosca.nodes.nfv.VDU.Tacker
|
||||||
|
capabilities:
|
||||||
|
nfv_compute:
|
||||||
|
properties:
|
||||||
|
disk_size: 1 GB
|
||||||
|
mem_size: 512 MB
|
||||||
|
num_cpus: 2
|
||||||
|
properties:
|
||||||
|
image: cirros-0.3.5-x86_64-disk
|
||||||
|
mgmt_driver: noop
|
||||||
|
availability_zone: nova
|
||||||
|
metadata: {metering.vnf: VDU1}
|
||||||
|
|
||||||
|
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: net_mgmt
|
||||||
|
vendor: Tacker
|
||||||
|
|
||||||
|
policies:
|
||||||
|
- vdu1_cpu_usage_monitoring_policy:
|
||||||
|
type: tosca.policies.tacker.Alarming
|
||||||
|
triggers:
|
||||||
|
mon_policy_multi_actions:
|
||||||
|
event_type:
|
||||||
|
type: tosca.events.resource.utilization
|
||||||
|
implementation: ceilometer
|
||||||
|
meter_name: cpu_util
|
||||||
|
condition:
|
||||||
|
threshold: 50
|
||||||
|
constraint: utilization greater_than 50%
|
||||||
|
period: 600
|
||||||
|
evaluations: 1
|
||||||
|
method: average
|
||||||
|
comparison_operator: gt
|
||||||
|
metadata: VDU1
|
||||||
|
actions: [respawn, log]
|
||||||
@@ -45,13 +45,13 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: VDU1
|
metadata: VDU1
|
||||||
actions: [respawn]
|
action: [respawn]
|
||||||
|
|||||||
@@ -55,13 +55,13 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: SG1
|
metadata: SG1
|
||||||
actions: [SP1]
|
action: [SP1]
|
||||||
|
|||||||
@@ -48,7 +48,7 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: Ceilometer
|
implementation: Ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
@@ -57,4 +57,4 @@ topology_template:
|
|||||||
method: average
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: VDU1
|
metadata: VDU1
|
||||||
actions: ''
|
action: ''
|
||||||
|
|||||||
@@ -46,7 +46,7 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: Ceilometer
|
implementation: Ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
@@ -55,4 +55,4 @@ topology_template:
|
|||||||
method: average
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: VDU1
|
metadata: VDU1
|
||||||
actions: ''
|
action: ''
|
||||||
|
|||||||
@@ -36,13 +36,13 @@ topology_template:
|
|||||||
policies:
|
policies:
|
||||||
- SP1:
|
- SP1:
|
||||||
type: tosca.policies.tacker.Scaling
|
type: tosca.policies.tacker.Scaling
|
||||||
|
targets: [VDU1]
|
||||||
properties:
|
properties:
|
||||||
increment: 1
|
increment: 1
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
min_instances: 1
|
min_instances: 1
|
||||||
max_instances: 3
|
max_instances: 3
|
||||||
default_instances: 2
|
default_instances: 2
|
||||||
targets: [VDU1]
|
|
||||||
|
|
||||||
- vdu_cpu_usage_monitoring_policy:
|
- vdu_cpu_usage_monitoring_policy:
|
||||||
type: tosca.policies.tacker.Alarming
|
type: tosca.policies.tacker.Alarming
|
||||||
@@ -51,28 +51,28 @@ topology_template:
|
|||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 50
|
threshold: 50
|
||||||
constraint: utilization greater_than 50%
|
constraint: utilization greater_than 50%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: gt
|
comparison_operator: gt
|
||||||
metadata: SG1
|
metadata: SG1
|
||||||
actions: [SP1]
|
action: [SP1]
|
||||||
|
|
||||||
vdu_lcpu_usage_scaling_in:
|
vdu_lcpu_usage_scaling_in:
|
||||||
event_type:
|
event_type:
|
||||||
type: tosca.events.resource.utilization
|
type: tosca.events.resource.utilization
|
||||||
implementation: ceilometer
|
implementation: ceilometer
|
||||||
metrics: cpu_util
|
meter_name: cpu_util
|
||||||
condition:
|
condition:
|
||||||
threshold: 10
|
threshold: 10
|
||||||
constraint: utilization less_than 10%
|
constraint: utilization less_than 10%
|
||||||
period: 600
|
period: 600
|
||||||
evaluations: 1
|
evaluations: 1
|
||||||
method: avg
|
method: average
|
||||||
comparison_operator: lt
|
comparison_operator: lt
|
||||||
metadata: SG1
|
metadata: SG1
|
||||||
actions: [SP1]
|
action: [SP1]
|
||||||
|
|||||||
@@ -35,10 +35,11 @@ topology_template:
|
|||||||
policies:
|
policies:
|
||||||
- SP1:
|
- SP1:
|
||||||
type: tosca.policies.tacker.Scaling
|
type: tosca.policies.tacker.Scaling
|
||||||
|
targets: [VDU1]
|
||||||
properties:
|
properties:
|
||||||
increment: 1
|
increment: 1
|
||||||
cooldown: 60
|
cooldown: 60
|
||||||
min_instances: 1
|
min_instances: 1
|
||||||
max_instances: 3
|
max_instances: 3
|
||||||
default_instances: 2
|
default_instances: 2
|
||||||
targets: [VDU1]
|
|
||||||
|
|||||||
@@ -17,7 +17,6 @@ import codecs
|
|||||||
import json
|
import json
|
||||||
import mock
|
import mock
|
||||||
import os
|
import os
|
||||||
import unittest
|
|
||||||
import yaml
|
import yaml
|
||||||
|
|
||||||
from tacker import context
|
from tacker import context
|
||||||
@@ -304,7 +303,7 @@ class TestOpenStack(base.TestCase):
|
|||||||
vnf["attributes"][k] = yaml.safe_load(
|
vnf["attributes"][k] = yaml.safe_load(
|
||||||
vnf["attributes"][k])
|
vnf["attributes"][k])
|
||||||
expected_vnf["attributes"]['scaling_group_names'] = {
|
expected_vnf["attributes"]['scaling_group_names'] = {
|
||||||
'SP1': 'G1'}
|
'SP1': 'SP1_group'}
|
||||||
vnf["attributes"]['scaling_group_names'] = json.loads(
|
vnf["attributes"]['scaling_group_names'] = json.loads(
|
||||||
vnf["attributes"]['scaling_group_names']
|
vnf["attributes"]['scaling_group_names']
|
||||||
)
|
)
|
||||||
@@ -399,12 +398,11 @@ class TestOpenStack(base.TestCase):
|
|||||||
input_params
|
input_params
|
||||||
)
|
)
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
|
||||||
def test_create_tosca_scale(self):
|
def test_create_tosca_scale(self):
|
||||||
self._test_assert_equal_for_tosca_templates(
|
self._test_assert_equal_for_tosca_templates(
|
||||||
'tosca_scale.yaml',
|
'tosca_scale.yaml',
|
||||||
'hot_scale_main.yaml',
|
'hot_scale_main.yaml',
|
||||||
files={'scaling.yaml': 'hot_scale_custom.yaml'},
|
files={'SP1_res.yaml': 'hot_scale_custom.yaml'},
|
||||||
is_monitor=False
|
is_monitor=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -434,7 +432,6 @@ class TestOpenStack(base.TestCase):
|
|||||||
'hot_tosca_mac_ip.yaml'
|
'hot_tosca_mac_ip.yaml'
|
||||||
)
|
)
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
|
||||||
def test_create_tosca_alarm_respawn(self):
|
def test_create_tosca_alarm_respawn(self):
|
||||||
self._test_assert_equal_for_tosca_templates(
|
self._test_assert_equal_for_tosca_templates(
|
||||||
'tosca_alarm_respawn.yaml',
|
'tosca_alarm_respawn.yaml',
|
||||||
@@ -442,16 +439,14 @@ class TestOpenStack(base.TestCase):
|
|||||||
is_monitor=False
|
is_monitor=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
|
||||||
def test_create_tosca_alarm_scale(self):
|
def test_create_tosca_alarm_scale(self):
|
||||||
self._test_assert_equal_for_tosca_templates(
|
self._test_assert_equal_for_tosca_templates(
|
||||||
'tosca_alarm_scale.yaml',
|
'tosca_alarm_scale.yaml',
|
||||||
'hot_tosca_alarm_scale.yaml',
|
'hot_tosca_alarm_scale.yaml',
|
||||||
files={'scaling.yaml': 'hot_alarm_scale_custom.yaml'},
|
files={'SP1_res.yaml': 'hot_alarm_scale_custom.yaml'},
|
||||||
is_monitor=False
|
is_monitor=False
|
||||||
)
|
)
|
||||||
|
|
||||||
@unittest.skip("Related Bug 1682098")
|
|
||||||
def test_create_tosca_with_alarm_monitoring_not_matched(self):
|
def test_create_tosca_with_alarm_monitoring_not_matched(self):
|
||||||
self.assertRaises(vnfm.MetadataNotMatched,
|
self.assertRaises(vnfm.MetadataNotMatched,
|
||||||
self._test_assert_equal_for_tosca_templates,
|
self._test_assert_equal_for_tosca_templates,
|
||||||
|
|||||||
@@ -455,6 +455,14 @@ class TestVNFMPlugin(db_base.SqlTestCase):
|
|||||||
self._test_create_vnf_trigger(policy_name="vdu_hcpu_usage_scaling_out",
|
self._test_create_vnf_trigger(policy_name="vdu_hcpu_usage_scaling_out",
|
||||||
action_value="SP1-out")
|
action_value="SP1-out")
|
||||||
|
|
||||||
|
@patch('tacker.db.vnfm.vnfm_db.VNFMPluginDb.get_vnf')
|
||||||
|
def test_create_vnf_trigger_multi_actions(self, mock_get_vnf):
|
||||||
|
dummy_vnf = self._get_dummy_active_vnf(
|
||||||
|
utils.vnfd_alarm_multi_actions_tosca_template)
|
||||||
|
mock_get_vnf.return_value = dummy_vnf
|
||||||
|
self._test_create_vnf_trigger(policy_name="mon_policy_multi_actions",
|
||||||
|
action_value="respawn&log")
|
||||||
|
|
||||||
@patch('tacker.db.vnfm.vnfm_db.VNFMPluginDb.get_vnf')
|
@patch('tacker.db.vnfm.vnfm_db.VNFMPluginDb.get_vnf')
|
||||||
def test_get_vnf_policies(self, mock_get_vnf):
|
def test_get_vnf_policies(self, mock_get_vnf):
|
||||||
vnf_id = "6261579e-d6f3-49ad-8bc3-a9cb974778fe"
|
vnf_id = "6261579e-d6f3-49ad-8bc3-a9cb974778fe"
|
||||||
|
|||||||
@@ -29,7 +29,8 @@ from collections import OrderedDict
|
|||||||
|
|
||||||
FAILURE = 'tosca.policies.tacker.Failure'
|
FAILURE = 'tosca.policies.tacker.Failure'
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
MONITORING = 'tosca.policies.tacker.Monitoring'
|
MONITORING = 'tosca.policies.Monitoring'
|
||||||
|
SCALING = 'tosca.policies.Scaling'
|
||||||
PLACEMENT = 'tosca.policies.tacker.Placement'
|
PLACEMENT = 'tosca.policies.tacker.Placement'
|
||||||
TACKERCP = 'tosca.nodes.nfv.CP.Tacker'
|
TACKERCP = 'tosca.nodes.nfv.CP.Tacker'
|
||||||
TACKERVDU = 'tosca.nodes.nfv.VDU.Tacker'
|
TACKERVDU = 'tosca.nodes.nfv.VDU.Tacker'
|
||||||
@@ -82,6 +83,9 @@ HEAT_RESOURCE_MAP = {
|
|||||||
"image": "OS::Glance::Image"
|
"image": "OS::Glance::Image"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
SCALE_GROUP_RESOURCE = "OS::Heat::AutoScalingGroup"
|
||||||
|
SCALE_POLICY_RESOURCE = "OS::Heat::ScalingPolicy"
|
||||||
|
|
||||||
|
|
||||||
@log.log
|
@log.log
|
||||||
def updateimports(template):
|
def updateimports(template):
|
||||||
@@ -167,6 +171,54 @@ def get_vdu_metadata(template):
|
|||||||
return metadata
|
return metadata
|
||||||
|
|
||||||
|
|
||||||
|
@log.log
|
||||||
|
def pre_process_alarm_resources(vnf, template, vdu_metadata):
|
||||||
|
alarm_resources = dict()
|
||||||
|
matching_metadata = dict()
|
||||||
|
alarm_actions = dict()
|
||||||
|
for policy in template.policies:
|
||||||
|
if (policy.type_definition.is_derived_from(MONITORING)):
|
||||||
|
matching_metadata =\
|
||||||
|
_process_matching_metadata(vdu_metadata, policy)
|
||||||
|
alarm_actions = _process_alarm_actions(vnf, policy)
|
||||||
|
alarm_resources['matching_metadata'] = matching_metadata
|
||||||
|
alarm_resources['alarm_actions'] = alarm_actions
|
||||||
|
return alarm_resources
|
||||||
|
|
||||||
|
|
||||||
|
def _process_matching_metadata(metadata, policy):
|
||||||
|
matching_mtdata = dict()
|
||||||
|
triggers = policy.entity_tpl['triggers']
|
||||||
|
for trigger_name, trigger_dict in triggers.items():
|
||||||
|
if not (trigger_dict.get('metadata') and metadata):
|
||||||
|
raise vnfm.MetadataNotMatched()
|
||||||
|
is_matched = False
|
||||||
|
for vdu_name, metadata_dict in metadata['vdus'].items():
|
||||||
|
if trigger_dict['metadata'] ==\
|
||||||
|
metadata_dict['metering.vnf']:
|
||||||
|
is_matched = True
|
||||||
|
if not is_matched:
|
||||||
|
raise vnfm.MetadataNotMatched()
|
||||||
|
matching_mtdata[trigger_name] = dict()
|
||||||
|
matching_mtdata[trigger_name]['metadata.user_metadata.vnf'] =\
|
||||||
|
trigger_dict['metadata']
|
||||||
|
return matching_mtdata
|
||||||
|
|
||||||
|
|
||||||
|
def _process_alarm_actions(vnf, policy):
|
||||||
|
# process alarm url here
|
||||||
|
triggers = policy.entity_tpl['triggers']
|
||||||
|
alarm_actions = dict()
|
||||||
|
for trigger_name, trigger_dict in triggers.items():
|
||||||
|
alarm_url = vnf['attributes'].get(trigger_name)
|
||||||
|
if alarm_url:
|
||||||
|
alarm_url = str(alarm_url)
|
||||||
|
LOG.debug('Alarm url in heat %s', alarm_url)
|
||||||
|
alarm_actions[trigger_name] = dict()
|
||||||
|
alarm_actions[trigger_name]['alarm_actions'] = [alarm_url]
|
||||||
|
return alarm_actions
|
||||||
|
|
||||||
|
|
||||||
@log.log
|
@log.log
|
||||||
def get_mgmt_ports(tosca):
|
def get_mgmt_ports(tosca):
|
||||||
mgmt_ports = {}
|
mgmt_ports = {}
|
||||||
@@ -199,9 +251,10 @@ def add_resources_tpl(heat_dict, hot_res_tpl):
|
|||||||
|
|
||||||
for prop, val in (vdu_dict).items():
|
for prop, val in (vdu_dict).items():
|
||||||
heat_dict["resources"][res_name]["properties"][prop] = val
|
heat_dict["resources"][res_name]["properties"][prop] = val
|
||||||
heat_dict["resources"][vdu]["properties"][res] = {
|
if heat_dict["resources"].get(vdu):
|
||||||
"get_resource": res_name
|
heat_dict["resources"][vdu]["properties"][res] = {
|
||||||
}
|
"get_resource": res_name
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
@log.log
|
@log.log
|
||||||
@@ -254,7 +307,8 @@ def represent_odict(dump, tag, mapping, flow_style=None):
|
|||||||
|
|
||||||
@log.log
|
@log.log
|
||||||
def post_process_heat_template(heat_tpl, mgmt_ports, metadata,
|
def post_process_heat_template(heat_tpl, mgmt_ports, metadata,
|
||||||
res_tpl, unsupported_res_prop=None):
|
alarm_resources, res_tpl,
|
||||||
|
unsupported_res_prop=None):
|
||||||
#
|
#
|
||||||
# TODO(bobh) - remove when heat-translator can support literal strings.
|
# TODO(bobh) - remove when heat-translator can support literal strings.
|
||||||
#
|
#
|
||||||
@@ -278,8 +332,24 @@ def post_process_heat_template(heat_tpl, mgmt_ports, metadata,
|
|||||||
LOG.debug('Added output for %s', outputname)
|
LOG.debug('Added output for %s', outputname)
|
||||||
if metadata:
|
if metadata:
|
||||||
for vdu_name, metadata_dict in metadata['vdus'].items():
|
for vdu_name, metadata_dict in metadata['vdus'].items():
|
||||||
heat_dict['resources'][vdu_name]['properties']['metadata'] =\
|
if heat_dict['resources'].get(vdu_name):
|
||||||
metadata_dict
|
heat_dict['resources'][vdu_name]['properties']['metadata'] =\
|
||||||
|
metadata_dict
|
||||||
|
matching_metadata = alarm_resources.get('matching_metadata')
|
||||||
|
alarm_actions = alarm_resources.get('alarm_actions')
|
||||||
|
if matching_metadata:
|
||||||
|
for trigger_name, matching_metadata_dict in matching_metadata.items():
|
||||||
|
if heat_dict['resources'].get(trigger_name):
|
||||||
|
matching_mtdata = dict()
|
||||||
|
matching_mtdata['matching_metadata'] =\
|
||||||
|
matching_metadata[trigger_name]
|
||||||
|
heat_dict['resources'][trigger_name]['properties'].\
|
||||||
|
update(matching_mtdata)
|
||||||
|
if alarm_actions:
|
||||||
|
for trigger_name, alarm_actions_dict in alarm_actions.items():
|
||||||
|
if heat_dict['resources'].get(trigger_name):
|
||||||
|
heat_dict['resources'][trigger_name]['properties']. \
|
||||||
|
update(alarm_actions_dict)
|
||||||
|
|
||||||
add_resources_tpl(heat_dict, res_tpl)
|
add_resources_tpl(heat_dict, res_tpl)
|
||||||
for res in heat_dict["resources"].values():
|
for res in heat_dict["resources"].values():
|
||||||
@@ -464,3 +534,72 @@ def get_resources_dict(template, flavor_extra_input=None):
|
|||||||
else:
|
else:
|
||||||
res_dict[res] = res_method(template)
|
res_dict[res] = res_method(template)
|
||||||
return res_dict
|
return res_dict
|
||||||
|
|
||||||
|
|
||||||
|
@log.log
|
||||||
|
def get_scaling_policy(template):
|
||||||
|
scaling_policy_names = list()
|
||||||
|
for policy in template.policies:
|
||||||
|
if (policy.type_definition.is_derived_from(SCALING)):
|
||||||
|
scaling_policy_names.append(policy.name)
|
||||||
|
return scaling_policy_names
|
||||||
|
|
||||||
|
|
||||||
|
@log.log
|
||||||
|
def get_scaling_group_dict(ht_template, scaling_policy_names):
|
||||||
|
scaling_group_dict = dict()
|
||||||
|
scaling_group_names = list()
|
||||||
|
heat_dict = yamlparser.simple_ordered_parse(ht_template)
|
||||||
|
for resource_name, resource_dict in heat_dict['resources'].items():
|
||||||
|
if resource_dict['type'] == SCALE_GROUP_RESOURCE:
|
||||||
|
scaling_group_names.append(resource_name)
|
||||||
|
if scaling_group_names:
|
||||||
|
scaling_group_dict[scaling_policy_names[0]] = scaling_group_names[0]
|
||||||
|
return scaling_group_dict
|
||||||
|
|
||||||
|
|
||||||
|
def get_nested_resources_name(template):
|
||||||
|
for policy in template.policies:
|
||||||
|
if (policy.type_definition.is_derived_from(SCALING)):
|
||||||
|
nested_resource_name = policy.name + '_res.yaml'
|
||||||
|
return nested_resource_name
|
||||||
|
|
||||||
|
|
||||||
|
def update_nested_scaling_resources(nested_resources, mgmt_ports, metadata,
|
||||||
|
res_tpl, unsupported_res_prop=None):
|
||||||
|
nested_tpl = dict()
|
||||||
|
if nested_resources:
|
||||||
|
nested_resource_name, nested_resources_yaml =\
|
||||||
|
list(nested_resources.items())[0]
|
||||||
|
nested_resources_dict =\
|
||||||
|
yamlparser.simple_ordered_parse(nested_resources_yaml)
|
||||||
|
if metadata:
|
||||||
|
for vdu_name, metadata_dict in metadata['vdus'].items():
|
||||||
|
nested_resources_dict['resources'][vdu_name]['properties']['metadata'] = \
|
||||||
|
metadata_dict
|
||||||
|
add_resources_tpl(nested_resources_dict, res_tpl)
|
||||||
|
for res in nested_resources_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(nested_resources_dict,
|
||||||
|
unsupported_res_prop)
|
||||||
|
|
||||||
|
for outputname, portname in mgmt_ports.items():
|
||||||
|
ipval = {'get_attr': [portname, 'fixed_ips', 0, 'ip_address']}
|
||||||
|
output = {outputname: {'value': ipval}}
|
||||||
|
if 'outputs' in nested_resources_dict:
|
||||||
|
nested_resources_dict['outputs'].update(output)
|
||||||
|
else:
|
||||||
|
nested_resources_dict['outputs'] = output
|
||||||
|
LOG.debug(_('Added output for %s'), outputname)
|
||||||
|
yaml.SafeDumper.add_representer(
|
||||||
|
OrderedDict, lambda dumper, value: represent_odict(
|
||||||
|
dumper, u'tag:yaml.org,2002:map', value))
|
||||||
|
nested_tpl[nested_resource_name] =\
|
||||||
|
yaml.safe_dump(nested_resources_dict)
|
||||||
|
return nested_tpl
|
||||||
|
|||||||
@@ -303,7 +303,7 @@ class OpenStack(abstract_driver.DeviceAbstractDriver,
|
|||||||
@log.log
|
@log.log
|
||||||
def scale(self, context, plugin, auth_attr, policy, region_name):
|
def scale(self, context, plugin, auth_attr, policy, region_name):
|
||||||
heatclient = hc.HeatClient(auth_attr, region_name)
|
heatclient = hc.HeatClient(auth_attr, region_name)
|
||||||
policy_rsc = get_scaling_policy_name(policy_name=policy['id'],
|
policy_rsc = get_scaling_policy_name(policy_name=policy['name'],
|
||||||
action=policy['action'])
|
action=policy['action'])
|
||||||
events = heatclient.resource_event_list(policy['instance_id'],
|
events = heatclient.resource_event_list(policy['instance_id'],
|
||||||
policy_rsc, limit=1,
|
policy_rsc, limit=1,
|
||||||
@@ -325,8 +325,8 @@ class OpenStack(abstract_driver.DeviceAbstractDriver,
|
|||||||
try:
|
try:
|
||||||
time.sleep(self.STACK_RETRY_WAIT)
|
time.sleep(self.STACK_RETRY_WAIT)
|
||||||
stack_id = policy['instance_id']
|
stack_id = policy['instance_id']
|
||||||
policy_name = get_scaling_policy_name(policy_name=policy['id'],
|
policy_name = get_scaling_policy_name(
|
||||||
action=policy['action'])
|
policy_name=policy['name'], action=policy['action'])
|
||||||
events = heatclient.resource_event_list(stack_id, policy_name,
|
events = heatclient.resource_event_list(stack_id, policy_name,
|
||||||
limit=1,
|
limit=1,
|
||||||
sort_dir='desc',
|
sort_dir='desc',
|
||||||
|
|||||||
@@ -10,8 +10,6 @@
|
|||||||
# License for the specific language governing permissions and limitations
|
# License for the specific language governing permissions and limitations
|
||||||
# under the License.
|
# under the License.
|
||||||
|
|
||||||
import copy
|
|
||||||
|
|
||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_serialization import jsonutils
|
from oslo_serialization import jsonutils
|
||||||
@@ -25,7 +23,6 @@ from tacker.extensions import common_services as cs
|
|||||||
from tacker.extensions import vnfm
|
from tacker.extensions import vnfm
|
||||||
from tacker.tosca import utils as toscautils
|
from tacker.tosca import utils as toscautils
|
||||||
|
|
||||||
from collections import OrderedDict
|
|
||||||
|
|
||||||
LOG = logging.getLogger(__name__)
|
LOG = logging.getLogger(__name__)
|
||||||
CONF = cfg.CONF
|
CONF = cfg.CONF
|
||||||
@@ -49,10 +46,6 @@ ALARMING_POLICY = 'tosca.policies.tacker.Alarming'
|
|||||||
SCALING_POLICY = 'tosca.policies.tacker.Scaling'
|
SCALING_POLICY = 'tosca.policies.tacker.Scaling'
|
||||||
|
|
||||||
|
|
||||||
def get_scaling_policy_name(action, policy_name):
|
|
||||||
return '%s_scale_%s' % (policy_name, action)
|
|
||||||
|
|
||||||
|
|
||||||
class TOSCAToHOT(object):
|
class TOSCAToHOT(object):
|
||||||
"""Convert TOSCA template to HOT template."""
|
"""Convert TOSCA template to HOT template."""
|
||||||
|
|
||||||
@@ -64,6 +57,7 @@ class TOSCAToHOT(object):
|
|||||||
self.unsupported_props = {}
|
self.unsupported_props = {}
|
||||||
self.heat_template_yaml = None
|
self.heat_template_yaml = None
|
||||||
self.monitoring_dict = None
|
self.monitoring_dict = None
|
||||||
|
self.nested_resources = dict()
|
||||||
self.fields = None
|
self.fields = None
|
||||||
self.STACK_FLAVOR_EXTRA = cfg.CONF.openstack_vim.flavor_extra_specs
|
self.STACK_FLAVOR_EXTRA = cfg.CONF.openstack_vim.flavor_extra_specs
|
||||||
|
|
||||||
@@ -77,13 +71,10 @@ class TOSCAToHOT(object):
|
|||||||
LOG.debug('vnfd_dict %s', vnfd_dict)
|
LOG.debug('vnfd_dict %s', vnfd_dict)
|
||||||
self._get_unsupported_resource_props(self.heatclient)
|
self._get_unsupported_resource_props(self.heatclient)
|
||||||
|
|
||||||
is_tosca_format = False
|
|
||||||
self._generate_hot_from_tosca(vnfd_dict, dev_attrs)
|
self._generate_hot_from_tosca(vnfd_dict, dev_attrs)
|
||||||
is_tosca_format = True
|
|
||||||
|
|
||||||
self.fields['template'] = self.heat_template_yaml
|
self.fields['template'] = self.heat_template_yaml
|
||||||
if is_tosca_format:
|
if not self.vnf['attributes'].get('heat_template'):
|
||||||
self._handle_policies(vnfd_dict)
|
self.vnf['attributes']['heat_template'] = self.fields['template']
|
||||||
if self.monitoring_dict:
|
if self.monitoring_dict:
|
||||||
self.vnf['attributes']['monitoring_policy'] = jsonutils.dumps(
|
self.vnf['attributes']['monitoring_policy'] = jsonutils.dumps(
|
||||||
self.monitoring_dict)
|
self.monitoring_dict)
|
||||||
@@ -122,37 +113,6 @@ class TOSCAToHOT(object):
|
|||||||
self.fields = fields
|
self.fields = fields
|
||||||
return dev_attrs
|
return dev_attrs
|
||||||
|
|
||||||
@log.log
|
|
||||||
def _handle_policies(self, vnfd_dict):
|
|
||||||
|
|
||||||
vnf = self.vnf
|
|
||||||
(is_scaling_needed, scaling_group_names,
|
|
||||||
main_dict) = self._generate_hot_scaling(
|
|
||||||
vnfd_dict['topology_template'], 'scaling.yaml')
|
|
||||||
(is_enabled_alarm, alarm_resource, heat_tpl_yaml) =\
|
|
||||||
self._generate_hot_alarm_resource(vnfd_dict['topology_template'])
|
|
||||||
if is_enabled_alarm and not is_scaling_needed:
|
|
||||||
self.fields['template'] = heat_tpl_yaml
|
|
||||||
|
|
||||||
if is_scaling_needed:
|
|
||||||
if is_enabled_alarm:
|
|
||||||
main_dict['resources'].update(alarm_resource)
|
|
||||||
main_yaml = yaml.safe_dump(main_dict)
|
|
||||||
self.fields['template'] = main_yaml
|
|
||||||
self.fields['files'] = {'scaling.yaml': self.heat_template_yaml}
|
|
||||||
vnf['attributes']['heat_template'] = main_yaml
|
|
||||||
# TODO(kanagaraj-manickam) when multiple groups are
|
|
||||||
# supported, make this scaling attribute as
|
|
||||||
# scaling name vs scaling template map and remove
|
|
||||||
# scaling_group_names
|
|
||||||
vnf['attributes']['scaling.yaml'] = self.heat_template_yaml
|
|
||||||
vnf['attributes']['scaling_group_names'] = jsonutils.dumps(
|
|
||||||
scaling_group_names)
|
|
||||||
|
|
||||||
elif not vnf['attributes'].get('heat_template'):
|
|
||||||
vnf['attributes']['heat_template'] = self.fields['template']
|
|
||||||
self.vnf = vnf
|
|
||||||
|
|
||||||
@log.log
|
@log.log
|
||||||
def _update_params(self, original, paramvalues, match=False):
|
def _update_params(self, original, paramvalues, match=False):
|
||||||
for key, value in (original).items():
|
for key, value in (original).items():
|
||||||
@@ -305,131 +265,55 @@ class TOSCAToHOT(object):
|
|||||||
raise vnfm.ToscaParserFailed(error_msg_details=str(e))
|
raise vnfm.ToscaParserFailed(error_msg_details=str(e))
|
||||||
|
|
||||||
metadata = toscautils.get_vdu_metadata(tosca)
|
metadata = toscautils.get_vdu_metadata(tosca)
|
||||||
|
alarm_resources =\
|
||||||
|
toscautils.pre_process_alarm_resources(self.vnf, tosca, metadata)
|
||||||
monitoring_dict = toscautils.get_vdu_monitoring(tosca)
|
monitoring_dict = toscautils.get_vdu_monitoring(tosca)
|
||||||
mgmt_ports = toscautils.get_mgmt_ports(tosca)
|
mgmt_ports = toscautils.get_mgmt_ports(tosca)
|
||||||
|
nested_resource_name = toscautils.get_nested_resources_name(tosca)
|
||||||
res_tpl = toscautils.get_resources_dict(tosca,
|
res_tpl = toscautils.get_resources_dict(tosca,
|
||||||
self.STACK_FLAVOR_EXTRA)
|
self.STACK_FLAVOR_EXTRA)
|
||||||
toscautils.post_process_template(tosca)
|
toscautils.post_process_template(tosca)
|
||||||
|
scaling_policy_names = toscautils.get_scaling_policy(tosca)
|
||||||
try:
|
try:
|
||||||
translator = tosca_translator.TOSCATranslator(tosca,
|
translator = tosca_translator.TOSCATranslator(tosca,
|
||||||
parsed_params)
|
parsed_params)
|
||||||
heat_template_yaml = translator.translate()
|
heat_template_yaml = translator.translate()
|
||||||
|
if nested_resource_name:
|
||||||
|
sub_heat_template_yaml =\
|
||||||
|
translator.translate_to_yaml_files_dict(
|
||||||
|
nested_resource_name, True)
|
||||||
|
nested_resource_yaml =\
|
||||||
|
sub_heat_template_yaml[nested_resource_name]
|
||||||
|
self.nested_resources[nested_resource_name] =\
|
||||||
|
nested_resource_yaml
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.debug("heat-translator error: %s", str(e))
|
LOG.debug("heat-translator error: %s", str(e))
|
||||||
raise vnfm.HeatTranslatorFailed(error_msg_details=str(e))
|
raise vnfm.HeatTranslatorFailed(error_msg_details=str(e))
|
||||||
|
|
||||||
|
if self.nested_resources:
|
||||||
|
nested_tpl = toscautils.update_nested_scaling_resources(
|
||||||
|
self.nested_resources, mgmt_ports, metadata,
|
||||||
|
res_tpl, self.unsupported_props)
|
||||||
|
self.fields['files'] = nested_tpl
|
||||||
|
self.vnf['attributes'][nested_resource_name] =\
|
||||||
|
nested_tpl[nested_resource_name]
|
||||||
|
mgmt_ports.clear()
|
||||||
|
|
||||||
|
if scaling_policy_names:
|
||||||
|
scaling_group_dict = toscautils.get_scaling_group_dict(
|
||||||
|
heat_template_yaml, scaling_policy_names)
|
||||||
|
self.vnf['attributes']['scaling_group_names'] =\
|
||||||
|
jsonutils.dumps(scaling_group_dict)
|
||||||
|
|
||||||
heat_template_yaml = toscautils.post_process_heat_template(
|
heat_template_yaml = toscautils.post_process_heat_template(
|
||||||
heat_template_yaml, mgmt_ports, metadata,
|
heat_template_yaml, mgmt_ports, metadata, alarm_resources,
|
||||||
res_tpl, self.unsupported_props)
|
res_tpl, self.unsupported_props)
|
||||||
|
|
||||||
self.heat_template_yaml = heat_template_yaml
|
self.heat_template_yaml = heat_template_yaml
|
||||||
self.monitoring_dict = monitoring_dict
|
self.monitoring_dict = monitoring_dict
|
||||||
self.metadata = metadata
|
self.metadata = metadata
|
||||||
|
|
||||||
@log.log
|
|
||||||
def _generate_hot_scaling(self, vnfd_dict,
|
|
||||||
scale_resource_type="OS::Nova::Server"):
|
|
||||||
# Initialize the template
|
|
||||||
template_dict = yaml.safe_load(HEAT_TEMPLATE_BASE)
|
|
||||||
template_dict['description'] = 'Tacker scaling template'
|
|
||||||
|
|
||||||
parameters = {}
|
|
||||||
template_dict['parameters'] = parameters
|
|
||||||
|
|
||||||
# Add scaling related resource defs
|
|
||||||
resources = {}
|
|
||||||
scaling_group_names = {}
|
|
||||||
# policies:
|
|
||||||
# - SP1:
|
|
||||||
# type: tosca.policies.tacker.Scaling
|
|
||||||
if 'policies' in vnfd_dict:
|
|
||||||
for policy_dict in vnfd_dict['policies']:
|
|
||||||
name, policy = list(policy_dict.items())[0]
|
|
||||||
if policy['type'] == SCALING_POLICY:
|
|
||||||
resources, scaling_group_names =\
|
|
||||||
self._convert_to_heat_scaling_policy(
|
|
||||||
policy['properties'], scale_resource_type, name)
|
|
||||||
# TODO(kanagaraj-manickam) only one policy is supported
|
|
||||||
# for all vdus. remove this break, once this limitation
|
|
||||||
# is addressed.
|
|
||||||
break
|
|
||||||
|
|
||||||
template_dict['resources'] = resources
|
|
||||||
|
|
||||||
# First return value helps to check if scaling resources exist
|
|
||||||
return ((len(template_dict['resources']) > 0), scaling_group_names,
|
|
||||||
template_dict)
|
|
||||||
|
|
||||||
@log.log
|
|
||||||
def _convert_to_heat_scaling_group(self, policy_prp, scale_resource_type,
|
|
||||||
name):
|
|
||||||
group_hot = {'type': 'OS::Heat::AutoScalingGroup'}
|
|
||||||
properties = {}
|
|
||||||
properties['min_size'] = policy_prp['min_instances']
|
|
||||||
properties['max_size'] = policy_prp['max_instances']
|
|
||||||
properties['desired_capacity'] = policy_prp['default_instances']
|
|
||||||
properties['cooldown'] = policy_prp['cooldown']
|
|
||||||
properties['resource'] = {}
|
|
||||||
# TODO(kanagaraj-manickam) all VDU members are considered as 1
|
|
||||||
# group now and make it to form the groups based on the VDU
|
|
||||||
# list mentioned in the policy's targets
|
|
||||||
# scale_resource_type is custome type mapped the HOT template
|
|
||||||
# generated for all VDUs in the tosca template
|
|
||||||
properties['resource']['type'] = scale_resource_type
|
|
||||||
# TODO(kanagraj-manickam) add custom type params here, to
|
|
||||||
# support parameterized template
|
|
||||||
group_hot['properties'] = properties
|
|
||||||
|
|
||||||
return group_hot
|
|
||||||
|
|
||||||
# TODO(kanagaraj-manickam) now only one group is supported, so name
|
|
||||||
# is hard-coded with G1
|
|
||||||
@log.log
|
|
||||||
def _get_scale_group_name(self, targets):
|
|
||||||
return 'G1'
|
|
||||||
|
|
||||||
# tosca policies
|
|
||||||
#
|
|
||||||
# properties:
|
|
||||||
# adjust_by: 1
|
|
||||||
# cooldown: 120
|
|
||||||
# targets: [G1]
|
|
||||||
@log.log
|
|
||||||
def _convert_to_heat_scaling_policy(self, policy_prp, scale_resource_type,
|
|
||||||
name):
|
|
||||||
# Add scaling related resource defs
|
|
||||||
resources = {}
|
|
||||||
scaling_group_names = {}
|
|
||||||
|
|
||||||
# Form the group
|
|
||||||
scale_grp = self._get_scale_group_name(policy_prp['targets'])
|
|
||||||
scaling_group_names[name] = scale_grp
|
|
||||||
resources[scale_grp] = self._convert_to_heat_scaling_group(
|
|
||||||
policy_prp, scale_resource_type, scale_grp)
|
|
||||||
|
|
||||||
grp_id = {'get_resource': scale_grp}
|
|
||||||
|
|
||||||
policy_hot = {'type': 'OS::Heat::ScalingPolicy'}
|
|
||||||
properties = {}
|
|
||||||
properties['adjustment_type'] = 'change_in_capacity'
|
|
||||||
properties['cooldown'] = policy_prp['cooldown']
|
|
||||||
properties['scaling_adjustment'] = policy_prp['increment']
|
|
||||||
properties['auto_scaling_group_id'] = grp_id
|
|
||||||
policy_hot['properties'] = properties
|
|
||||||
|
|
||||||
# Add scale_out policy
|
|
||||||
policy_rsc_name = get_scaling_policy_name(action='out',
|
|
||||||
policy_name=name)
|
|
||||||
resources[policy_rsc_name] = policy_hot
|
|
||||||
|
|
||||||
# Add scale_in policy
|
|
||||||
in_value = '-%d' % int(policy_prp['increment'])
|
|
||||||
policy_hot_in = copy.deepcopy(policy_hot)
|
|
||||||
policy_hot_in['properties']['scaling_adjustment'] = in_value
|
|
||||||
policy_rsc_name = get_scaling_policy_name(action='in',
|
|
||||||
policy_name=name)
|
|
||||||
resources[policy_rsc_name] = policy_hot_in
|
|
||||||
return resources, scaling_group_names
|
|
||||||
|
|
||||||
@log.log
|
@log.log
|
||||||
def represent_odict(self, dump, tag, mapping, flow_style=None):
|
def represent_odict(self, dump, tag, mapping, flow_style=None):
|
||||||
value = []
|
value = []
|
||||||
@@ -455,74 +339,3 @@ class TOSCAToHOT(object):
|
|||||||
else:
|
else:
|
||||||
node.flow_style = best_style
|
node.flow_style = best_style
|
||||||
return node
|
return node
|
||||||
|
|
||||||
@log.log
|
|
||||||
def _generate_hot_alarm_resource(self, topology_tpl_dict):
|
|
||||||
alarm_resource = dict()
|
|
||||||
heat_tpl = self.heat_template_yaml
|
|
||||||
heat_dict = yamlparser.simple_ordered_parse(heat_tpl)
|
|
||||||
is_enabled_alarm = False
|
|
||||||
|
|
||||||
if 'policies' in topology_tpl_dict:
|
|
||||||
for policy_dict in topology_tpl_dict['policies']:
|
|
||||||
name, policy_tpl_dict = list(policy_dict.items())[0]
|
|
||||||
# need to parse triggers here: scaling in/out, respawn,...
|
|
||||||
if policy_tpl_dict['type'] == \
|
|
||||||
'tosca.policies.tacker.Alarming':
|
|
||||||
is_enabled_alarm = True
|
|
||||||
triggers = policy_tpl_dict['triggers']
|
|
||||||
for trigger_name, trigger_dict in triggers.items():
|
|
||||||
alarm_resource[trigger_name] =\
|
|
||||||
self._convert_to_heat_monitoring_resource({
|
|
||||||
trigger_name: trigger_dict}, self.vnf)
|
|
||||||
heat_dict['resources'].update(alarm_resource)
|
|
||||||
|
|
||||||
yaml.SafeDumper.add_representer(OrderedDict,
|
|
||||||
lambda dumper, value: self.represent_odict(dumper,
|
|
||||||
u'tag:yaml.org,2002:map', value))
|
|
||||||
heat_tpl_yaml = yaml.safe_dump(heat_dict)
|
|
||||||
return (is_enabled_alarm,
|
|
||||||
alarm_resource,
|
|
||||||
heat_tpl_yaml
|
|
||||||
)
|
|
||||||
|
|
||||||
def _convert_to_heat_monitoring_resource(self, mon_policy, vnf):
|
|
||||||
mon_policy_hot = {'type': 'OS::Aodh::Alarm'}
|
|
||||||
mon_policy_hot['properties'] = \
|
|
||||||
self._convert_to_heat_monitoring_prop(mon_policy, vnf)
|
|
||||||
return mon_policy_hot
|
|
||||||
|
|
||||||
def _convert_to_heat_monitoring_prop(self, mon_policy, vnf):
|
|
||||||
metadata = self.metadata
|
|
||||||
trigger_name, trigger_dict = list(mon_policy.items())[0]
|
|
||||||
tpl_condition = trigger_dict['condition']
|
|
||||||
properties = dict()
|
|
||||||
if not (trigger_dict.get('metadata') and metadata):
|
|
||||||
raise vnfm.MetadataNotMatched()
|
|
||||||
matching_metadata_dict = dict()
|
|
||||||
properties['meter_name'] = trigger_dict['metrics']
|
|
||||||
is_matched = False
|
|
||||||
for vdu_name, metadata_dict in metadata['vdus'].items():
|
|
||||||
if trigger_dict['metadata'] ==\
|
|
||||||
metadata_dict['metering.vnf']:
|
|
||||||
is_matched = True
|
|
||||||
if not is_matched:
|
|
||||||
raise vnfm.MetadataNotMatched()
|
|
||||||
matching_metadata_dict['metadata.user_metadata.vnf'] =\
|
|
||||||
trigger_dict['metadata']
|
|
||||||
properties['matching_metadata'] = \
|
|
||||||
matching_metadata_dict
|
|
||||||
properties['comparison_operator'] = \
|
|
||||||
tpl_condition['comparison_operator']
|
|
||||||
properties['period'] = tpl_condition['period']
|
|
||||||
properties['evaluation_periods'] = tpl_condition['evaluations']
|
|
||||||
properties['statistic'] = tpl_condition['method']
|
|
||||||
properties['description'] = tpl_condition['constraint']
|
|
||||||
properties['threshold'] = tpl_condition['threshold']
|
|
||||||
# alarm url process here
|
|
||||||
alarm_url = vnf['attributes'].get(trigger_name)
|
|
||||||
if alarm_url:
|
|
||||||
alarm_url = str(alarm_url)
|
|
||||||
LOG.debug('Alarm url in heat %s', alarm_url)
|
|
||||||
properties['alarm_actions'] = [alarm_url]
|
|
||||||
return properties
|
|
||||||
|
|||||||
@@ -220,8 +220,9 @@ class VNFAlarmMonitor(object):
|
|||||||
params['vnf_id'] = vnf['id']
|
params['vnf_id'] = vnf['id']
|
||||||
params['mon_policy_name'] = trigger_name
|
params['mon_policy_name'] = trigger_name
|
||||||
driver = trigger_dict['event_type']['implementation']
|
driver = trigger_dict['event_type']['implementation']
|
||||||
policy_action_list = trigger_dict.get('actions')
|
# TODO(Tung Doan) trigger_dict.get('actions') needs to be used
|
||||||
if len(policy_action_list) == 0:
|
policy_action = trigger_dict.get('action')
|
||||||
|
if len(policy_action) == 0:
|
||||||
_log_monitor_events(t_context.get_admin_context(),
|
_log_monitor_events(t_context.get_admin_context(),
|
||||||
vnf,
|
vnf,
|
||||||
"Alarm not set: policy action missing")
|
"Alarm not set: policy action missing")
|
||||||
@@ -234,8 +235,9 @@ class VNFAlarmMonitor(object):
|
|||||||
'policy_name': bk_policy_name,
|
'policy_name': bk_policy_name,
|
||||||
'action_name': bk_action_name}
|
'action_name': bk_action_name}
|
||||||
return policy
|
return policy
|
||||||
for policy_action in policy_action_list:
|
|
||||||
filters = {'name': policy_action}
|
for index, policy_action_name in enumerate(policy_action):
|
||||||
|
filters = {'name': policy_action_name}
|
||||||
bkend_policies =\
|
bkend_policies =\
|
||||||
plugin.get_vnf_policies(context, vnf['id'], filters)
|
plugin.get_vnf_policies(context, vnf['id'], filters)
|
||||||
if bkend_policies:
|
if bkend_policies:
|
||||||
@@ -244,16 +246,19 @@ class VNFAlarmMonitor(object):
|
|||||||
cp = trigger_dict['condition'].\
|
cp = trigger_dict['condition'].\
|
||||||
get('comparison_operator')
|
get('comparison_operator')
|
||||||
scaling_type = 'out' if cp == 'gt' else 'in'
|
scaling_type = 'out' if cp == 'gt' else 'in'
|
||||||
policy_action = _refactor_backend_policy(policy_action,
|
policy_action[index] = _refactor_backend_policy(
|
||||||
scaling_type)
|
policy_action_name, scaling_type)
|
||||||
|
|
||||||
params['mon_policy_action'] = policy_action
|
# Support multiple action. Ex: respawn % notify
|
||||||
alarm_url[trigger_name] =\
|
action_name = '%'.join(policy_action)
|
||||||
self.call_alarm_url(driver, vnf, params)
|
|
||||||
details = "Alarm URL set successfully: %s" % alarm_url
|
params['mon_policy_action'] = action_name
|
||||||
_log_monitor_events(t_context.get_admin_context(),
|
alarm_url[trigger_name] =\
|
||||||
vnf,
|
self.call_alarm_url(driver, vnf, params)
|
||||||
details)
|
details = "Alarm URL set successfully: %s" % alarm_url
|
||||||
|
_log_monitor_events(t_context.get_admin_context(),
|
||||||
|
vnf,
|
||||||
|
details)
|
||||||
return alarm_url
|
return alarm_url
|
||||||
|
|
||||||
def process_alarm_for_vnf(self, vnf, trigger):
|
def process_alarm_for_vnf(self, vnf, trigger):
|
||||||
|
|||||||
@@ -22,6 +22,7 @@ import eventlet
|
|||||||
from oslo_config import cfg
|
from oslo_config import cfg
|
||||||
from oslo_log import log as logging
|
from oslo_log import log as logging
|
||||||
from oslo_utils import excutils
|
from oslo_utils import excutils
|
||||||
|
from oslo_utils import uuidutils
|
||||||
from toscaparser.tosca_template import ToscaTemplate
|
from toscaparser.tosca_template import ToscaTemplate
|
||||||
|
|
||||||
from tacker.api.v1 import attributes
|
from tacker.api.v1 import attributes
|
||||||
@@ -122,7 +123,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
OPTS_POLICY_ACTION = [
|
OPTS_POLICY_ACTION = [
|
||||||
cfg.ListOpt(
|
cfg.ListOpt(
|
||||||
'policy_action', default=['autoscaling', 'respawn',
|
'policy_action', default=['autoscaling', 'respawn',
|
||||||
'log_only', 'log_and_kill'],
|
'log', 'log_and_kill'],
|
||||||
help=_('Hosting vnf drivers tacker plugin will use')),
|
help=_('Hosting vnf drivers tacker plugin will use')),
|
||||||
]
|
]
|
||||||
cfg.CONF.register_opts(OPTS_POLICY_ACTION, 'tacker')
|
cfg.CONF.register_opts(OPTS_POLICY_ACTION, 'tacker')
|
||||||
@@ -542,7 +543,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
raise exceptions.VnfPolicyTypeInvalid(
|
raise exceptions.VnfPolicyTypeInvalid(
|
||||||
type=type,
|
type=type,
|
||||||
valid_types=constants.POLICY_ACTIONS.keys(),
|
valid_types=constants.POLICY_ACTIONS.keys(),
|
||||||
policy=policy['id']
|
policy=policy['name']
|
||||||
)
|
)
|
||||||
action = policy['action']
|
action = policy['action']
|
||||||
|
|
||||||
@@ -550,10 +551,10 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
raise exceptions.VnfPolicyActionInvalid(
|
raise exceptions.VnfPolicyActionInvalid(
|
||||||
action=action,
|
action=action,
|
||||||
valid_actions=constants.POLICY_ACTIONS[type],
|
valid_actions=constants.POLICY_ACTIONS[type],
|
||||||
policy=policy['id']
|
policy=policy['name']
|
||||||
)
|
)
|
||||||
|
|
||||||
LOG.debug("Policy %s is validated successfully", policy['id'])
|
LOG.debug("Policy %s is validated successfully", policy['name'])
|
||||||
|
|
||||||
def _get_status():
|
def _get_status():
|
||||||
if policy['action'] == constants.ACTION_SCALE_IN:
|
if policy['action'] == constants.ACTION_SCALE_IN:
|
||||||
@@ -571,7 +572,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
[constants.ACTIVE],
|
[constants.ACTIVE],
|
||||||
status)
|
status)
|
||||||
LOG.debug("Policy %(policy)s vnf is at %(status)s",
|
LOG.debug("Policy %(policy)s vnf is at %(status)s",
|
||||||
{'policy': policy['id'],
|
{'policy': policy['name'],
|
||||||
'status': status})
|
'status': status})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -584,7 +585,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
new_status,
|
new_status,
|
||||||
mgmt_url)
|
mgmt_url)
|
||||||
LOG.debug("Policy %(policy)s vnf is at %(status)s",
|
LOG.debug("Policy %(policy)s vnf is at %(status)s",
|
||||||
{'policy': policy['id'],
|
{'policy': policy['name'],
|
||||||
'status': new_status})
|
'status': new_status})
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@@ -601,7 +602,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
region_name=region_name
|
region_name=region_name
|
||||||
)
|
)
|
||||||
LOG.debug("Policy %s action is started successfully",
|
LOG.debug("Policy %s action is started successfully",
|
||||||
policy['id'])
|
policy['name'])
|
||||||
return last_event_id
|
return last_event_id
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error("Policy %s action is failed to start",
|
LOG.error("Policy %s action is failed to start",
|
||||||
@@ -618,7 +619,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
def _vnf_policy_action_wait():
|
def _vnf_policy_action_wait():
|
||||||
try:
|
try:
|
||||||
LOG.debug("Policy %s action is in progress",
|
LOG.debug("Policy %s action is in progress",
|
||||||
policy['id'])
|
policy['name'])
|
||||||
mgmt_url = self._vnf_manager.invoke(
|
mgmt_url = self._vnf_manager.invoke(
|
||||||
infra_driver,
|
infra_driver,
|
||||||
'scale_wait',
|
'scale_wait',
|
||||||
@@ -630,12 +631,12 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
last_event_id=last_event_id
|
last_event_id=last_event_id
|
||||||
)
|
)
|
||||||
LOG.debug("Policy %s action is completed successfully",
|
LOG.debug("Policy %s action is completed successfully",
|
||||||
policy['id'])
|
policy['name'])
|
||||||
_handle_vnf_scaling_post(constants.ACTIVE, mgmt_url)
|
_handle_vnf_scaling_post(constants.ACTIVE, mgmt_url)
|
||||||
# TODO(kanagaraj-manickam): Add support for config and mgmt
|
# TODO(kanagaraj-manickam): Add support for config and mgmt
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
LOG.error("Policy %s action is failed to complete",
|
LOG.error("Policy %s action is failed to complete",
|
||||||
policy['id'])
|
policy['name'])
|
||||||
with excutils.save_and_reraise_exception():
|
with excutils.save_and_reraise_exception():
|
||||||
self.set_vnf_error_status_reason(
|
self.set_vnf_error_status_reason(
|
||||||
context,
|
context,
|
||||||
@@ -665,7 +666,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
p['properties'] = policy.get('properties') or policy.get('triggers')
|
p['properties'] = policy.get('properties') or policy.get('triggers')
|
||||||
p['vnf'] = vnf
|
p['vnf'] = vnf
|
||||||
p['name'] = name
|
p['name'] = name
|
||||||
p['id'] = p['name']
|
p['id'] = uuidutils.generate_uuid()
|
||||||
return p
|
return p
|
||||||
|
|
||||||
def get_vnf_policies(
|
def get_vnf_policies(
|
||||||
@@ -704,14 +705,16 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
filters={'name': policy_id})
|
filters={'name': policy_id})
|
||||||
if policies:
|
if policies:
|
||||||
return policies[0]
|
return policies[0]
|
||||||
|
else:
|
||||||
raise exceptions.VnfPolicyNotFound(policy=policy_id,
|
return None
|
||||||
vnf_id=vnf_id)
|
|
||||||
|
|
||||||
def create_vnf_scale(self, context, vnf_id, scale):
|
def create_vnf_scale(self, context, vnf_id, scale):
|
||||||
policy_ = self.get_vnf_policy(context,
|
policy_ = self.get_vnf_policy(context,
|
||||||
scale['scale']['policy'],
|
scale['scale']['policy'],
|
||||||
vnf_id)
|
vnf_id)
|
||||||
|
if not policy_:
|
||||||
|
raise exceptions.VnfPolicyNotFound(policy=scale['scale']['policy'],
|
||||||
|
vnf_id=vnf_id)
|
||||||
policy_.update({'action': scale['scale']['type']})
|
policy_.update({'action': scale['scale']['type']})
|
||||||
self._handle_vnf_scaling(context, policy_)
|
self._handle_vnf_scaling(context, policy_)
|
||||||
|
|
||||||
@@ -732,26 +735,39 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
if not self._vnf_alarm_monitor.process_alarm_for_vnf(vnf_id, trigger):
|
if not self._vnf_alarm_monitor.process_alarm_for_vnf(vnf_id, trigger):
|
||||||
raise exceptions.AlarmUrlInvalid(vnf_id=vnf_id)
|
raise exceptions.AlarmUrlInvalid(vnf_id=vnf_id)
|
||||||
|
|
||||||
policy_ = None
|
|
||||||
action_ = None
|
|
||||||
# validate policy action. if action is composite, split it.
|
# validate policy action. if action is composite, split it.
|
||||||
# ex: SP1-in, SP1-out
|
# ex: respawn%notify
|
||||||
action = trigger['action_name']
|
action = trigger['action_name']
|
||||||
sp_action = action.split('-')
|
action_list = action.split('%')
|
||||||
if len(sp_action) == 2:
|
pl_action_dict = dict()
|
||||||
bk_policy_name = sp_action[0]
|
pl_action_dict['policy_actions'] = dict()
|
||||||
bk_policy_action = sp_action[1]
|
pl_action_dict['policy_actions']['def_actions'] = list()
|
||||||
policies_ = self.get_vnf_policies(context, vnf_id,
|
pl_action_dict['policy_actions']['custom_actions'] = dict()
|
||||||
filters={'name': bk_policy_name})
|
for action in action_list:
|
||||||
if policies_:
|
# validate policy action. if action is composite, split it.
|
||||||
policy_ = policies_[0]
|
# ex: SP1-in, SP1-out
|
||||||
action_ = bk_policy_action
|
action_ = None
|
||||||
|
if action in constants.DEFAULT_ALARM_ACTIONS:
|
||||||
|
pl_action_dict['policy_actions']['def_actions'].append(action)
|
||||||
|
policy_ = self.get_vnf_policy(context, action, vnf_id)
|
||||||
|
if not policy_:
|
||||||
|
sp_action = action.split('-')
|
||||||
|
if len(sp_action) == 2:
|
||||||
|
bk_policy_name = sp_action[0]
|
||||||
|
bk_policy_action = sp_action[1]
|
||||||
|
policies_ = self.get_vnf_policies(
|
||||||
|
context, vnf_id, filters={'name': bk_policy_name})
|
||||||
|
if policies_:
|
||||||
|
policy_ = policies_[0]
|
||||||
|
action_ = bk_policy_action
|
||||||
|
if policy_:
|
||||||
|
pl_action_dict['policy_actions']['custom_actions'].update(
|
||||||
|
{policy_['id']: {'bckend_policy': policy_,
|
||||||
|
'bckend_action': action_}})
|
||||||
|
|
||||||
if not policy_:
|
LOG.debug("Trigger %s is validated successfully", trigger)
|
||||||
if action not in constants.DEFAULT_ALARM_ACTIONS:
|
|
||||||
policy_ = self.get_vnf_policy(context, action, vnf_id)
|
return pl_action_dict
|
||||||
LOG.debug("Trigger %s is validated successfully", trigger)
|
|
||||||
return policy_, action_
|
|
||||||
# validate url
|
# validate url
|
||||||
|
|
||||||
def _get_vnf_triggers(self, context, vnf_id, filters=None, fields=None):
|
def _get_vnf_triggers(self, context, vnf_id, filters=None, fields=None):
|
||||||
@@ -786,36 +802,48 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
|
|||||||
action, 'execute_action', plugin=self, context=context,
|
action, 'execute_action', plugin=self, context=context,
|
||||||
vnf_dict=vnf_dict, args={})
|
vnf_dict=vnf_dict, args={})
|
||||||
|
|
||||||
if trigger.get('bckend_policy'):
|
# Multiple actions support
|
||||||
bckend_policy = trigger['bckend_policy']
|
if trigger.get('policy_actions'):
|
||||||
bckend_policy_type = bckend_policy['type']
|
policy_actions = trigger['policy_actions']
|
||||||
if bckend_policy_type == constants.POLICY_SCALING:
|
if policy_actions.get('def_actions'):
|
||||||
if vnf_dict['status'] != constants.ACTIVE:
|
for action in policy_actions['def_actions']:
|
||||||
LOG.info("Scaling Policy action skipped due to status:"
|
self._vnf_action.invoke(
|
||||||
" %(status)s for vnf: %(vnfid)s",
|
action, 'execute_action', plugin=self, context=context,
|
||||||
{"status": vnf_dict['status'],
|
vnf_dict=vnf_dict, args={})
|
||||||
"vnfid": vnf_dict['id']})
|
if policy_actions.get('custom_actions'):
|
||||||
return
|
custom_actions = policy_actions['custom_actions']
|
||||||
action = 'autoscaling'
|
for pl_action, pl_action_dict in custom_actions.items():
|
||||||
scale = {}
|
bckend_policy = pl_action_dict['bckend_policy']
|
||||||
scale.setdefault('scale', {})
|
bckend_action = pl_action_dict['bckend_action']
|
||||||
scale['scale']['type'] = trigger['bckend_action']
|
bckend_policy_type = bckend_policy['type']
|
||||||
scale['scale']['policy'] = bckend_policy['name']
|
if bckend_policy_type == constants.POLICY_SCALING:
|
||||||
self._vnf_action.invoke(
|
if vnf_dict['status'] != constants.ACTIVE:
|
||||||
action, 'execute_action', plugin=self, context=context,
|
LOG.info(_("Scaling Policy action"
|
||||||
vnf_dict=vnf_dict, args=scale)
|
"skipped due to status:"
|
||||||
|
"%(status)s for vnf: %(vnfid)s"),
|
||||||
|
{"status": vnf_dict['status'],
|
||||||
|
"vnfid": vnf_dict['id']})
|
||||||
|
return
|
||||||
|
action = 'autoscaling'
|
||||||
|
scale = {}
|
||||||
|
scale.setdefault('scale', {})
|
||||||
|
scale['scale']['type'] = bckend_action
|
||||||
|
scale['scale']['policy'] = bckend_policy['name']
|
||||||
|
self._vnf_action.invoke(
|
||||||
|
action, 'execute_action', plugin=self,
|
||||||
|
context=context, vnf_dict=vnf_dict, args=scale)
|
||||||
|
|
||||||
def create_vnf_trigger(
|
def create_vnf_trigger(
|
||||||
self, context, vnf_id, trigger):
|
self, context, vnf_id, trigger):
|
||||||
trigger_ = self.get_vnf_trigger(
|
trigger_ = self.get_vnf_trigger(
|
||||||
context, vnf_id, trigger['trigger']['policy_name'])
|
context, vnf_id, trigger['trigger']['policy_name'])
|
||||||
|
# action_name before analyzing
|
||||||
trigger_.update({'action_name': trigger['trigger']['action_name']})
|
trigger_.update({'action_name': trigger['trigger']['action_name']})
|
||||||
trigger_.update({'params': trigger['trigger']['params']})
|
trigger_.update({'params': trigger['trigger']['params']})
|
||||||
bk_policy, bk_action = self._validate_alarming_policy(
|
policy_actions = self._validate_alarming_policy(
|
||||||
context, vnf_id, trigger_)
|
context, vnf_id, trigger_)
|
||||||
if bk_policy:
|
if policy_actions:
|
||||||
trigger_.update({'bckend_policy': bk_policy,
|
trigger_.update(policy_actions)
|
||||||
'bckend_action': bk_action})
|
|
||||||
self._handle_vnf_monitoring(context, trigger_)
|
self._handle_vnf_monitoring(context, trigger_)
|
||||||
return trigger['trigger']
|
return trigger['trigger']
|
||||||
|
|
||||||
|
|||||||
@@ -32,12 +32,12 @@ def _log_monitor_events(context, vnf_dict, evt_details):
|
|||||||
details=evt_details)
|
details=evt_details)
|
||||||
|
|
||||||
|
|
||||||
class VNFActionLogOnly(abstract_action.AbstractPolicyAction):
|
class VNFActionLog(abstract_action.AbstractPolicyAction):
|
||||||
def get_type(self):
|
def get_type(self):
|
||||||
return 'log_only'
|
return 'log'
|
||||||
|
|
||||||
def get_name(self):
|
def get_name(self):
|
||||||
return 'log_only'
|
return 'log'
|
||||||
|
|
||||||
def get_description(self):
|
def get_description(self):
|
||||||
return 'Tacker VNF logging policy'
|
return 'Tacker VNF logging policy'
|
||||||
|
|||||||
Reference in New Issue
Block a user