OS::Trove::Instance observe reality implementation

Add override methods get_live_resource_data and
parse_live_resource_data. Also, add translation rule for
flavor.

implements bp get-reality-for-resources

Change-Id: I37f0a7af5d1fd3031f2d0f2141a52b7443df8ebb
This commit is contained in:
Peter Razumovsky 2016-11-03 18:28:22 +03:00
parent 4513777bfc
commit c6eccbd389
2 changed files with 77 additions and 12 deletions

View File

@ -23,6 +23,7 @@ from heat.engine import constraints
from heat.engine import properties
from heat.engine import resource
from heat.engine import support
from heat.engine import translation
LOG = logging.getLogger(__name__)
@ -292,6 +293,17 @@ class Instance(resource.Resource):
entity = 'instances'
def translation_rules(self, properties):
return [
translation.TranslationRule(
properties,
translation.TranslationRule.RESOLVE,
[self.FLAVOR],
client_plugin=self.client_plugin(),
finder='find_flavor_by_name_or_id'
)
]
def __init__(self, name, json_snippet, stack):
super(Instance, self).__init__(name, json_snippet, stack)
self._href = None
@ -314,8 +326,7 @@ class Instance(resource.Resource):
def handle_create(self):
"""Create cloud database instance."""
self.flavor = self.client_plugin().find_flavor_by_name_or_id(
self.properties[self.FLAVOR])
self.flavor = self.properties[self.FLAVOR]
self.volume = {'size': self.properties[self.SIZE]}
self.databases = self.properties[self.DATABASES]
self.users = self.properties[self.USERS]
@ -431,8 +442,7 @@ class Instance(resource.Resource):
if self.NAME in prop_diff:
updates.update({self.NAME: prop_diff[self.NAME]})
if self.FLAVOR in prop_diff:
flvid = prop_diff[self.FLAVOR]
flv = self.client_plugin().get_flavor_id(flvid)
flv = prop_diff[self.FLAVOR]
updates.update({self.FLAVOR: flv})
if self.SIZE in prop_diff:
updates.update({self.SIZE: prop_diff[self.SIZE]})
@ -588,6 +598,29 @@ class Instance(resource.Resource):
revokes)
return True
def parse_live_resource_data(self, resource_properties, resource_data):
"""A method to parse live resource data to update current resource.
NOTE: cannot update users from live resource data in case of
impossibility to get required user password.
"""
dbs = [d.name for d in self.client().databases.list(self.resource_id)]
dbs_reality = []
for resource_db in resource_properties[self.DATABASES]:
if resource_db[self.DATABASE_NAME] in dbs:
dbs_reality.append(resource_db)
dbs.remove(resource_db[self.DATABASE_NAME])
# cannot get any property for databases except for name, so update
# resource with name
dbs_reality.extend([{self.DATABASE_NAME: db} for db in dbs])
result = {self.NAME: resource_data.get('name'),
self.DATABASES: dbs_reality}
if resource_data.get('flavor') is not None:
result[self.FLAVOR] = resource_data['flavor'].get('id')
if resource_data.get('volume') is not None:
result[self.SIZE] = resource_data['volume']['size']
return result
def handle_delete(self):
"""Delete a cloud database instance."""
if not self.resource_id:

View File

