Merge "Just to migrate existing resource to backup stack" into stable/newton

This commit is contained in:
Jenkins 2017-08-14 16:57:01 +00:00 committed by Gerrit Code Review
commit a2962689ad
10 changed files with 104 additions and 143 deletions

View File

@ -1711,39 +1711,46 @@ class Resource(object):
except Exception as ex:
LOG.warning(_LW('db error %s'), ex)
def _store(self, metadata=None):
"""Create the resource in the database."""
def store(self, set_metadata=False):
"""Create the resource in the database.
If self.id is set, we update the existing stack.
"""
properties_data_encrypted, properties_data = (
resource_objects.Resource.encrypt_properties_data(
self._stored_properties_data))
if not self.root_stack_id:
self.root_stack_id = self.stack.root_stack_id()
try:
rs = {'action': self.action,
'status': self.status,
'status_reason': self.status_reason,
'stack_id': self.stack.id,
'physical_resource_id': self.resource_id,
'name': self.name,
'rsrc_metadata': metadata,
'properties_data': properties_data,
'properties_data_encrypted': properties_data_encrypted,
'needed_by': self.needed_by,
'requires': self.requires,
'replaces': self.replaces,
'replaced_by': self.replaced_by,
'current_template_id': self.current_template_id,
'stack_name': self.stack.name,
'root_stack_id': self.root_stack_id}
rs = {'action': self.action,
'status': self.status,
'status_reason': str(self.status_reason),
'stack_id': self.stack.id,
'physical_resource_id': self.resource_id,
'name': self.name,
'needed_by': self.needed_by,
'requires': self.requires,
'replaces': self.replaces,
'replaced_by': self.replaced_by,
'current_template_id': self.current_template_id,
'root_stack_id': self.root_stack_id,
'updated_at': self.updated_time,
'properties_data': properties_data,
'properties_data_encrypted': properties_data_encrypted}
if set_metadata:
metadata = self.t.metadata()
rs['rsrc_metadata'] = metadata
self._rsrc_metadata = metadata
if self.id is not None:
resource_objects.Resource.update_by_id(
self.context, self.id, rs)
else:
new_rs = resource_objects.Resource.create(self.context, rs)
self.id = new_rs.id
self.uuid = new_rs.uuid
self.created_time = new_rs.created_at
self._rsrc_metadata = metadata
except Exception as ex:
LOG.error(_LE('DB error %s'), ex)
def _add_event(self, action, status, reason):
"""Add a state change event to the database."""
@ -1755,50 +1762,6 @@ class Resource(object):
ev.store()
self.stack.dispatch_event(ev)
def _store_or_update(self, action, status, reason):
prev_action = self.action
self.action = action
self.status = status
self.status_reason = reason
properties_data_encrypted, properties_data = (
resource_objects.Resource.encrypt_properties_data(
self._stored_properties_data))
data = {
'action': self.action,
'status': self.status,
'status_reason': reason,
'stack_id': self.stack.id,
'updated_at': self.updated_time,
'properties_data': properties_data,
'properties_data_encrypted': properties_data_encrypted,
'needed_by': self.needed_by,
'requires': self.requires,
'replaces': self.replaces,
'replaced_by': self.replaced_by,
'current_template_id': self.current_template_id,
'physical_resource_id': self.resource_id,
'root_stack_id': self.root_stack_id
}
if prev_action == self.INIT:
metadata = self.t.metadata()
data['rsrc_metadata'] = metadata
else:
metadata = self._rsrc_metadata
if self.id is not None:
try:
resource_objects.Resource.update_by_id(self.context, self.id,
data)
except Exception as ex:
LOG.error(_LE('DB error %s'), ex)
else:
self._rsrc_metadata = metadata
else:
# This should only happen in unit tests
LOG.warning(_LW('Resource "%s" not pre-stored in DB'), self)
self._store(metadata)
@contextlib.contextmanager
def lock(self, engine_id):
self._acquire(engine_id)
@ -1992,7 +1955,11 @@ class Resource(object):
old_state = (self.action, self.status)
new_state = (action, status)
self._store_or_update(action, status, reason)
set_metadata = self.action == self.INIT
self.action = action
self.status = status
self.status_reason = reason
self.store(set_metadata)
if new_state != old_state:
self._add_event(action, status, reason)

View File

@ -452,7 +452,7 @@ class StackResource(resource.Resource):
timeout_mins=None):
"""Update the nested stack with the new template."""
if self.id is None:
self._store()
self.store()
if self.stack.action == self.stack.ROLLBACK:
if self._try_rollback():

