Allow mark-unhealthy by physical resource ID
If the name passed into mark-unhealthy is not a valid resource name, check if it is a valid resource id and retrieve the resource via id instead of name. Change-Id: Ie28ed102665b2c6379d1f55b7a02b76d05e38ddd Co-Authored-By: Zane Bitter <zbitter@redhat.com> Closes-Bug: #1635295
This commit is contained in:
parent
f310a1f6bc
commit
4e465402d0
@ -54,6 +54,13 @@ resource_name_url:
|
||||
in: path
|
||||
required: false
|
||||
type: string
|
||||
resource_name_or_physical_id_url:
|
||||
description: |
|
||||
The name of a resource in the stack, or the ID of its underlying physical
|
||||
resource.
|
||||
in: path
|
||||
required: true
|
||||
type: string
|
||||
snapshot_id_url:
|
||||
description: |
|
||||
The UUID of the snapshot.
|
||||
|
@ -263,7 +263,7 @@ This operation does not return a response body.
|
||||
Mark a resource as unhealthy
|
||||
============================
|
||||
|
||||
.. rest_method:: PATCH /v1/{tenant_id}/stacks/{stack_name}/{stack_id}/resources/{resource_name}
|
||||
.. rest_method:: PATCH /v1/{tenant_id}/stacks/{stack_name}/{stack_id}/resources/{resource_name_or_physical_id}
|
||||
|
||||
Mark the specified resource in the stack as unhealthy.
|
||||
|
||||
@ -288,7 +288,7 @@ Request Parameters
|
||||
- tenant_id: tenant_id
|
||||
- stack_name: stack_name_url
|
||||
- stack_id: stack_id_url
|
||||
- resource_name: resource_name_url
|
||||
- resource_name_or_physical_id: resource_name_or_physical_id_url
|
||||
- mark_unhealthy: mark_unhealthy
|
||||
- resource_status_reason: resource_update_status_reason
|
||||
|
||||
|
@ -1866,6 +1866,8 @@ class EngineService(service.ServiceBase):
|
||||
is false and the resource is in CHECK_FAILED state.
|
||||
Otherwise, make no change.
|
||||
|
||||
:param resource_name: either the logical name of the resource or the
|
||||
physical resource ID.
|
||||
:param mark_unhealthy: indicates whether the resource is unhealthy.
|
||||
:param resource_status_reason: reason for health change.
|
||||
"""
|
||||
@ -1877,22 +1879,21 @@ class EngineService(service.ServiceBase):
|
||||
rsrc.stack.id,
|
||||
self.engine_id)
|
||||
|
||||
s = self._get_stack(cnxt, stack_identity)
|
||||
stack = parser.Stack.load(cnxt, stack=s)
|
||||
if resource_name not in stack:
|
||||
raise exception.ResourceNotFound(resource_name=resource_name,
|
||||
stack_name=stack.name)
|
||||
|
||||
if not isinstance(mark_unhealthy, bool):
|
||||
raise exception.Invalid(reason="mark_unhealthy is not a boolean")
|
||||
|
||||
rsrc = stack[resource_name]
|
||||
s = self._get_stack(cnxt, stack_identity)
|
||||
stack = parser.Stack.load(cnxt, stack=s)
|
||||
|
||||
rsrc = self._find_resource_in_stack(cnxt, resource_name, stack)
|
||||
|
||||
reason = (resource_status_reason or
|
||||
"state changed by resource_mark_unhealthy api")
|
||||
try:
|
||||
with lock(rsrc):
|
||||
if mark_unhealthy:
|
||||
rsrc.state_set(rsrc.CHECK, rsrc.FAILED, reason=reason)
|
||||
if rsrc.action != rsrc.DELETE:
|
||||
rsrc.state_set(rsrc.CHECK, rsrc.FAILED, reason=reason)
|
||||
elif rsrc.state == (rsrc.CHECK, rsrc.FAILED):
|
||||
rsrc.state_set(rsrc.CHECK, rsrc.COMPLETE, reason=reason)
|
||||
|
||||
@ -1900,6 +1901,29 @@ class EngineService(service.ServiceBase):
|
||||
raise exception.ActionInProgress(stack_name=stack.name,
|
||||
action=stack.action)
|
||||
|
||||
@staticmethod
|
||||
def _find_resource_in_stack(cnxt, resource_name, stack):
|
||||
"""Find a resource in a stack by either name or physical ID."""
|
||||
if resource_name in stack:
|
||||
return stack[resource_name]
|
||||
|
||||
rsrcs = resource_objects.Resource.get_all_by_physical_resource_id(
|
||||
cnxt,
|
||||
resource_name)
|
||||
|
||||
def in_stack(rs):
|
||||
return rs.stack_id == stack.id and stack[rs.name].id == rs.id
|
||||
|
||||
matches = [stack[rs.name] for rs in rsrcs if in_stack(rs)]
|
||||
|
||||
if not matches:
|
||||
raise exception.ResourceNotFound(resource_name=resource_name,
|
||||
stack_name=stack.name)
|
||||
if len(matches) > 1:
|
||||
raise exception.PhysicalResourceIDAmbiguity(phys_id=resource_name)
|
||||
|
||||
return matches[0]
|
||||
|
||||
@context.request_context
|
||||
def find_physical_resource(self, cnxt, physical_resource_id):
|
||||
"""Return an identifier for the specified resource.
|
||||
|
@ -536,6 +536,28 @@ class StackResourcesServiceTest(common.HeatTestCase):
|
||||
self.assertIsInstance(stack_dependencies, dependencies.Dependencies)
|
||||
self.assertEqual(2, len(stack_dependencies.graph()))
|
||||
|
||||
@tools.stack_context('service_find_resource_logical_name')
|
||||
def test_find_resource_logical_name(self):
|
||||
rsrc = self.stack['WebServer']
|
||||
physical_rsrc = self.eng._find_resource_in_stack(self.ctx,
|
||||
'WebServer',
|
||||
self.stack)
|
||||
self.assertEqual(rsrc.id, physical_rsrc.id)
|
||||
|
||||
@tools.stack_context('service_find_resource_physical_id')
|
||||
def test_find_resource_physical_id(self):
|
||||
rsrc = self.stack['WebServer']
|
||||
physical_rsrc = self.eng._find_resource_in_stack(self.ctx,
|
||||
rsrc.resource_id,
|
||||
self.stack)
|
||||
self.assertEqual(rsrc.id, physical_rsrc.id)
|
||||
|
||||
@tools.stack_context('service_find_resource_not_found')
|
||||
def test_find_resource_nonexist(self):
|
||||
self.assertRaises(exception.ResourceNotFound,
|
||||
self.eng._find_resource_in_stack,
|
||||
self.ctx, 'wibble', self.stack)
|
||||
|
||||
@tools.stack_context('service_mark_healthy_create_complete_test_stk')
|
||||
def test_mark_healthy_in_create_complete(self):
|
||||
self.eng.resource_mark_unhealthy(self.ctx, self.stack.identifier(),
|
||||
|
@ -0,0 +1,3 @@
|
||||
---
|
||||
features:
|
||||
- The ``resource mark unhealthy`` command now accepts either a logical resource name (as it did previously) or a physical resource ID to identify the resource to be marked unhealthy.
|
Loading…
x
Reference in New Issue
Block a user