Don't replace failed neutron resources always
Override needs_replace_failed() for all neutron resource. Change-Id: I1789540fe2caae18fb446cd069b827036dd86f1c Blueprint: custom-update-replace-for-failed-resources
This commit is contained in:
parent
3c53b24567
commit
52de872899
|
@ -100,6 +100,18 @@ class NeutronResource(resource.Resource):
|
|||
attributes = self._show_resource()
|
||||
return attributes[name]
|
||||
|
||||
def needs_replace_failed(self):
|
||||
if not self.resource_id:
|
||||
return True
|
||||
|
||||
with self.client_plugin().ignore_not_found:
|
||||
res_attrs = self._show_resource()
|
||||
if 'status' in res_attrs:
|
||||
return res_attrs['status'] == 'ERROR'
|
||||
return False
|
||||
|
||||
return True
|
||||
|
||||
def get_reference_id(self):
|
||||
return self.resource_id
|
||||
|
||||
|
|
|
@ -109,3 +109,49 @@ class NeutronTest(common.HeatTestCase):
|
|||
# and return None due to resource_id is None
|
||||
res.attributes.reset_resolved_values()
|
||||
self.assertIsNone(res.FnGetAtt('show'))
|
||||
|
||||
def test_needs_replace_failed(self):
|
||||
class SomeNeutronResource(nr.NeutronResource):
|
||||
properties_schema = {}
|
||||
|
||||
@classmethod
|
||||
def is_service_available(cls, context):
|
||||
return (True, None)
|
||||
|
||||
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
|
||||
stack = mock.MagicMock()
|
||||
stack.has_cache_data = mock.Mock(return_value=False)
|
||||
res = SomeNeutronResource('aresource', tmpl, stack)
|
||||
res.state_set(res.CREATE, res.FAILED)
|
||||
mock_show_resource = mock.MagicMock()
|
||||
mock_show_resource.side_effect = [
|
||||
{'attr1': 'val1', 'status': 'ACTIVE'},
|
||||
{'attr1': 'val1', 'status': 'ERROR'},
|
||||
{'attr1': 'val1', 'attr2': 'val2'},
|
||||
qe.NotFound]
|
||||
res._show_resource = mock_show_resource
|
||||
nclientplugin = neutron.NeutronClientPlugin(mock.MagicMock())
|
||||
res.client_plugin = mock.Mock(return_value=nclientplugin)
|
||||
|
||||
# needs replace because res not created yet
|
||||
res.resource_id = None
|
||||
self.assertTrue(res.needs_replace_failed())
|
||||
self.assertEqual(0, mock_show_resource.call_count)
|
||||
|
||||
# no need to replace because res is ACTIVE underlying
|
||||
res.resource_id = 'I am a resource'
|
||||
self.assertFalse(res.needs_replace_failed())
|
||||
self.assertEqual(1, mock_show_resource.call_count)
|
||||
|
||||
# needs replace because res is ERROR underlying
|
||||
self.assertTrue(res.needs_replace_failed())
|
||||
self.assertEqual(2, mock_show_resource.call_count)
|
||||
|
||||
# no need to replace because res exists and no status
|
||||
# to check
|
||||
self.assertFalse(res.needs_replace_failed())
|
||||
self.assertEqual(3, mock_show_resource.call_count)
|
||||
|
||||
# needs replace because res can not be found
|
||||
self.assertTrue(res.needs_replace_failed())
|
||||
self.assertEqual(4, mock_show_resource.call_count)
|
||||
|
|
|
@ -352,6 +352,27 @@ class NeutronPortTest(common.HeatTestCase):
|
|||
self.assertEqual((port.CREATE, port.COMPLETE), port.state)
|
||||
self.create_mock.assert_called_once_with({'port': port_prop})
|
||||
|
||||
def test_update_failed_port_no_replace(self):
|
||||
t = template_format.parse(neutron_port_template)
|
||||
stack = utils.parse_stack(t)
|
||||
port = stack['port']
|
||||
port.resource_id = 'r_id'
|
||||
port.state_set(port.CREATE, port.FAILED)
|
||||
new_props = port.properties.data.copy()
|
||||
new_props['name'] = 'new_one'
|
||||
self.find_mock.return_value = 'net_or_sub'
|
||||
self.port_show_mock.return_value = {'port': {
|
||||
"status": "ACTIVE",
|
||||
"id": "fc68ea2c-b60b-4b4f-bd82-94ec81110766",
|
||||
"fixed_ips": {
|
||||
"subnet_id": "d0e971a6-a6b4-4f4c-8c88-b75e9c120b7e",
|
||||
"ip_address": "10.0.3.21"}}}
|
||||
update_snippet = rsrc_defn.ResourceDefinition(port.name, port.type(),
|
||||
new_props)
|
||||
scheduler.TaskRunner(port.update, update_snippet)()
|
||||
self.assertEqual((port.UPDATE, port.COMPLETE), port.state)
|
||||
self.assertEqual(1, self.update_mock.call_count)
|
||||
|
||||
def test_port_needs_update(self):
|
||||
t = template_format.parse(neutron_port_template)
|
||||
t['resources']['port']['properties'].pop('fixed_ips')
|
||||
|
|
Loading…
Reference in New Issue