@ -100,6 +100,9 @@ class FakeDBInstance(object):
def delete(self):
pass
def to_dict(self):
pass
class FakeFlavor(object):
def __init__(self, id, name):
@ -126,7 +129,7 @@ class InstanceTest(common.HeatTestCase):
return_value=True)
self.flavor_resolve = self.patchobject(trove.TroveClientPlugin,
'find_flavor_by_name_or_id',
return_value=1)
return_value='1')
self.fake_instance = FakeDBInstance()
self.client.instances.create.return_value = self.fake_instance
self.client.instances.get.return_value = self.fake_instance
@ -245,7 +248,7 @@ class InstanceTest(common.HeatTestCase):
"character_set": "utf8",
"name": "validdb"}]
self.client.instances.create.assert_called_once_with(
'test', 1, volume={'size': 30}, databases=databases, users=users,
'test', '1', volume={'size': 30}, databases=databases, users=users,
restorePoint={"backupRef": "1234"}, availability_zone=None,
datastore="SomeDStype", datastore_version="MariaDB-5.5", nics=[],
replica_of=None, replica_count=None)
@ -514,7 +517,7 @@ class InstanceTest(common.HeatTestCase):
scheduler.TaskRunner(instance.create)()
self.assertEqual((instance.CREATE, instance.COMPLETE), instance.state)
self.client.instances.create.assert_called_once_with(
'test', 1, volume={'size': 30}, databases=[], users=[],
'test', '1', volume={'size': 30}, databases=[], users=[],
restorePoint=None, availability_zone=None, datastore=None,
datastore_version=None, nics=[{'port-id': 'someportid',
'v4-fixed-ip': '1.2.3.4'}],
@ -533,7 +536,7 @@ class InstanceTest(common.HeatTestCase):
scheduler.TaskRunner(instance.create)()
self.assertEqual((instance.CREATE, instance.COMPLETE), instance.state)
self.client.instances.create.assert_called_once_with(
'test', 1, volume={'size': 30}, databases=[], users=[],
'test', '1', volume={'size': 30}, databases=[], users=[],
restorePoint=None, availability_zone=None, datastore=None,
datastore_version=None, nics=[{'net-id': net_id}], replica_of=None,
replica_count=None)
@ -555,7 +558,7 @@ class InstanceTest(common.HeatTestCase):
scheduler.TaskRunner(instance.create)()
self.assertEqual((instance.CREATE, instance.COMPLETE), instance.state)
self.client.instances.create.assert_called_once_with(
'test', 1, volume={'size': 30}, databases=[], users=[],
'test', '1', volume={'size': 30}, databases=[], users=[],
restorePoint=None, availability_zone=None, datastore=None,
datastore_version=None, nics=[{'net-id': 'somenetid'}],
replica_of=None, replica_count=None)
@ -567,11 +570,40 @@ class InstanceTest(common.HeatTestCase):
scheduler.TaskRunner(instance.create)()
self.assertEqual((instance.CREATE, instance.COMPLETE), instance.state)
self.client.instances.create.assert_called_once_with(
'test', 1, volume={'size': 30}, databases=[], users=[],
'test', '1', volume={'size': 30}, databases=[], users=[],
restorePoint=None, availability_zone=None, datastore=None,
datastore_version=None, nics=[],
replica_of="0e642916-dd64-43b3-933f-ff34fff69a7f", replica_count=2)
def test_instance_get_live_state(self):
self.fake_instance.to_dict = mock.Mock(return_value={
'name': 'test_instance',
'flavor': {'id': '1'},
'volume': {'size': 30}
})
fake_db1 = mock.Mock()
fake_db1.name = 'validdb'
fake_db2 = mock.Mock()
fake_db2.name = 'secondvaliddb'
self.client.databases.list.return_value = [fake_db1, fake_db2]
expected = {
'flavor': '1',
'name': 'test_instance',
'size': 30,
'databases': [{'name': 'validdb',
'character_set': 'utf8',
'collate': 'utf8_general_ci'},
{'name': 'secondvaliddb'}]
}
t = template_format.parse(db_template)
instance = self._setup_test_instance('get_live_state_test', t)
reality = instance.get_live_state(instance.properties)
self.assertEqual(expected, reality)
@mock.patch.object(resource.Resource, "client_plugin")
@mock.patch.object(resource.Resource, "client")
@ -678,10 +710,10 @@ class InstanceUpdateTests(common.HeatTestCase):
self.assertEqual(expected, trove.handle_update(None, None, prop_diff))
def test_handle_update_flavor(self, mock_client, mock_plugin):
# Translation mechanism already resolved flavor name to id.
prop_diff = {
"flavor": "changed"
"flavor": 1234
}
mock_plugin().get_flavor_id.return_value = 1234
trove = dbinstance.Instance('test', self._rdef, self._stack)
expected = {
"flavor": 1234