Add support to capture error_reason for the VNF
Partial-Bug: #1524214 Change-Id: I4897e7e4ebdb8c887fb9882e693e5b3d3f4664e5
This commit is contained in:
parent
10c05eb874
commit
edd3b04e5b
@ -1 +1 @@
|
||||
5246a6bd410f
|
||||
acf941e54075
|
||||
|
@ -0,0 +1,38 @@
|
||||
# Copyright 2016 OpenStack Foundation
|
||||
#
|
||||
# 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.
|
||||
#
|
||||
|
||||
"""Add error_reason to device
|
||||
|
||||
Revision ID: acf941e54075
|
||||
Revises: 5246a6bd410f
|
||||
Create Date: 2016-04-07 23:53:56.623647
|
||||
|
||||
"""
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision = 'acf941e54075'
|
||||
down_revision = '5246a6bd410f'
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
def upgrade(active_plugins=None, options=None):
|
||||
op.add_column('devices', sa.Column('error_reason',
|
||||
sa.Text(), nullable=True))
|
||||
|
||||
|
||||
def downgrade(active_plugins=None, options=None):
|
||||
op.drop_column('devices', 'error_reason')
|
@ -119,6 +119,7 @@ class Device(model_base.BASE, models_v1.HasTenant):
|
||||
vim_id = sa.Column(sa.String(36), sa.ForeignKey('vims.id'), nullable=False)
|
||||
placement_attr = sa.Column(sa.PickleType, nullable=True)
|
||||
vim = orm.relationship('Vim')
|
||||
error_reason = sa.Column(sa.Text, nullable=True)
|
||||
|
||||
|
||||
class DeviceAttribute(model_base.BASE, models_v1.HasId):
|
||||
@ -195,7 +196,7 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
||||
}
|
||||
key_list = ('id', 'tenant_id', 'name', 'description', 'instance_id',
|
||||
'vim_id', 'placement_attr', 'template_id', 'status',
|
||||
'mgmt_url')
|
||||
'mgmt_url', 'error_reason')
|
||||
res.update((key, device_db[key]) for key in key_list)
|
||||
return self._fields(res, fields)
|
||||
|
||||
@ -354,7 +355,8 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
||||
template_id=template_id,
|
||||
vim_id=vim_id,
|
||||
placement_attr=placement_attr,
|
||||
status=constants.PENDING_CREATE)
|
||||
status=constants.PENDING_CREATE,
|
||||
error_reason=None)
|
||||
context.session.add(device_db)
|
||||
for key, value in attributes.items():
|
||||
arg = DeviceAttribute(
|
||||
@ -493,6 +495,12 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
||||
return [device for device in devices
|
||||
if uuidutils.is_uuid_like(device['id'])]
|
||||
|
||||
def set_device_error_status_reason(self, context, device_id, new_reason):
|
||||
with context.session.begin(subtransactions=True):
|
||||
(self._model_query(context, Device).
|
||||
filter(Device.id == device_id).
|
||||
update({'error_reason': new_reason}))
|
||||
|
||||
def _mark_device_status(self, device_id, exclude_status, new_status):
|
||||
context = t_context.get_admin_context()
|
||||
with context.session.begin(subtransactions=True):
|
||||
@ -540,7 +548,8 @@ class VNFMPluginDb(vnfm.VNFMPluginBase, db_base.CommonDbMixin):
|
||||
mgmt_url=device_db.mgmt_url,
|
||||
status=device_db.status,
|
||||
vim_id=device_db.vim_id,
|
||||
placement_attr=device_db.placement_attr)
|
||||
placement_attr=device_db.placement_attr,
|
||||
error_reason=device_db.error_reason)
|
||||
context.session.add(new_device_db)
|
||||
|
||||
(self._model_query(context, DeviceAttribute).
|
||||
|
@ -66,7 +66,7 @@ class DeviceCreateFailed(exceptions.TackerException):
|
||||
|
||||
|
||||
class DeviceCreateWaitFailed(exceptions.TackerException):
|
||||
message = _('waiting for creation of VNF %(device_id)s failed')
|
||||
message = _('%(reason)s')
|
||||
|
||||
|
||||
class DeviceDeleteFailed(exceptions.TackerException):
|
||||
@ -298,6 +298,11 @@ RESOURCE_ATTRIBUTE_MAP = {
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
},
|
||||
'error_reason': {
|
||||
'allow_post': False,
|
||||
'allow_put': False,
|
||||
'is_visible': True,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
@ -417,6 +417,7 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver):
|
||||
stack = heatclient_.get(device_id)
|
||||
status = stack.stack_status
|
||||
stack_retries = STACK_RETRIES
|
||||
error_reason = None
|
||||
while status == 'CREATE_IN_PROGRESS' and stack_retries > 0:
|
||||
time.sleep(STACK_RETRY_WAIT)
|
||||
try:
|
||||
@ -433,14 +434,22 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver):
|
||||
|
||||
LOG.debug(_('stack status: %(stack)s %(status)s'),
|
||||
{'stack': str(stack), 'status': status})
|
||||
if stack_retries == 0:
|
||||
LOG.warning(_("Resource creation is"
|
||||
" not completed within %(wait)s seconds as "
|
||||
"creation of Stack %(stack)s is not completed"),
|
||||
{'wait': (STACK_RETRIES * STACK_RETRY_WAIT),
|
||||
'stack': device_id})
|
||||
if status != 'CREATE_COMPLETE':
|
||||
raise vnfm.DeviceCreateWaitFailed(device_id=device_id)
|
||||
if stack_retries == 0 and status != 'CREATE_COMPLETE':
|
||||
error_reason = _("Resource creation is not completed within"
|
||||
" {wait} seconds as creation of stack {stack}"
|
||||
" is not completed").format(
|
||||
wait=(STACK_RETRIES * STACK_RETRY_WAIT),
|
||||
stack=device_id)
|
||||
LOG.warning(_("VNF Creation failed: %(reason)s"),
|
||||
{'reason': error_reason})
|
||||
raise vnfm.DeviceCreateWaitFailed(device_id=device_id,
|
||||
reason=error_reason)
|
||||
|
||||
elif stack_retries != 0 and status != 'CREATE_COMPLETE':
|
||||
error_reason = stack.stack_status_reason
|
||||
raise vnfm.DeviceCreateWaitFailed(device_id=device_id,
|
||||
reason=error_reason)
|
||||
|
||||
outputs = stack.outputs
|
||||
LOG.debug(_('outputs %s'), outputs)
|
||||
PREFIX = 'mgmt_ip-'
|
||||
@ -510,6 +519,7 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver):
|
||||
|
||||
stack = heatclient_.get(device_id)
|
||||
status = stack.stack_status
|
||||
error_reason = None
|
||||
stack_retries = STACK_RETRIES
|
||||
while (status == 'DELETE_IN_PROGRESS' and stack_retries > 0):
|
||||
time.sleep(STACK_RETRY_WAIT)
|
||||
@ -526,16 +536,23 @@ class DeviceHeat(abstract_driver.DeviceAbstractDriver):
|
||||
status = stack.stack_status
|
||||
stack_retries = stack_retries - 1
|
||||
|
||||
if stack_retries == 0:
|
||||
LOG.warning(_("Resource cleanup for device is"
|
||||
" not completed within %(wait)s seconds as "
|
||||
"deletion of Stack %(stack)s is not completed"),
|
||||
{'wait': (STACK_RETRIES * STACK_RETRY_WAIT),
|
||||
'stack': device_id})
|
||||
if status != 'DELETE_COMPLETE':
|
||||
LOG.warning(_("device (%(device_id)d) deletion is not completed. "
|
||||
"%(stack_status)s"),
|
||||
{'device_id': device_id, 'stack_status': status})
|
||||
if stack_retries == 0 and status != 'DELETE_COMPLETE':
|
||||
error_reason = _("Resource cleanup for device is"
|
||||
" not completed within {wait} seconds as "
|
||||
"deletion of Stack {stack} is "
|
||||
"not completed").format(stack=device_id,
|
||||
wait=(STACK_RETRIES * STACK_RETRY_WAIT))
|
||||
LOG.warning(error_reason)
|
||||
raise vnfm.DeviceCreateWaitFailed(device_id=device_id,
|
||||
reason=error_reason)
|
||||
|
||||
if stack_retries != 0 and status != 'DELETE_COMPLETE':
|
||||
error_reason = _("device {device_id} deletion is not completed. "
|
||||
"{stack_status}").format(device_id=device_id,
|
||||
stack_status=status)
|
||||
LOG.warning(error_reason)
|
||||
raise vnfm.DeviceCreateWaitFailed(device_id=device_id,
|
||||
reason=error_reason)
|
||||
|
||||
|
||||
class HeatClient(object):
|
||||
|
@ -16,6 +16,7 @@
|
||||
|
||||
import copy
|
||||
import inspect
|
||||
import six
|
||||
|
||||
import eventlet
|
||||
from oslo_config import cfg
|
||||
@ -200,10 +201,12 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
|
||||
driver_name, 'create_wait', plugin=self, context=context,
|
||||
device_dict=device_dict, device_id=instance_id,
|
||||
auth_attr=auth_attr)
|
||||
except vnfm.DeviceCreateWaitFailed:
|
||||
except vnfm.DeviceCreateWaitFailed as e:
|
||||
LOG.error(_LE("VNF Create failed for vnf_id %s"), device_id)
|
||||
create_failed = True
|
||||
device_dict['status'] = constants.ERROR
|
||||
self.set_device_error_status_reason(context, device_id,
|
||||
six.text_type(e))
|
||||
|
||||
if instance_id is None or create_failed:
|
||||
mgmt_url = None
|
||||
@ -231,6 +234,8 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
|
||||
except Exception:
|
||||
LOG.exception(_('create_device_wait'))
|
||||
new_status = constants.ERROR
|
||||
self.set_device_error_status_reason(context, device_id,
|
||||
'Unable to configure VDU')
|
||||
device_dict['status'] = new_status
|
||||
self._create_device_status(context, device_id, new_status)
|
||||
|
||||
@ -302,9 +307,11 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
|
||||
context=context, device_id=instance_id, auth_attr=vim_auth,
|
||||
region_name=region_name)
|
||||
self.mgmt_call(context, device_dict, kwargs)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
LOG.exception(_('_update_device_wait'))
|
||||
new_status = constants.ERROR
|
||||
self.set_device_error_status_reason(context, device_dict['id'],
|
||||
six.text_type(e))
|
||||
device_dict['status'] = new_status
|
||||
self.mgmt_update_post(context, device_dict)
|
||||
|
||||
@ -323,9 +330,12 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
|
||||
driver_name, 'update', plugin=self, context=context,
|
||||
device_id=instance_id, device_dict=device_dict,
|
||||
device=device, auth_attr=vim_auth)
|
||||
except Exception:
|
||||
except Exception as e:
|
||||
with excutils.save_and_reraise_exception():
|
||||
device_dict['status'] = constants.ERROR
|
||||
self.set_device_error_status_reason(context,
|
||||
device_dict['id'],
|
||||
six.text_type(e))
|
||||
self.mgmt_update_post(context, device_dict)
|
||||
self._update_device_post(context, device_id, constants.ERROR)
|
||||
|
||||
@ -346,6 +356,7 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
|
||||
except Exception as e_:
|
||||
e = e_
|
||||
device_dict['status'] = constants.ERROR
|
||||
device_dict['error_reason'] = six.text_type(e)
|
||||
LOG.exception(_('_delete_device_wait'))
|
||||
self.mgmt_delete_post(context, device_dict)
|
||||
device_id = device_dict['id']
|
||||
@ -377,6 +388,7 @@ class VNFMPlugin(vm_db.VNFMPluginDb, VNFMMgmtMixin):
|
||||
# Other case mark error
|
||||
with excutils.save_and_reraise_exception():
|
||||
device_dict['status'] = constants.ERROR
|
||||
device_dict['error_reason'] = six.text_type(e)
|
||||
self.mgmt_delete_post(context, device_dict)
|
||||
self._delete_device_post(context, device_id, e)
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user