Use conductor in the servicegroup db driver.

This patch updates the servicegroup db driver to use the conductor API
in the cases where it was accessing the db directly before.  If the
service is allowed to do direct db access, the conductor API will
optimize the call to go straight to the db.  Otherwise, it will invoke
rpc to a remove conductor service to perform the operations.

Part of bp no-db-compute.

Change-Id: I96adffc6f80288c829d84f170414613a35b5c840
This commit is contained in:
Russell Bryant
2013-01-14 18:33:14 -05:00
parent 102e761d8f
commit ab7e0ce6db
3 changed files with 26 additions and 6 deletions

View File

@@ -411,7 +411,7 @@ class Service(object):
self.db_allowed = db_allowed
self.conductor_api = conductor.API(use_local=db_allowed)
self.conductor_api.wait_until_ready(context.get_admin_context())
self.servicegroup_api = servicegroup.API()
self.servicegroup_api = servicegroup.API(db_allowed=db_allowed)
def start(self):
verstr = version.version_string_with_package()

View File

@@ -45,6 +45,15 @@ class API(object):
@lockutils.synchronized('nova.servicegroup.api.new', 'nova-')
def __new__(cls, *args, **kwargs):
'''Create an instance of the servicegroup API.
args and kwargs are passed down to the servicegroup driver when it gets
created. No args currently exist, though. Valid kwargs are:
db_allowed - Boolean. False if direct db access is not allowed and
alternative data access (conductor) should be used
instead.
'''
if not cls._driver:
LOG.debug(_('ServiceGroup driver defined as an instance of %s'),
@@ -55,7 +64,8 @@ class API(object):
except KeyError:
raise TypeError(_("unknown ServiceGroup driver name: %s")
% driver_name)
cls._driver = importutils.import_object(driver_class)
cls._driver = importutils.import_object(driver_class,
*args, **kwargs)
utils.check_isinstance(cls._driver, ServiceGroupDriver)
# we don't have to check that cls._driver is not NONE,
# check_isinstance does it

View File

@@ -14,8 +14,8 @@
# See the License for the specific language governing permissions and
# limitations under the License.
from nova import conductor
from nova import context
from nova import db
from nova import exception
from nova.openstack.common import cfg
from nova.openstack.common import log as logging
@@ -32,6 +32,10 @@ LOG = logging.getLogger(__name__)
class DbDriver(api.ServiceGroupDriver):
def __init__(self, *args, **kwargs):
self.db_allowed = kwargs.get('db_allowed', True)
self.conductor_api = conductor.API(use_local=self.db_allowed)
def join(self, member_id, group_id, service=None):
"""Join the given service with it's group."""
@@ -53,6 +57,11 @@ class DbDriver(api.ServiceGroupDriver):
Check whether a service is up based on last heartbeat.
"""
last_heartbeat = service_ref['updated_at'] or service_ref['created_at']
if isinstance(last_heartbeat, basestring):
# NOTE(russellb) If this service_ref came in over rpc via
# conductor, then the timestamp will be a string and needs to be
# converted back to a datetime.
last_heartbeat = timeutils.parse_strtime(last_heartbeat)
# Timestamps in DB are UTC.
elapsed = utils.total_seconds(timeutils.utcnow() - last_heartbeat)
LOG.debug('DB_Driver.is_up last_heartbeat = %(lhb)s elapsed = %(el)s',
@@ -66,7 +75,8 @@ class DbDriver(api.ServiceGroupDriver):
LOG.debug(_('DB_Driver: get_all members of the %s group') % group_id)
rs = []
ctxt = context.get_admin_context()
for service in db.service_get_all_by_topic(ctxt, group_id):
services = self.conductor_api.service_get_all_by_topic(ctxt, group_id)
for service in services:
if self.is_up(service):
rs.append(service['host'])
return rs
@@ -79,8 +89,8 @@ class DbDriver(api.ServiceGroupDriver):
report_count = service.service_ref['report_count'] + 1
state_catalog['report_count'] = report_count
service.service_ref = db.service_update(ctxt,
service.service_id, state_catalog)
service.service_ref = self.conductor_api.service_update(ctxt,
service.service_ref, state_catalog)
# TODO(termie): make this pattern be more elegant.
if getattr(service, 'model_disconnected', False):