Add replication slave info to instance show
Update the 'show' response for an instance: - If the instance is a replication slave, include the slave_of id. - If the instance is a replication master, include the list of slave instance ids. Update the 'list' response to include the slave_of id. Add CheckInstance tests for slave/slave_of info. (Unrelated: remove a #TODO comment that has already been addressed.) Partially Implements: blueprint replication-v1 Closes-Bug: #1340359 Change-Id: If8a154083d0095606fb3ee115cc9b66ab788cbb4
This commit is contained in:
parent
315c20cc8c
commit
87b621b2d9
|
@ -162,6 +162,8 @@ class SimpleInstance(object):
|
|||
self.ds = (datastore_models.Datastore.
|
||||
load(self.ds_version.datastore_id))
|
||||
|
||||
self.slave_list = None
|
||||
|
||||
@property
|
||||
def addresses(self):
|
||||
#TODO(tim.simpson): This code attaches two parts of the Nova server to
|
||||
|
@ -239,6 +241,10 @@ class SimpleInstance(object):
|
|||
def server_id(self):
|
||||
return self.db_info.compute_instance_id
|
||||
|
||||
@property
|
||||
def slave_of_id(self):
|
||||
return self.db_info.slave_of_id
|
||||
|
||||
@property
|
||||
def datastore_status(self):
|
||||
"""
|
||||
|
@ -352,6 +358,14 @@ class SimpleInstance(object):
|
|||
return Configuration.load(self.context,
|
||||
self.db_info.configuration_id)
|
||||
|
||||
@property
|
||||
def slaves(self):
|
||||
if self.slave_list is None:
|
||||
self.slave_list = DBInstance.find_all(tenant_id=self.tenant_id,
|
||||
slave_of_id=self.id,
|
||||
deleted=False).all()
|
||||
return self.slave_list
|
||||
|
||||
|
||||
class DetailInstance(SimpleInstance):
|
||||
"""A detailed view of an Instance.
|
||||
|
@ -1006,8 +1020,6 @@ class Instances(object):
|
|||
class DBInstance(dbmodels.DatabaseModelBase):
|
||||
"""Defines the task being executed plus the start time."""
|
||||
|
||||
#TODO(tim.simpson): Add start time.
|
||||
|
||||
_data_fields = ['name', 'created', 'compute_instance_id',
|
||||
'task_id', 'task_description', 'task_start_time',
|
||||
'volume_id', 'deleted', 'tenant_id',
|
||||
|
|
|
@ -49,6 +49,9 @@ class InstanceView(object):
|
|||
if ip:
|
||||
instance_dict['ip'] = ip
|
||||
|
||||
if self.instance.slave_of_id is not None:
|
||||
instance_dict['slave_of'] = self._build_master_info()
|
||||
|
||||
LOG.debug(instance_dict)
|
||||
return {"instance": instance_dict}
|
||||
|
||||
|
@ -65,6 +68,13 @@ class InstanceView(object):
|
|||
return create_links("flavors", self.req,
|
||||
self.instance.flavor_id)
|
||||
|
||||
def _build_master_info(self):
|
||||
return {
|
||||
"id": self.instance.slave_of_id,
|
||||
"links": create_links("instances", self.req,
|
||||
self.instance.slave_of_id)
|
||||
}
|
||||
|
||||
|
||||
class InstanceDetailView(InstanceView):
|
||||
"""Works with a full-blown instance."""
|
||||
|
@ -81,6 +91,9 @@ class InstanceDetailView(InstanceView):
|
|||
result['instance']['datastore']['version'] = (self.instance.
|
||||
datastore_version.name)
|
||||
|
||||
if self.instance.slaves:
|
||||
result['instance']['slaves'] = self._build_slaves_info()
|
||||
|
||||
if self.instance.configuration is not None:
|
||||
result['instance']['configuration'] = (self.
|
||||
_build_configuration_info())
|
||||
|
@ -99,6 +112,15 @@ class InstanceDetailView(InstanceView):
|
|||
|
||||
return result
|
||||
|
||||
def _build_slaves_info(self):
|
||||
data = []
|
||||
for slave in self.instance.slaves:
|
||||
data.append({
|
||||
"id": slave.id,
|
||||
"links": create_links("instances", self.req, slave.id)
|
||||
})
|
||||
return data
|
||||
|
||||
def _build_configuration_info(self):
|
||||
return {
|
||||
"id": self.instance.configuration.id,
|
||||
|
|
|
@ -1459,6 +1459,24 @@ class CheckInstance(AttrCheck):
|
|||
self.attrs_exist(self.instance['volume'], expected_attrs,
|
||||
msg="Volume")
|
||||
|
||||
def slave_of(self):
|
||||
if 'slave_of' not in self.instance:
|
||||
self.fail("'slave_of' not found in instance.")
|
||||
else:
|
||||
expected_attrs = ['id', 'links']
|
||||
self.attrs_exist(self.instance['slave_of'], expected_attrs,
|
||||
msg="Slave Of")
|
||||
self.links(self.instance['slave_of']['links'])
|
||||
|
||||
def slaves(self):
|
||||
if 'slaves' not in self.instance:
|
||||
self.fail("'slaves' not found in instance.")
|
||||
else:
|
||||
expected_attrs = ['id', 'links']
|
||||
for slave in self.instance['slaves']:
|
||||
self.attrs_exist(slave, expected_attrs, msg="Slave")
|
||||
self.links(slave['links'])
|
||||
|
||||
|
||||
@test(groups=[GROUP])
|
||||
class BadInstanceStatusBug():
|
||||
|
|
|
@ -18,6 +18,7 @@ from proboscis.asserts import assert_raises
|
|||
from proboscis.decorators import time_out
|
||||
from trove.common.utils import generate_uuid
|
||||
from trove.common.utils import poll_until
|
||||
from trove.tests.api.instances import CheckInstance
|
||||
from trove.tests.api.instances import instance_info
|
||||
from trove.tests.api.instances import TIMEOUT_INSTANCE_CREATE
|
||||
from trove.tests.api.instances import TIMEOUT_INSTANCE_DELETE
|
||||
|
@ -111,6 +112,31 @@ class VerifySlave(object):
|
|||
poll_until(db_is_found)
|
||||
|
||||
|
||||
@test(groups=[GROUP],
|
||||
depends_on=[WaitForCreateSlaveToFinish],
|
||||
runs_after=[VerifySlave])
|
||||
class TestInstanceListing(object):
|
||||
"""Test replication information in instance listing."""
|
||||
|
||||
@test
|
||||
def test_get_slave_instance(self):
|
||||
instance = instance_info.dbaas.instances.get(slave_instance.id)
|
||||
assert_equal(200, instance_info.dbaas.last_http_code)
|
||||
instance_dict = instance._info
|
||||
print("instance_dict=%s" % instance_dict)
|
||||
CheckInstance(instance_dict).slave_of()
|
||||
assert_equal(instance_info.id, instance_dict['slave_of']['id'])
|
||||
|
||||
@test
|
||||
def test_get_master_instance(self):
|
||||
instance = instance_info.dbaas.instances.get(instance_info.id)
|
||||
assert_equal(200, instance_info.dbaas.last_http_code)
|
||||
instance_dict = instance._info
|
||||
print("instance_dict=%s" % instance_dict)
|
||||
CheckInstance(instance_dict).slaves()
|
||||
assert_equal(slave_instance.id, instance_dict['slaves'][0]['id'])
|
||||
|
||||
|
||||
@test(groups=[GROUP],
|
||||
depends_on=[WaitForCreateSlaveToFinish],
|
||||
runs_after=[VerifySlave])
|
||||
|
|
|
@ -60,6 +60,8 @@ class InstanceDetailViewTest(TestCase):
|
|||
self.instance.volume_used = '3'
|
||||
self.instance.root_password = 'iloveyou'
|
||||
self.instance.get_visible_ip_addresses = lambda: ["1.2.3.4"]
|
||||
self.instance.slave_of_id = None
|
||||
self.instance.slaves = []
|
||||
|
||||
def tearDown(self):
|
||||
super(InstanceDetailViewTest, self).tearDown()
|
||||
|
|
Loading…
Reference in New Issue