Refactor: separating backend actions out from monitor

Currently, backend actions are tightly coupled with monitor module.
This is like a barrier when we have a various actions in the future.
Also, it will be good for separating monitoring-related features out
from tacker-server. This patch also proposes a policy action framework so
that VNF operators can easily add their own actions.

Change-Id: I6ad163f7435c3b778810f96c506c77298be0c53d
Closes-bug: #1582446
This commit is contained in:
doantungbk 2017-04-05 20:12:15 -07:00
parent aa36918f77
commit 829f50e915
16 changed files with 388 additions and 165 deletions

View File

@ -0,0 +1,91 @@
Tacker Policy Framework
=======================
This section will introduce framework for tacker policy actions.
* Introduction
* How to write a new policy action
* Event and Auditing support
* How to combine policy actions with existing monitoring frameworks in Tacker
Introduction
------------
Tacker policy actions framework provides the NFV operators and VNF vendors to
write a pluggable action that manages their own VNFs. Currently Tacker
already provided some common actions like autoscaling, respawning, and
logging. With this framework the custom actions can be easily
applied for the management purpose.
How to write a new policy action
--------------------------------
A policy action for tacker is a python module which contains a class that
inherits from
"tacker.vnfm.policy_actions.abstract_action.AbstractPolicyAction". If the
driver depends/imports more than one module, then create a new python package
under tacker/vnfm/policy_actions folder. After this we have to mention our
driver path in setup.cfg file in root directory.
For example:
::
tacker.tacker.policy.actions =
respawn = tacker.vnfm.policy_actions.respawn.respawn:VNFActionRespawn
Following methods need to be overridden in the new action:
``def get_type(self)``
This method must return the type of action. ex: respawn
``def get_name(self)``
This method must return the symbolic name of the vnf policy action.
``def get_description(self)``
This method must return the description for the policy action.
``def execute_action(self, plugin, context, vnf, arguments)``
This method must expose what will be executed with the policy action.
'arguments' is used to add more options for policy actions. For example,
if action is scaling, 'arguments' should let you know
'scaling-out' or 'scaling-in' will be applied.
Event and Auditing support
--------------------------
This function can be used to describe the execution process of policy.
For example:
::
_log_monitor_events(context, vnf_dict, "ActionRespawnHeat invoked")
How to combine policy with existing monitoring framework in Tacker
------------------------------------------------------------------
In the monitoring policy section, you can specify the monitors details with
corresponding action.
The below example shows how policy is used for alarm monitor.
Example Template
----------------
::
policies:
- vdu1_cpu_usage_monitoring_policy:
type: tosca.policies.tacker.Alarming
triggers:
resize_compute:
event_type:
type: tosca.events.resource.utilization
implementation: ceilometer
metrics: cpu_util
condition:
threshold: 50
constraint: utilization greater_than 50%
period: 65
evaluations: 1
method: avg
comparison_operator: gt
actions: [respawn]

View File

@ -13,6 +13,9 @@ namespace = tacker.vnfm.mgmt_drivers.openwrt.openwrt
namespace = tacker.vnfm.monitor_drivers.http_ping.http_ping
namespace = tacker.vnfm.monitor_drivers.ping.ping
namespace = tacker.vnfm.monitor_drivers.ceilometer.ceilometer
namespace = tacker.tacker.policy_actions.autoscaling.autoscaling
namespace = tacker.tacker.policy_actions.respawn.respawn
namespace = tacker.tacker.policy_actions.log.log
namespace = tacker.alarm_receiver
namespace = keystonemiddleware.auth_token
namespace = oslo.middleware

View File

@ -59,6 +59,11 @@ tacker.tacker.monitor.drivers =
http_ping = tacker.vnfm.monitor_drivers.http_ping.http_ping:VNFMonitorHTTPPing
tacker.tacker.alarm_monitor.drivers =
ceilometer = tacker.vnfm.monitor_drivers.ceilometer.ceilometer:VNFMonitorCeilometer
tacker.tacker.policy.actions =
autoscaling = tacker.vnfm.policy_actions.autoscaling.autoscaling:VNFActionAutoscaling
respawn = tacker.vnfm.policy_actions.respawn.respawn:VNFActionRespawn
log_only = tacker.vnfm.policy_actions.log.log:VNFActionLogOnly
log_and_kill = tacker.vnfm.policy_actions.log.log:VNFActionLogAndKill
oslo.config.opts =
tacker.common.config = tacker.common.config:config_opts
tacker.wsgi = tacker.wsgi:config_opts

