Add rollback option to create and update stacks
This patch adds a rollback option to create and update stacks. If "CONF.v2_vnfm.enable_rollback_stack" is True, when a resource creation fails in the create and update stack, rollback stack is executed and the create resource is deleted. This feature is implemented to successful AZ reselection at the VDU using volume. Closes-Bug: #2034886 Change-Id: Icdc70f299c65a137672935338dd6d795a3dbea73
This commit is contained in:
parent
4f857d3276
commit
83a109f765
@ -653,8 +653,7 @@
|
||||
test_grant_zone_list: az-1
|
||||
v2_vnfm:
|
||||
placement_fallback_best_effort: true
|
||||
server_notification:
|
||||
server_notification: true
|
||||
enable_rollback_stack: true
|
||||
devstack_services:
|
||||
n-cpu: true
|
||||
placement-client: true
|
||||
|
@ -93,6 +93,10 @@ VNFM_OPTS = [
|
||||
help=_('Error message for Availability Zone reselection. '
|
||||
'These configs are regular expressions to detect '
|
||||
'error messages from OpenStack Heat.')),
|
||||
cfg.BoolOpt('enable_rollback_stack',
|
||||
default=False,
|
||||
help=_('If True, enable rollback stack on resource create '
|
||||
'failure.')),
|
||||
# NOTE: This is for test use since it is convenient to be able to delete
|
||||
# under development.
|
||||
cfg.BoolOpt('test_enable_lcm_op_occ_delete',
|
||||
|
@ -60,6 +60,8 @@ class HeatClient(object):
|
||||
base_url=base_url)
|
||||
|
||||
def create_stack(self, fields, wait=True):
|
||||
if CONF.v2_vnfm.enable_rollback_stack:
|
||||
fields['disable_rollback'] = False
|
||||
path = "stacks"
|
||||
resp, body = self.client.do_request(path, "POST",
|
||||
expected_status=[201], body=fields)
|
||||
@ -71,6 +73,8 @@ class HeatClient(object):
|
||||
return body['stack']['id']
|
||||
|
||||
def update_stack(self, stack_name, fields, wait=True):
|
||||
if CONF.v2_vnfm.enable_rollback_stack:
|
||||
fields['disable_rollback'] = False
|
||||
path = f"stacks/{stack_name}"
|
||||
# It was assumed that PATCH is used and therefore 'fields'
|
||||
# contains only update parts and 'existing' is not used.
|
||||
@ -132,6 +136,9 @@ class HeatClient(object):
|
||||
LOG.info("%s %s done.", operation, stack_name.split('/')[0])
|
||||
raise loopingcall.LoopingCallDone()
|
||||
elif status in failed_status:
|
||||
if (status == "ROLLBACK_COMPLETE"
|
||||
or status == "ROLLBACK_FAILED"):
|
||||
status_reason = self.get_original_failed_reason(stack_name)
|
||||
LOG.error("%s %s failed.", operation, stack_name.split('/')[0])
|
||||
sol_title = "%s failed" % operation
|
||||
raise sol_ex.StackOperationFailed(sol_title=sol_title,
|
||||
@ -149,12 +156,28 @@ class HeatClient(object):
|
||||
timer.start(interval=CHECK_INTERVAL).wait()
|
||||
|
||||
def wait_stack_create(self, stack_name):
|
||||
self._wait_completion(stack_name, "Stack create",
|
||||
["CREATE_COMPLETE"], ["CREATE_IN_PROGRESS"], ["CREATE_FAILED"])
|
||||
if CONF.v2_vnfm.enable_rollback_stack:
|
||||
self._wait_completion(stack_name, "Stack create",
|
||||
["CREATE_COMPLETE"],
|
||||
["CREATE_IN_PROGRESS", "CREATE_FAILED",
|
||||
"ROLLBACK_IN_PROGRESS"],
|
||||
["ROLLBACK_COMPLETE", "ROLLBACK_FAILED"])
|
||||
else:
|
||||
self._wait_completion(stack_name, "Stack create",
|
||||
["CREATE_COMPLETE"], ["CREATE_IN_PROGRESS"],
|
||||
["CREATE_FAILED"])
|
||||
|
||||
def wait_stack_update(self, stack_name):
|
||||
self._wait_completion(stack_name, "Stack update",
|
||||
["UPDATE_COMPLETE"], ["UPDATE_IN_PROGRESS"], ["UPDATE_FAILED"])
|
||||
if CONF.v2_vnfm.enable_rollback_stack:
|
||||
self._wait_completion(stack_name, "Stack update",
|
||||
["UPDATE_COMPLETE"],
|
||||
["UPDATE_IN_PROGRESS", "UPDATE_FAILED",
|
||||
"ROLLBACK_IN_PROGRESS"],
|
||||
["ROLLBACK_COMPLETE", "ROLLBACK_FAILED"])
|
||||
else:
|
||||
self._wait_completion(stack_name, "Stack update",
|
||||
["UPDATE_COMPLETE"], ["UPDATE_IN_PROGRESS"],
|
||||
["UPDATE_FAILED"])
|
||||
|
||||
def wait_stack_delete(self, stack_name):
|
||||
# NOTE: wait until stack is deleted in the DB since it is necessary
|
||||
@ -203,6 +226,21 @@ class HeatClient(object):
|
||||
|
||||
return body
|
||||
|
||||
def get_original_failed_reason(self, stack_name):
|
||||
# This method gets the reason for stack failure from the stack event
|
||||
# if the rollback option is enabled.
|
||||
resource_name = stack_name.split('/')[0]
|
||||
path = (f"stacks/{stack_name}/resources/{resource_name}/"
|
||||
"events?resource_action=CREATE&resource_action=UPDATE"
|
||||
"&resource_status=FAILED&sort_dir=desc&limit=1")
|
||||
resp, body = self.client.do_request(path, "GET",
|
||||
expected_status=[200, 404])
|
||||
|
||||
if resp.status_code == 404:
|
||||
return None
|
||||
|
||||
return body["events"][0]["resource_status_reason"]
|
||||
|
||||
|
||||
def get_reses_by_types(heat_reses, types):
|
||||
return [res for res in heat_reses if res['resource_type'] in types]
|
||||
|
@ -4,7 +4,7 @@ description: 'VDU1 HOT for Sample VNF'
|
||||
parameters:
|
||||
flavor:
|
||||
type: string
|
||||
image-VDU1:
|
||||
image-VDU1-VirtualStorage:
|
||||
type: string
|
||||
zone:
|
||||
type: string
|
||||
@ -21,7 +21,7 @@ resources:
|
||||
properties:
|
||||
flavor: { get_param: flavor }
|
||||
name: VDU1
|
||||
image: { get_param: image-VDU1 }
|
||||
block_device_mapping_v2: [{"volume_id": { get_resource: VDU1-VirtualStorage }}]
|
||||
networks:
|
||||
- port:
|
||||
get_resource: VDU1_CP1
|
||||
@ -33,6 +33,19 @@ resources:
|
||||
get_resource: VDU1_CP3
|
||||
availability_zone: { get_param: zone }
|
||||
|
||||
VDU1-VirtualStorage:
|
||||
type: OS::Cinder::Volume
|
||||
properties:
|
||||
image: { get_param: image-VDU1-VirtualStorage }
|
||||
size: 1
|
||||
volume_type: { get_resource: multi }
|
||||
multi:
|
||||
type: OS::Cinder::VolumeType
|
||||
properties:
|
||||
# making unique name to avoid conflicting with other packages
|
||||
name: { list_join: ['-', [get_param: OS::stack_name, 'VDU1-multi']] }
|
||||
metadata: { multiattach: "<is> True" }
|
||||
|
||||
# extVL without FixedIP or with numDynamicAddresses
|
||||
VDU1_CP1:
|
||||
type: OS::Neutron::Port
|
||||
|
@ -10,7 +10,7 @@ resources:
|
||||
type: VDU1.yaml
|
||||
properties:
|
||||
flavor: { get_param: [ nfv, VDU, VDU1, computeFlavourId ] }
|
||||
image-VDU1: { get_param: [ nfv, VDU, VDU1, vcImageId ] }
|
||||
image-VDU1-VirtualStorage: { get_param: [ nfv, VDU, VDU1-VirtualStorage, vcImageId ] }
|
||||
zone: { get_param: [ nfv, VDU, VDU1, locationConstraints] }
|
||||
net1: { get_param: [ nfv, CP, VDU1_CP1, network ] }
|
||||
net2: { get_resource: internalVL1 }
|
||||
|
@ -84,17 +84,6 @@ topology_template:
|
||||
# in other zones in the test_update_stack_retry.
|
||||
# If there is a change in the Zuul environment in the future,
|
||||
# it must be reviewed along with the flavor.
|
||||
sw_image_data:
|
||||
name: cirros-0.5.2-x86_64-disk
|
||||
version: '0.5.2'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
min_ram: 256 MB
|
||||
size: 12 GB
|
||||
capabilities:
|
||||
virtual_compute:
|
||||
properties:
|
||||
@ -110,6 +99,30 @@ topology_template:
|
||||
num_virtual_cpu: 2
|
||||
virtual_local_storage:
|
||||
- size_of_storage: 4 GB
|
||||
requirements:
|
||||
- virtual_storage: VDU1-VirtualStorage
|
||||
|
||||
VDU1-VirtualStorage:
|
||||
type: tosca.nodes.nfv.Vdu.VirtualBlockStorage
|
||||
properties:
|
||||
virtual_block_storage_data:
|
||||
size_of_storage: 1 GB
|
||||
rdma_enabled: true
|
||||
sw_image_data:
|
||||
name: VDU1-VirtualStorage-image
|
||||
version: '0.5.2'
|
||||
checksum:
|
||||
algorithm: sha-256
|
||||
hash: 932fcae93574e242dc3d772d5235061747dfe537668443a1f0567d893614b464
|
||||
container_format: bare
|
||||
disk_format: qcow2
|
||||
min_disk: 0 GB
|
||||
min_ram: 256 MB
|
||||
size: 12 GB
|
||||
artifacts:
|
||||
sw_image:
|
||||
type: tosca.artifacts.nfv.SwImage
|
||||
file: ../Files/images/cirros-0.5.2-x86_64-disk.img
|
||||
|
||||
VDU1_CP1:
|
||||
type: tosca.nodes.nfv.VduCp
|
||||
@ -188,7 +201,7 @@ topology_template:
|
||||
VDU1_scale:
|
||||
name: VDU1_scale
|
||||
description: VDU1 scaling aspect
|
||||
max_scale_level: 2
|
||||
max_scale_level: 4
|
||||
step_deltas:
|
||||
- delta_1
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user