View File

@ -700,8 +700,7 @@ class Stack(collections.Mapping):
self.t.add_resource(definition)
if self.t.id is not None:
self.t.store(self.context)
if resource.action == resource.INIT:
resource._store()
resource.store()
def remove_resource(self, resource_name):
"""Remove the resource with the specified name."""
@ -982,7 +981,7 @@ class Stack(collections.Mapping):
def _store_resources(self):
for r in reversed(self.dependencies):
if r.action == r.INIT:
r._store()
r.store()
@profiler.trace('Stack.create', hide_args=False)
@reset_state_on_error
@ -1353,7 +1352,7 @@ class Stack(collections.Mapping):
if existing_rsrc_db is None:
update_needed_by(rsrc)
rsrc.current_template_id = self.t.id
rsrc._store()
rsrc.store()
rsrcs[rsrc.name] = rsrc
else:
update_needed_by(existing_rsrc_db)

View File

@ -125,7 +125,7 @@ class UserTest(common.HeatTestCase):
rsrc = user.User(resource_name,
resource_defns[resource_name],
stack)
rsrc._store()
rsrc.store()
self.m.StubOutWithMock(short_id, 'get_id')
short_id.get_id(rsrc.uuid).MultipleTimes().AndReturn('aabbcc')

View File

@ -882,7 +882,7 @@ class TestConvergenceMigration(common.HeatTestCase):
template=tools.string_template_five)
self.stack.store()
for r in self.stack.resources.values():
r._store()
r.store()
self.stack.migrate_to_convergence()
self.stack = self.stack.load(self.ctx, self.stack.id)

View File

@ -92,7 +92,7 @@ class EventCommon(common.HeatTestCase):
self.stack.store()
self.resource = self.stack['EventTestResource']
self.resource._store()
self.resource.store()
self.addCleanup(stack_object.Stack.delete, self.ctx, self.stack.id)

View File

@ -295,7 +295,7 @@ Resources:
stack.store()
stack_res = stack['the_nested']
stack_res._store()
stack_res.store()
nested_t = template_format.parse(self.nested_template)
nested_t['Parameters']['KeyName']['Default'] = 'Key'
@ -383,7 +383,7 @@ Outputs:
self.res = stack_res.NestedStack('test_t_res',
self.defn, self.stack)
self.assertIsNone(self.res.validate())
self.res._store()
self.res.store()
def test_handle_create(self):
self.res.create_with_template = mock.Mock(return_value=None)

View File