View File

@ -15,7 +15,7 @@ DEFAULT_ALARM_ACTIONS = ['respawn', 'log', 'log_and_kill', 'notify']
VNF_CIRROS_CREATE_TIMEOUT = 300
VNFC_CREATE_TIMEOUT = 600
VNF_CIRROS_DELETE_TIMEOUT = 300
VNF_CIRROS_DEAD_TIMEOUT = 250
VNF_CIRROS_DEAD_TIMEOUT = 500
ACTIVE_SLEEP_TIME = 3
DEAD_SLEEP_TIME = 1
SCALE_WINDOW_SLEEP_TIME = 120

View File

@ -63,7 +63,7 @@ topology_template:
type: tosca.nodes.nfv.VDU.Tacker
properties:
image: cirros-0.3.5-x86_64-disk
flavor: m1.medium
flavor: m1.tiny
availability_zone: nova
mgmt_driver: noop
config: |

View File

@ -434,33 +434,20 @@ class TestVNFMPlugin(db_base.SqlTestCase):
self.assertEqual(expected_result, trigger_result)
@patch('tacker.db.vnfm.vnfm_db.VNFMPluginDb.get_vnf')
@patch('tacker.vnfm.monitor.ActionPolicy.get_policy')
def test_create_vnf_trigger_respawn(self, mock_get_policy, mock_get_vnf):
def test_create_vnf_trigger_respawn(self, mock_get_vnf):
dummy_vnf = self._get_dummy_active_vnf(
utils.vnfd_alarm_respawn_tosca_template)
mock_get_vnf.return_value = dummy_vnf
mock_action_class = mock.Mock()
mock_get_policy.return_value = mock_action_class
self._test_create_vnf_trigger(policy_name="vdu_hcpu_usage_respawning",
action_value="respawn")
mock_get_policy.assert_called_once_with('respawn', 'test_vim')
mock_action_class.execute_action.assert_called_once_with(
self.vnfm_plugin, dummy_vnf)
@patch('tacker.db.vnfm.vnfm_db.VNFMPluginDb.get_vnf')
@patch('tacker.vnfm.monitor.ActionPolicy.get_policy')
def test_create_vnf_trigger_scale(self, mock_get_policy, mock_get_vnf):
def test_create_vnf_trigger_scale(self, mock_get_vnf):
dummy_vnf = self._get_dummy_active_vnf(
utils.vnfd_alarm_scale_tosca_template)
mock_get_vnf.return_value = dummy_vnf
mock_action_class = mock.Mock()
mock_get_policy.return_value = mock_action_class
scale_body = {'scale': {'policy': 'SP1', 'type': 'out'}}
self._test_create_vnf_trigger(policy_name="vdu_hcpu_usage_scaling_out",
action_value="SP1-out")
mock_get_policy.assert_called_once_with('scaling', 'test_vim')
mock_action_class.execute_action.assert_called_once_with(
self.vnfm_plugin, dummy_vnf, scale_body)
@patch('tacker.db.vnfm.vnfm_db.VNFMPluginDb.get_vnf')
def test_get_vnf_policies(self, mock_get_vnf):

View File

