Fix the display of updated_at time when using memcache driver.

When using mc driver(set servicegroup_driver=mc), the service reports
state by memcache. but we use 'nova service-list' get the status of
services registered in nova, the 'update_at' time is not the last updated
time not as db driver. so we should get the time in memcache to update the
time in response.
Closes-Bug: #1647269

Change-Id: I1d4763436ad6de2483c39f5fe97fa6e8d283d8a3
This commit is contained in:
Tao Li 2016-12-23 10:35:01 +08:00
parent 1a643bf934
commit 0df91a7f79
8 changed files with 81 additions and 1 deletions

View File

@ -71,13 +71,15 @@ class ServiceController(wsgi.Controller):
active = 'enabled'
if svc['disabled']:
active = 'disabled'
updated_time = self.servicegroup_api.get_updated_time(svc)
service_detail = {'binary': svc['binary'],
'host': svc['host'],
'id': svc['id'],
'zone': svc['availability_zone'],
'status': active,
'state': state,
'updated_at': svc['updated_at'],
'updated_at': updated_time,
'disabled_reason': svc['disabled_reason']}
for field in additional_fields:

View File

@ -78,3 +78,7 @@ class API(object):
return False
return self._driver.is_up(member)
def get_updated_time(self, member):
"""Get the updated time from drivers except db"""
return self._driver.updated_time(member)

View File

@ -27,3 +27,7 @@ class Driver(object):
def is_up(self, member):
"""Check whether the given member is up."""
raise NotImplementedError()
def updated_time(self, service_ref):
"""Get the updated time"""
raise NotImplementedError()

View File

@ -79,6 +79,10 @@ class DbDriver(base.Driver):
'lhb': str(last_heartbeat), 'el': str(elapsed)})
return is_up
def updated_time(self, service_ref):
"""Get the updated time from db"""
return service_ref['updated_at']
def _report_state(self, service):
"""Update the state of this service in the datastore."""

View File

@ -17,6 +17,7 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import iso8601
from oslo_log import log as logging
from oslo_utils import timeutils
@ -67,6 +68,21 @@ class MemcachedDriver(base.Driver):
return is_up
def updated_time(self, service_ref):
"""Get the updated time from memcache"""
key = "%(topic)s:%(host)s" % service_ref
updated_time_in_mc = self.mc.get(str(key))
updated_time_in_db = service_ref['updated_at']
if updated_time_in_mc:
# Change mc time to offset-aware time
updated_time_in_mc = \
updated_time_in_mc.replace(tzinfo=iso8601.iso8601.Utc())
if updated_time_in_db <= updated_time_in_mc:
return updated_time_in_mc
return updated_time_in_db
def _report_state(self, service):
"""Update the state of this service in the datastore."""
try:

View File

@ -60,3 +60,14 @@ class ServiceGroupApiTestCase(test.NoDBTestCase):
result = self.servicegroup_api.service_is_up(member)
self.assertIs(result, False)
driver.is_up.assert_not_called()
def test_get_updated_time(self):
member = {"host": "fake-host",
"topic": "compute",
"forced_down": False}
retval = "2016-11-02T22:40:31.000000"
driver = self.servicegroup_api._driver
driver.updated_time = mock.MagicMock(return_value=retval)
result = self.servicegroup_api.get_updated_time(member)
self.assertEqual(retval, result)

View File

@ -106,3 +106,14 @@ class DBServiceGroupTestCase(test.NoDBTestCase):
def test_report_state_unexpected_error(self):
self._test_report_state_error(RuntimeError)
def test_get_updated_time(self):
retval = "2016-11-02T22:40:31.000000"
service_ref = {
'host': 'fake-host',
'topic': 'compute',
'updated_at': retval
}
result = self.servicegroup_api.get_updated_time(service_ref)
self.assertEqual(retval, result)

View File

@ -15,10 +15,12 @@
# License for the specific language governing permissions and limitations
# under the License.
import iso8601
import mock
from nova import servicegroup
from nova import test
from oslo_utils import timeutils
class MemcachedServiceGroupTestCase(test.NoDBTestCase):
@ -63,3 +65,29 @@ class MemcachedServiceGroupTestCase(test.NoDBTestCase):
fn(service)
self.mc_client.set.assert_called_once_with('compute:fake-host',
mock.ANY)
def test_get_updated_time(self):
updated_at_time = timeutils.parse_strtime("2016-04-18T02:56:25.198871")
service_ref = {
'host': 'fake-host',
'topic': 'compute',
'updated_at': updated_at_time.replace(tzinfo=iso8601.iso8601.Utc())
}
self.mc_client.get.return_value = None
self.assertEqual(service_ref['updated_at'],
self.servicegroup_api.get_updated_time(service_ref))
self.mc_client.get.assert_called_once_with('compute:fake-host')
self.mc_client.reset_mock()
retval = timeutils.utcnow()
self.mc_client.get.return_value = retval
self.assertEqual(retval.replace(tzinfo=iso8601.iso8601.Utc()),
self.servicegroup_api.get_updated_time(service_ref))
self.mc_client.get.assert_called_once_with('compute:fake-host')
self.mc_client.reset_mock()
service_ref['updated_at'] = \
retval.replace(tzinfo=iso8601.iso8601.Utc())
self.mc_client.get.return_value = updated_at_time
self.assertEqual(service_ref['updated_at'],
self.servicegroup_api.get_updated_time(service_ref))
self.mc_client.get.assert_called_once_with('compute:fake-host')