@ -12,6 +12,7 @@
# under the License.
import collections
import datetime
import eventlet
import itertools
import json
@ -280,11 +281,25 @@ class ResourceTest(common.HeatTestCase):
def test_state_set(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
res = generic_rsrc.GenericResource('test_resource', tmpl, self.stack)
res.state_set(res.CREATE, res.COMPLETE, 'wibble')
res.state_set(res.CREATE, res.IN_PROGRESS, 'test_state_set')
self.assertIsNotNone(res.id)
self.assertEqual(res.CREATE, res.action)
self.assertEqual(res.IN_PROGRESS, res.status)
self.assertEqual('test_state_set', res.status_reason)
db_res = resource_objects.Resource.get_obj(res.context, res.id)
self.assertEqual(res.CREATE, db_res.action)
self.assertEqual(res.IN_PROGRESS, db_res.status)
self.assertEqual('test_state_set', db_res.status_reason)
res.state_set(res.CREATE, res.COMPLETE, 'test_update')
self.assertEqual(res.CREATE, res.action)
self.assertEqual(res.COMPLETE, res.status)
self.assertEqual((res.CREATE, res.COMPLETE), res.state)
self.assertEqual('wibble', res.status_reason)
self.assertEqual('test_update', res.status_reason)
db_res.refresh()
self.assertEqual(res.CREATE, db_res.action)
self.assertEqual(res.COMPLETE, db_res.status)
self.assertEqual('test_update', db_res.status_reason)
def test_physical_resource_name_or_FnGetRefId(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
@ -429,14 +444,14 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
res = generic_rsrc.GenericResource('test_res_new', tmpl, self.stack)
self.assertIsNone(res.created_time)
res._store()
res.store()
self.assertIsNotNone(res.created_time)
def test_updated_time(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource',
'GenericResourceType')
res = generic_rsrc.GenericResource('test_resource', tmpl, self.stack)
res._store()
res.store()
stored_time = res.updated_time
utmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
@ -542,43 +557,20 @@ class ResourceTest(common.HeatTestCase):
self.m.VerifyAll()
def test_updated_time_changes_only_on_update_calls(self):
def test_updated_time_changes_only_when_it_changed(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource',
'GenericResourceType')
res = generic_rsrc.GenericResource('test_resource', tmpl, self.stack)
res._store()
res.store()
self.assertIsNone(res.updated_time)
res._store_or_update(res.UPDATE, res.COMPLETE, 'should not change')
self.assertIsNone(res.updated_time)
def test_store_or_update(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
res = generic_rsrc.GenericResource('test_res_upd', tmpl, self.stack)
res._store_or_update(res.CREATE, res.IN_PROGRESS, 'test_store')
self.assertIsNotNone(res.id)
self.assertEqual(res.CREATE, res.action)
self.assertEqual(res.IN_PROGRESS, res.status)
self.assertEqual('test_store', res.status_reason)
db_res = resource_objects.Resource.get_obj(res.context, res.id)
self.assertEqual(res.CREATE, db_res.action)
self.assertEqual(res.IN_PROGRESS, db_res.status)
self.assertEqual('test_store', db_res.status_reason)
res._store_or_update(res.CREATE, res.COMPLETE, 'test_update')
self.assertEqual(res.CREATE, res.action)
self.assertEqual(res.COMPLETE, res.status)
self.assertEqual('test_update', res.status_reason)
db_res.refresh()
self.assertEqual(res.CREATE, db_res.action)
self.assertEqual(res.COMPLETE, db_res.status)
self.assertEqual('test_update', db_res.status_reason)
res.updated_time = datetime.datetime.utcnow()
res.store()
self.assertIsNotNone(res.updated_time)
def test_make_replacement(self):
tmpl = rsrc_defn.ResourceDefinition('test_resource', 'Foo')
res = generic_rsrc.GenericResource('test_res_upd', tmpl, self.stack)
res._store()
res.store()
new_tmpl_id = 2
self.assertIsNotNone(res.id)
new_id = res.make_replacement(new_tmpl_id)
@ -1797,15 +1789,15 @@ class ResourceTest(common.HeatTestCase):
# The db data should be encrypted when _store_or_update() is called
res = generic_rsrc.GenericResource('test_res_enc', tmpl, self.stack)
res._stored_properties_data = stored_properties_data
res._store_or_update(res.CREATE, res.IN_PROGRESS, 'test_store')
res.state_set(res.CREATE, res.IN_PROGRESS, 'test_store')
db_res = db_api.resource_get(res.context, res.id)
self.assertNotEqual('string',
db_res.properties_data['prop1'])
# The db data should be encrypted when _store() is called
# The db data should be encrypted when state_set is called
res = generic_rsrc.GenericResource('test_res_enc', tmpl, self.stack)
res._stored_properties_data = stored_properties_data
res._store()
res.state_set(res.CREATE, res.IN_PROGRESS, 'test_store')
db_res = db_api.resource_get(res.context, res.id)
self.assertNotEqual('string',
db_res.properties_data['prop1'])
@ -1839,18 +1831,18 @@ class ResourceTest(common.HeatTestCase):
'prop4': ['a', 'list'],
'prop5': True}
# The db data should not be encrypted when _store_or_update()
# The db data should not be encrypted when state_set()
# is called
res = generic_rsrc.GenericResource('test_res_enc', tmpl, self.stack)
res._stored_properties_data = stored_properties_data
res._store_or_update(res.CREATE, res.IN_PROGRESS, 'test_store')
res.state_set(res.CREATE, res.IN_PROGRESS, 'test_store')
db_res = db_api.resource_get(res.context, res.id)
self.assertEqual('string', db_res.properties_data['prop1'])
# The db data should not be encrypted when _store() is called
res = generic_rsrc.GenericResource('test_res_enc', tmpl, self.stack)
res._stored_properties_data = stored_properties_data
res._store()
res.store()
db_res = db_api.resource_get(res.context, res.id)
self.assertEqual('string', db_res.properties_data['prop1'])
@ -1876,7 +1868,7 @@ class ResourceTest(common.HeatTestCase):
def test_release_ignores_not_found_error(self, mock_sau, mock_get_obj):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res._store()
res.store()
res._acquire('engine-id')
mock_get_obj.side_effect = exception.NotFound()
res._release('engine-id')
@ -1886,7 +1878,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.action = res.CREATE
res._store()
res.store()
self._assert_resource_lock(res.id, None, None)
res_data = {(1, True): {u'id': 1, u'name': 'A', 'attrs': {}},
(2, True): {u'id': 3, u'name': 'B', 'attrs': {}}}
@ -1904,7 +1896,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.action = res.CREATE
res._store()
res.store()
res_data = {(1, True): {u'id': 1, u'name': 'A', 'attrs': {}},
(2, True): {u'id': 3, u'name': 'B', 'attrs': {}}}
@ -1920,7 +1912,7 @@ class ResourceTest(common.HeatTestCase):
"""
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res._store()
res.store()
dummy_ex = exception.ResourceNotAvailable(resource_name=res.name)
res.create = mock.Mock(side_effect=dummy_ex)
self._assert_resource_lock(res.id, None, None)
@ -1937,7 +1929,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.action = res.ADOPT
res._store()
res.store()
self.stack.adopt_stack_data = {'resources': {'test_res': {
'resource_id': 'fluffy'}}}
self._assert_resource_lock(res.id, None, None)
@ -1956,7 +1948,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.action = res.ADOPT
res._store()
res.store()
self.stack.adopt_stack_data = {'resources': {}}
self._assert_resource_lock(res.id, None, None)
res_data = {(1, True): {u'id': 5, u'name': 'A', 'attrs': {}},
@ -1979,7 +1971,7 @@ class ResourceTest(common.HeatTestCase):
res = stack.resources['test_res']
res.requires = [2]
res.action = res.CREATE
res._store()
res.store()
self._assert_resource_lock(res.id, None, None)
new_temp = template.Template({
@ -2015,7 +2007,7 @@ class ResourceTest(common.HeatTestCase):
tmpl)
stack.converge_stack(stack.t, action=stack.CREATE)
res = stack.resources['test_res']
res._store()
res.store()
new_temp = template.Template({
'HeatTemplateFormatVersion': '2012-12-12',
@ -2037,7 +2029,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res',
'GenericResourceType')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res._store()
res.store()
new_temp = template.Template({
'HeatTemplateFormatVersion': '2012-12-12',
@ -2058,7 +2050,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res',
'GenericResourceType')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res._store()
res.store()
new_temp = template.Template({
'HeatTemplateFormatVersion': '2012-12-12',
@ -2081,7 +2073,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.requires = [1, 2]
res._store()
res.store()
rs = resource_objects.Resource.get_obj(self.stack.context, res.id)
rs.update_and_save({'engine_id': 'not-this'})
self._assert_resource_lock(res.id, 'not-this', None)
@ -2110,7 +2102,7 @@ class ResourceTest(common.HeatTestCase):
stack.converge_stack(stack.t, action=stack.CREATE)
res = stack.resources['test_res']
res.requires = [2]
res._store()
res.store()
self._assert_resource_lock(res.id, None, None)
new_temp = template.Template({
@ -2153,7 +2145,7 @@ class ResourceTest(common.HeatTestCase):
stack.converge_stack(stack.t, action=stack.CREATE)
res = stack.resources['test_res']
res.requires = [2]
res._store()
res.store()
self._assert_resource_lock(res.id, None, None)
new_temp = template.Template({
@ -2187,7 +2179,7 @@ class ResourceTest(common.HeatTestCase):
'ResourceWithPropsType')
res = generic_rsrc.ResourceWithProps('test_res', rsrc_def, self.stack)
res.replaced_by = 'dummy'
res._store()
res.store()
new_temp = template.Template({
'HeatTemplateFormatVersion': '2012-12-12',
@ -2211,7 +2203,7 @@ class ResourceTest(common.HeatTestCase):
'ResourceWithPropsType')
res = generic_rsrc.ResourceWithProps('test_res', rsrc_def, self.stack)
res.replaced_by = 'dummy'
res._store()
res.store()
new_temp = template.Template({
'HeatTemplateFormatVersion': '2012-12-12',
@ -2237,7 +2229,7 @@ class ResourceTest(common.HeatTestCase):
res.current_template_id = 1
res.status = res.COMPLETE
res.action = res.CREATE
res._store()
res.store()
res.handle_delete = mock.Mock(return_value=None)
res._update_replacement_data = mock.Mock()
self._assert_resource_lock(res.id, None, None)
@ -2254,7 +2246,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.current_template_id = 'same-template'
res._store()
res.store()
res.delete = mock.Mock()
tr = scheduler.TaskRunner(res.delete_convergence, 'same-template', {},
'engine-007', self.dummy_timeout,
@ -2268,7 +2260,7 @@ class ResourceTest(common.HeatTestCase):
res.current_template_id = 1
res.status = res.COMPLETE
res.action = res.CREATE
res._store()
res.store()
res_id = res.id
res.handle_delete = mock.Mock(side_effect=ValueError('test'))
self._assert_resource_lock(res.id, None, None)
@ -2289,7 +2281,7 @@ class ResourceTest(common.HeatTestCase):
res.current_template_id = 1
res.status = res.COMPLETE
res.action = res.CREATE
res._store()
res.store()
rs = resource_objects.Resource.get_obj(self.stack.context, res.id)
rs.update_and_save({'engine_id': 'not-this'})
self._assert_resource_lock(res.id, 'not-this', None)
@ -2307,7 +2299,7 @@ class ResourceTest(common.HeatTestCase):
res.current_template_id = 1
res.status = res.COMPLETE
res.action = res.CREATE
res._store()
res.store()
res.destroy = mock.Mock()
input_data = {(1, False): 4, (2, False): 5} # needed_by resource ids
self._assert_resource_lock(res.id, None, None)
@ -2322,7 +2314,7 @@ class ResourceTest(common.HeatTestCase):
r = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
r.replaced_by = 4
r.needed_by = [4, 5]
r._store()
r.store()
db_res = mock.MagicMock()
db_res.current_template_id = 'same_tmpl'
mock_get_obj.return_value = db_res
@ -2451,7 +2443,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
# action is INIT by default
res._store()
res.store()
with mock.patch.object(resource_objects.Resource,
'delete') as resource_del:
tr = scheduler.TaskRunner(res.delete_convergence, 1, {},
@ -2463,7 +2455,7 @@ class ResourceTest(common.HeatTestCase):
tmpl = rsrc_defn.ResourceDefinition('test_res', 'Foo')
res = generic_rsrc.GenericResource('test_res', tmpl, self.stack)
res.action = res.CREATE
res._store()
res.store()
timeout = -1 # to emulate timeout
tr = scheduler.TaskRunner(res.delete_convergence, 1, {}, 'engine-007',
timeout, self.dummy_event)
@ -2489,7 +2481,7 @@ class ResourceTest(common.HeatTestCase):
mock_tmpl_load.return_value = tmpl
res = stack['res']
res.current_template_id = stack.t.id
res._store()
res.store()
data = {'bar': {'atrr1': 'baz', 'attr2': 'baz2'}}
mock_stack_load.return_value = stack
resource.Resource.load(stack.context, res.id, True, data)
@ -3402,6 +3394,7 @@ class ResourceHookTest(common.HeatTestCase):
res = resource.Resource('res', snippet, self.stack)
res.id = '1234'
res.uuid = uuid.uuid4()
res.store = mock.Mock()
task = scheduler.TaskRunner(res.create)
task.start()
task.step()
@ -3419,6 +3412,7 @@ class ResourceHookTest(common.HeatTestCase):
res.id = '1234'
res.action = 'CREATE'
res.uuid = uuid.uuid4()
res.store = mock.Mock()
self.stack.action = 'DELETE'
task = scheduler.TaskRunner(res.delete)
task.start()
@ -3436,6 +3430,7 @@ class ResourceHookTest(common.HeatTestCase):
res = resource.Resource('res', snippet, self.stack)
res.id = '1234'
res.uuid = uuid.uuid4()
res.store = mock.Mock()
task = scheduler.TaskRunner(res.create)
task.start()
task.step()
@ -3454,6 +3449,7 @@ class ResourceHookTest(common.HeatTestCase):
res.uuid = uuid.uuid4()
res.action = 'CREATE'
self.stack.action = 'DELETE'
res.store = mock.Mock()
task = scheduler.TaskRunner(res.delete)
task.start()
task.step()

View File

@ -539,7 +539,6 @@ class StackTest(common.HeatTestCase):
self.assertEqual((stack.Stack.UPDATE, stack.Stack.COMPLETE),
self.stack.state)
self.assertEqual('xyz', self.stack['AResource'].properties['Foo'])
self.assertEqual(
stack_arn, self.stack['AResource'].metadata_get()['Bar'])

View File

@ -58,7 +58,7 @@ class StackUserTest(common.HeatTestCase):
else:
self.stack.set_stack_user_project_id(project_id)
rsrc._store()
rsrc.store()
self.m.StubOutWithMock(short_id, 'get_id')
short_id.get_id(rsrc.uuid).MultipleTimes().AndReturn('aabbcc')