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:
		@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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()
 | 
			
		||||
 
 | 
			
		||||
@@ -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."""
 | 
			
		||||
 | 
			
		||||
 
 | 
			
		||||
@@ -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:
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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)
 | 
			
		||||
 
 | 
			
		||||
@@ -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')
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user