@ -14,7 +14,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import abc
import inspect
import threading
import time
@ -23,14 +23,12 @@ from oslo_config import cfg
from oslo_log import log as logging
from oslo_serialization import jsonutils
from oslo_utils import timeutils
import six
from tacker.common import driver_manager
from tacker import context as t_context
from tacker.db.common_services import common_services_db
from tacker.plugins.common import constants
from tacker.vnfm.infra_drivers.openstack import heat_client as hc
from tacker.vnfm import vim_client
LOG = logging.getLogger(__name__)
CONF = cfg.CONF
@ -281,126 +279,3 @@ class VNFAlarmMonitor(object):
def process_alarm(self, driver, vnf_dict, kwargs):
return self._invoke(driver,
vnf=vnf_dict, kwargs=kwargs)
@six.add_metaclass(abc.ABCMeta)
class ActionPolicy(object):
@classmethod
@abc.abstractmethod
def execute_action(cls, plugin, vnf_dict):
pass
_POLICIES = {}
@staticmethod
def register(policy, infra_driver=None):
def _register(cls):
cls._POLICIES.setdefault(policy, {})[infra_driver] = cls
return cls
return _register
@classmethod
def get_policy(cls, policy, infra_driver=None):
action_clses = cls._POLICIES.get(policy)
if not action_clses:
return None
cls = action_clses.get(infra_driver)
if cls:
return cls
return action_clses.get(None)
@classmethod
def get_supported_actions(cls):
return cls._POLICIES.keys()
@ActionPolicy.register('respawn', 'openstack')
class ActionRespawnHeat(ActionPolicy):
@classmethod
def execute_action(cls, plugin, vnf_dict):
vnf_id = vnf_dict['id']
LOG.info(_('vnf %s is dead and needs to be respawned'), vnf_id)
attributes = vnf_dict['attributes']
vim_id = vnf_dict['vim_id']
# TODO(anyone) set the current request ctxt
context = t_context.get_admin_context()
def _update_failure_count():
failure_count = int(attributes.get('failure_count', '0')) + 1
failure_count_str = str(failure_count)
LOG.debug(_("vnf %(vnf_id)s failure count %(failure_count)s"),
{'vnf_id': vnf_id, 'failure_count': failure_count_str})
attributes['failure_count'] = failure_count_str
attributes['dead_instance_id_' + failure_count_str] = vnf_dict[
'instance_id']
def _fetch_vim(vim_uuid):
return vim_client.VimClient().get_vim(context, vim_uuid)
def _delete_heat_stack(vim_auth):
placement_attr = vnf_dict.get('placement_attr', {})
region_name = placement_attr.get('region_name')
heatclient = hc.HeatClient(auth_attr=vim_auth,
region_name=region_name)
heatclient.delete(vnf_dict['instance_id'])
LOG.debug(_("Heat stack %s delete initiated"), vnf_dict[
'instance_id'])
_log_monitor_events(context, vnf_dict, "ActionRespawnHeat invoked")
def _respin_vnf():
update_vnf_dict = plugin.create_vnf_sync(context, vnf_dict)
LOG.info(_('respawned new vnf %s'), update_vnf_dict['id'])
plugin.config_vnf(context, update_vnf_dict)
return update_vnf_dict
if plugin._mark_vnf_dead(vnf_dict['id']):
_update_failure_count()
vim_res = _fetch_vim(vim_id)
if vnf_dict['attributes'].get('monitoring_policy'):
plugin._vnf_monitor.mark_dead(vnf_dict['id'])
_delete_heat_stack(vim_res['vim_auth'])
updated_vnf = _respin_vnf()
plugin.add_vnf_to_monitor(updated_vnf, vim_res['vim_type'])
LOG.debug(_("VNF %s added to monitor thread"), updated_vnf[
'id'])
if vnf_dict['attributes'].get('alarming_policy'):
_delete_heat_stack(vim_res['vim_auth'])
vnf_dict['attributes'].pop('alarming_policy')
_respin_vnf()
@ActionPolicy.register('scaling')
class ActionAutoscalingHeat(ActionPolicy):
@classmethod
def execute_action(cls, plugin, vnf_dict, scale):
vnf_id = vnf_dict['id']
_log_monitor_events(t_context.get_admin_context(),
vnf_dict,
"ActionAutoscalingHeat invoked")
plugin.create_vnf_scale(t_context.get_admin_context(), vnf_id, scale)
@ActionPolicy.register('log')
class ActionLogOnly(ActionPolicy):
@classmethod
def execute_action(cls, plugin, vnf_dict):
vnf_id = vnf_dict['id']
LOG.error(_('vnf %s dead'), vnf_id)
_log_monitor_events(t_context.get_admin_context(),
vnf_dict,
"ActionLogOnly invoked")
@ActionPolicy.register('log_and_kill')
class ActionLogAndKill(ActionPolicy):
@classmethod
def execute_action(cls, plugin, vnf_dict):
_log_monitor_events(t_context.get_admin_context(),
vnf_dict,
"ActionLogAndKill invoked")
vnf_id = vnf_dict['id']
if plugin._mark_vnf_dead(vnf_dict['id']):
if vnf_dict['attributes'].get('monitoring_policy'):
plugin._vnf_monitor.mark_dead(vnf_dict['id'])
plugin.delete_vnf(t_context.get_admin_context(), vnf_id)
LOG.error(_('vnf %s dead'), vnf_id)

View File

@ -43,7 +43,8 @@ CONF = cfg.CONF
def config_opts():
return [('tacker', VNFMMgmtMixin.OPTS),
('tacker', VNFMPlugin.OPTS)]
('tacker', VNFMPlugin.OPTS_INFRA_DRIVER),
('tacker', VNFMPlugin.OPTS_POLICY_ACTION)]
class VNFMMgmtMixin(object):
@ -111,12 +112,21 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
Plugin which supports Tacker framework
"""
OPTS = [
OPTS_INFRA_DRIVER = [
cfg.ListOpt(
'infra_driver', default=['noop', 'openstack'],
help=_('Hosting vnf drivers tacker plugin will use')),
]
cfg.CONF.register_opts(OPTS, 'tacker')
cfg.CONF.register_opts(OPTS_INFRA_DRIVER, 'tacker')
OPTS_POLICY_ACTION = [
cfg.ListOpt(
'policy_action', default=['autoscaling', 'respawn',
'log_only', 'log_and_kill'],
help=_('Hosting vnf drivers tacker plugin will use')),
]
cfg.CONF.register_opts(OPTS_POLICY_ACTION, 'tacker')
supported_extension_aliases = ['vnfm']
def __init__(self):
@ -127,6 +137,9 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
self._vnf_manager = driver_manager.DriverManager(
'tacker.tacker.vnfm.drivers',
cfg.CONF.tacker.infra_driver)
self._vnf_action = driver_manager.DriverManager(
'tacker.tacker.policy.actions',
cfg.CONF.tacker.policy_action)
self._vnf_monitor = monitor.VNFMonitor(self.boot_wait)
self._vnf_alarm_monitor = monitor.VNFAlarmMonitor()
@ -203,15 +216,15 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
tosca)
LOG.debug(_('vnfd %s'), vnfd)
def add_vnf_to_monitor(self, vnf_dict, infra_driver):
def add_vnf_to_monitor(self, context, vnf_dict):
dev_attrs = vnf_dict['attributes']
mgmt_url = vnf_dict['mgmt_url']
if 'monitoring_policy' in dev_attrs and mgmt_url:
def action_cb(action):
action_cls = monitor.ActionPolicy.get_policy(action,
infra_driver)
if action_cls:
action_cls.execute_action(self, hosting_vnf['vnf'])
LOG.debug('policy action: %s', action)
self._vnf_action.invoke(
action, 'execute_action', plugin=self, context=context,
vnf_dict=hosting_vnf['vnf'], args={})
hosting_vnf = self._vnf_monitor.to_hosting_vnf(
vnf_dict, action_cb)
@ -376,7 +389,7 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
def create_vnf_wait():
self._create_vnf_wait(context, vnf_dict, vim_auth, infra_driver)
if vnf_dict['status'] is not constants.ERROR:
self.add_vnf_to_monitor(vnf_dict, infra_driver)
self.add_vnf_to_monitor(context, vnf_dict)
self.config_vnf(context, vnf_dict)
self.spawn_n(create_vnf_wait)
return vnf_dict
@ -760,11 +773,9 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
if trigger['action_name'] in constants.DEFAULT_ALARM_ACTIONS:
action = trigger['action_name']
LOG.debug(_('vnf for monitoring: %s'), vnf_dict)
infra_driver, vim_auth = self._get_infra_driver(context, vnf_dict)
action_cls = monitor.ActionPolicy.get_policy(action,
infra_driver)
if action_cls:
action_cls.execute_action(self, vnf_dict)
self._vnf_action.invoke(
action, 'execute_action', plugin=self, context=context,
vnf_dict=vnf_dict, args={})
if trigger.get('bckend_policy'):
bckend_policy = trigger['bckend_policy']
@ -776,17 +787,14 @@ class VNFMPlugin(vnfm_db.VNFMPluginDb, VNFMMgmtMixin):
{"status": vnf_dict['status'],
"vnfid": vnf_dict['id']})
return
action = 'scaling'
action = 'autoscaling'
scale = {}
scale.setdefault('scale', {})
scale['scale']['type'] = trigger['bckend_action']
scale['scale']['policy'] = bckend_policy['name']
infra_driver, vim_auth = self._get_infra_driver(context,
vnf_dict)
action_cls = monitor.ActionPolicy.get_policy(action,
infra_driver)
if action_cls:
action_cls.execute_action(self, vnf_dict, scale)
self._vnf_action.invoke(
action, 'execute_action', plugin=self, context=context,
vnf_dict=vnf_dict, args=scale)
def create_vnf_trigger(
self, context, vnf_id, trigger):

View File

View File

@ -0,0 +1,38 @@
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import abc
import six
@six.add_metaclass(abc.ABCMeta)
class AbstractPolicyAction(object):
@abc.abstractmethod
def get_type(self):
"""Return one of predefined type of the hosting vnf drivers."""
pass
@abc.abstractmethod
def get_name(self):
"""Return a symbolic name for the service VM plugin."""
pass
@abc.abstractmethod
def get_description(self):
pass
@abc.abstractmethod
def execute_action(self, plugin, context, vnf_dict, args):
"""args: policy is enabled to execute with additional arguments."""
pass

View File

@ -0,0 +1,50 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from oslo_log import log as logging
from oslo_utils import timeutils
from tacker.db.common_services import common_services_db
from tacker.plugins.common import constants
from tacker.vnfm.policy_actions import abstract_action
LOG = logging.getLogger(__name__)
def _log_monitor_events(context, vnf_dict, evt_details):
_cos_db_plg = common_services_db.CommonServicesPluginDb()
_cos_db_plg.create_event(context, res_id=vnf_dict['id'],
res_type=constants.RES_TYPE_VNF,
res_state=vnf_dict['status'],
evt_type=constants.RES_EVT_MONITOR,
tstamp=timeutils.utcnow(),
details=evt_details)
class VNFActionAutoscaling(abstract_action.AbstractPolicyAction):
def get_type(self):
return 'autoscaling'
def get_name(self):
return 'autoscaling'
def get_description(self):
return 'Tacker VNF auto-scaling policy'
def execute_action(self, plugin, context, vnf_dict, args):
vnf_id = vnf_dict['id']
_log_monitor_events(context,
vnf_dict,
"ActionAutoscalingHeat invoked")
plugin.create_vnf_scale(context, vnf_id, args)

View File

@ -0,0 +1,72 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from oslo_log import log as logging
from oslo_utils import timeutils
from tacker.db.common_services import common_services_db
from tacker.plugins.common import constants
from tacker.vnfm.policy_actions import abstract_action
LOG = logging.getLogger(__name__)
def _log_monitor_events(context, vnf_dict, evt_details):
_cos_db_plg = common_services_db.CommonServicesPluginDb()
_cos_db_plg.create_event(context, res_id=vnf_dict['id'],
res_type=constants.RES_TYPE_VNF,
res_state=vnf_dict['status'],
evt_type=constants.RES_EVT_MONITOR,
tstamp=timeutils.utcnow(),
details=evt_details)
class VNFActionLogOnly(abstract_action.AbstractPolicyAction):
def get_type(self):
return 'log_only'
def get_name(self):
return 'log_only'
def get_description(self):
return 'Tacker VNF logging policy'
def execute_action(self, plugin, context, vnf_dict, args):
vnf_id = vnf_dict['id']
LOG.error(_('vnf %s dead'), vnf_id)
_log_monitor_events(context,
vnf_dict,
"ActionLogOnly invoked")
class VNFActionLogAndKill(abstract_action.AbstractPolicyAction):
def get_type(self):
return 'log_and_kill'
def get_name(self):
return 'log_and_kill'
def get_description(self):
return 'Tacker VNF log_and_kill policy'
def execute_action(self, plugin, context, vnf_dict, args):
_log_monitor_events(context,
vnf_dict,
"ActionLogAndKill invoked")
vnf_id = vnf_dict['id']
if plugin._mark_vnf_dead(vnf_dict['id']):
if vnf_dict['attributes'].get('monitoring_policy'):
plugin._vnf_monitor.mark_dead(vnf_dict['id'])
plugin.delete_vnf(context, vnf_id)
LOG.error(_('vnf %s dead'), vnf_id)

View File

@ -0,0 +1,94 @@
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
#
from oslo_log import log as logging
from oslo_utils import timeutils
from tacker.db.common_services import common_services_db
from tacker.plugins.common import constants
from tacker.vnfm.infra_drivers.openstack import heat_client as hc
from tacker.vnfm.policy_actions import abstract_action
from tacker.vnfm import vim_client
LOG = logging.getLogger(__name__)
def _log_monitor_events(context, vnf_dict, evt_details):
_cos_db_plg = common_services_db.CommonServicesPluginDb()
_cos_db_plg.create_event(context, res_id=vnf_dict['id'],
res_type=constants.RES_TYPE_VNF,
res_state=vnf_dict['status'],
evt_type=constants.RES_EVT_MONITOR,
tstamp=timeutils.utcnow(),
details=evt_details)
class VNFActionRespawn(abstract_action.AbstractPolicyAction):
def get_type(self):
return 'respawn'
def get_name(self):
return 'respawn'
def get_description(self):
return 'Tacker VNF respawning policy'
def execute_action(self, plugin, context, vnf_dict, args):
vnf_id = vnf_dict['id']
LOG.info(_('vnf %s is dead and needs to be respawned'), vnf_id)
attributes = vnf_dict['attributes']
vim_id = vnf_dict['vim_id']
def _update_failure_count():
failure_count = int(attributes.get('failure_count', '0')) + 1
failure_count_str = str(failure_count)
LOG.debug(_("vnf %(vnf_id)s failure count %(failure_count)s"),
{'vnf_id': vnf_id, 'failure_count': failure_count_str})
attributes['failure_count'] = failure_count_str
attributes['dead_instance_id_' + failure_count_str] = vnf_dict[
'instance_id']
def _fetch_vim(vim_uuid):
return vim_client.VimClient().get_vim(context, vim_uuid)
def _delete_heat_stack(vim_auth):
placement_attr = vnf_dict.get('placement_attr', {})
region_name = placement_attr.get('region_name')
heatclient = hc.HeatClient(auth_attr=vim_auth,
region_name=region_name)
heatclient.delete(vnf_dict['instance_id'])
LOG.debug(_("Heat stack %s delete initiated"), vnf_dict[
'instance_id'])
_log_monitor_events(context, vnf_dict, "ActionRespawnHeat invoked")
def _respin_vnf():
update_vnf_dict = plugin.create_vnf_sync(context, vnf_dict)
LOG.info(_('respawned new vnf %s'), update_vnf_dict['id'])
plugin.config_vnf(context, update_vnf_dict)
return update_vnf_dict
if plugin._mark_vnf_dead(vnf_dict['id']):
_update_failure_count()
vim_res = _fetch_vim(vim_id)
if vnf_dict['attributes'].get('monitoring_policy'):
plugin._vnf_monitor.mark_dead(vnf_dict['id'])
_delete_heat_stack(vim_res['vim_auth'])
updated_vnf = _respin_vnf()
plugin.add_vnf_to_monitor(context, updated_vnf)
LOG.debug(_("VNF %s added to monitor thread"), updated_vnf[
'id'])
if vnf_dict['attributes'].get('alarming_policy'):
_delete_heat_stack(vim_res['vim_auth'])
vnf_dict['attributes'].pop('alarming_policy')
_respin_vnf()