merged orm branch

This commit is contained in:
Vishvananda Ishaya
2010-09-02 14:21:41 -07:00
7 changed files with 115 additions and 95 deletions

View File

@@ -52,41 +52,46 @@ class NoMoreNetworks(exception.Error):
###################
def daemon_get(context, daemon_id):
"""Get an daemon or raise if it does not exist."""
return IMPL.daemon_get(context, daemon_id)
def service_destroy(context, instance_id):
"""Destroy the service or raise if it does not exist."""
return IMPL.service_destroy(context, instance_id)
def daemon_get_by_args(context, host, binary):
"""Get the state of an daemon by node name and binary."""
return IMPL.daemon_get_by_args(context, host, binary)
def service_get(context, service_id):
"""Get an service or raise if it does not exist."""
return IMPL.service_get(context, service_id)
def daemon_get_all_by_topic(context, topic):
"""Get all compute daemons for a given topi """
return IMPL.daemon_get_all_by_topic(context, topic)
def service_get_all_by_topic(context, topic):
"""Get all compute services for a given topic """
return IMPL.service_get_all_by_topic(context, topic)
def daemon_get_all_compute_sorted(context):
"""Get all compute daemons sorted by instance count
def service_get_all_compute_sorted(context):
"""Get all compute services sorted by instance count
Returns a list of (Daemon, instance_count) tuples
Returns a list of (Service, instance_count) tuples
"""
return IMPL.daemon_get_all_compute_sorted(context)
return IMPL.service_get_all_compute_sorted(context)
def daemon_create(context, values):
"""Create a daemon from the values dictionary."""
return IMPL.daemon_create(context, values)
def service_get_by_args(context, host, binary):
"""Get the state of an service by node name and binary."""
return IMPL.service_get_by_args(context, host, binary)
def daemon_update(context, daemon_id, values):
"""Set the given properties on an daemon and update it.
def service_create(context, values):
"""Create a service from the values dictionary."""
return IMPL.service_create(context, values)
Raises NotFound if daemon does not exist.
def service_update(context, service_id, values):
"""Set the given properties on an service and update it.
Raises NotFound if service does not exist.
"""
return IMPL.daemon_update(context, daemon_id, values)
return IMPL.service_update(context, service_id, values)
###################

View File

@@ -36,27 +36,27 @@ FLAGS = flags.FLAGS
###################
def daemon_get(_context, daemon_id):
return models.Daemon.find(daemon_id)
def service_destroy(context, service_id):
service_ref = service_get(context, service_id)
service_ref.delete()
def service_get(_context, service_id):
return models.Service.find(service_id)
def daemon_get_by_args(_context, host, binary):
return models.Daemon.find_by_args(host, binary)
def daemon_get_all_by_topic(context, topic):
def service_get_all_by_topic(context, topic):
with managed_session() as session:
return session.query(models.Daemon) \
return session.query(models.Service) \
.filter_by(deleted=False) \
.filter_by(topic=topic) \
.all()
def daemon_get_all_compute_sorted(_context):
def service_get_all_compute_sorted(_context):
with managed_session() as session:
# NOTE(vish): The intended query is below
# SELECT daemons.*, inst_count.instance_count
# FROM daemons LEFT OUTER JOIN
# SELECT services.*, inst_count.instance_count
# FROM services LEFT OUTER JOIN
# (SELECT host, count(*) AS instance_count
# FROM instances GROUP BY host) AS inst_count
subq = session.query(models.Instance.host,
@@ -65,27 +65,31 @@ def daemon_get_all_compute_sorted(_context):
.group_by(models.Instance.host) \
.subquery()
topic = 'compute'
return session.query(models.Daemon, subq.c.instance_count) \
return session.query(models.Service, subq.c.instance_count) \
.filter_by(topic=topic) \
.filter_by(deleted=False) \
.outerjoin((subq, models.Daemon.host == subq.c.host)) \
.outerjoin((subq, models.Service.host == subq.c.host)) \
.order_by(subq.c.instance_count) \
.all()
def daemon_create(_context, values):
daemon_ref = models.Daemon()
for (key, value) in values.iteritems():
daemon_ref[key] = value
daemon_ref.save()
return daemon_ref.id
def service_get_by_args(_context, host, binary):
return models.Service.find_by_args(host, binary)
def daemon_update(context, daemon_id, values):
daemon_ref = daemon_get(context, daemon_id)
def service_create(_context, values):
service_ref = models.Service()
for (key, value) in values.iteritems():
daemon_ref[key] = value
daemon_ref.save()
service_ref[key] = value
service_ref.save()
return service_ref.id
def service_update(context, service_id, values):
service_ref = service_get(context, service_id)
for (key, value) in values.iteritems():
service_ref[key] = value
service_ref.save()
###################

View File

@@ -160,9 +160,9 @@ class Host(BASE, NovaBase):
id = Column(String(255), primary_key=True)
class Daemon(BASE, NovaBase):
class Service(BASE, NovaBase):
"""Represents a running service on a host"""
__tablename__ = 'daemons'
__tablename__ = 'services'
id = Column(Integer, primary_key=True)
host = Column(String(255), ForeignKey('hosts.id'))
binary = Column(String(255))
@@ -392,7 +392,7 @@ class FloatingIp(BASE, NovaBase):
def register_models():
"""Register Models and create metadata"""
from sqlalchemy import create_engine
models = (Image, Host, Daemon, Instance, Volume, ExportDevice,
models = (Image, Host, Service, Instance, Volume, ExportDevice,
FixedIp, FloatingIp, Network, NetworkIndex)
engine = create_engine(FLAGS.sql_connection, echo=False)
for model in models:

View File

@@ -18,7 +18,7 @@
"""
Proxy AMI-related calls from the cloud controller, to the running
objectstore daemon.
objectstore service.
"""
import json

View File

@@ -17,11 +17,11 @@
# under the License.
"""
Base functionality for nova daemons - gradually being replaced with twistd.py.
Base functionality for nova services - gradually being replaced with twistd.py.
"""
import daemon
from daemon import pidlockfile
import service
from service import pidlockfile
import logging
import logging.handlers
import os
@@ -33,14 +33,14 @@ from nova import flags
FLAGS = flags.FLAGS
flags.DEFINE_bool('daemonize', False, 'daemonize this process')
# NOTE(termie): right now I am defaulting to using syslog when we daemonize
flags.DEFINE_bool('serviceize', False, 'serviceize this process')
# NOTE(termie): right now I am defaulting to using syslog when we serviceize
# it may be better to do something else -shrug-
# NOTE(Devin): I think we should let each process have its own log file
# and put it in /var/logs/nova/(appname).log
# This makes debugging much easier and cuts down on sys log
# clutter.
flags.DEFINE_bool('use_syslog', True, 'output to syslog when daemonizing')
flags.DEFINE_bool('use_syslog', True, 'output to syslog when serviceizing')
flags.DEFINE_string('logfile', None, 'log file to output to')
flags.DEFINE_string('pidfile', None, 'pid file to output to')
flags.DEFINE_string('working_directory', './', 'working directory...')
@@ -50,17 +50,17 @@ flags.DEFINE_integer('gid', os.getgid(), 'gid under which to run')
def stop(pidfile):
"""
Stop the daemon
Stop the service
"""
# Get the pid from the pidfile
try:
pid = int(open(pidfile,'r').read().strip())
except IOError:
message = "pidfile %s does not exist. Daemon not running?\n"
message = "pidfile %s does not exist. Service not running?\n"
sys.stderr.write(message % pidfile)
return # not an error in a restart
# Try killing the daemon process
# Try killing the service process
try:
while 1:
os.kill(pid, signal.SIGTERM)
@@ -100,13 +100,13 @@ def serve(name, main):
else:
print 'usage: %s [options] [start|stop|restart]' % argv[0]
sys.exit(1)
daemonize(argv, name, main)
serviceize(argv, name, main)
def daemonize(args, name, main):
"""Does the work of daemonizing the process"""
def serviceize(args, name, main):
"""Does the work of serviceizing the process"""
logging.getLogger('amqplib').setLevel(logging.WARN)
if FLAGS.daemonize:
if FLAGS.serviceize:
logger = logging.getLogger()
formatter = logging.Formatter(
name + '(%(name)s): %(levelname)s %(message)s')
@@ -129,8 +129,8 @@ def daemonize(args, name, main):
else:
logging.getLogger().setLevel(logging.WARNING)
with daemon.DaemonContext(
detach_process=FLAGS.daemonize,
with service.ServiceContext(
detach_process=FLAGS.serviceize,
working_directory=FLAGS.working_directory,
pidfile=pidlockfile.TimeoutPIDLockFile(FLAGS.pidfile,
acquire_timeout=1,

View File

@@ -52,6 +52,16 @@ class Service(object, service.Service):
self.manager = manager_class(host=host, *args, **kwargs)
self.model_disconnected = False
super(Service, self).__init__(*args, **kwargs)
try:
service_ref = db.service_get_by_args(None,
self.host,
self.binary)
self.service_id = service_ref['id']
except exception.NotFound:
self.service_id = db.service_create(None, {'host': self.host,
'binary': self.binary,
'topic': self.topic,
'report_count': 0})
def __getattr__(self, key):
try:
@@ -110,24 +120,25 @@ class Service(object, service.Service):
service_obj.setServiceParent(application)
return application
def kill(self, context=None):
"""Destroy the service object in the datastore"""
try:
service_ref = db.service_get_by_args(context,
self.host,
self.binary)
service_id = service_ref['id']
db.service_destroy(context, self.service_id)
except exception.NotFound:
logging.warn("Service killed that has no database entry")
@defer.inlineCallbacks
def report_state(self, context=None):
"""Update the state of this daemon in the datastore."""
"""Update the state of this service in the datastore."""
try:
try:
daemon_ref = db.daemon_get_by_args(context,
self.host,
self.binary)
daemon_id = daemon_ref['id']
except exception.NotFound:
daemon_id = db.daemon_create(context, {'host': self.host,
'binary': self.binary,
'topic': self.topic,
'report_count': 0})
daemon_ref = db.daemon_get(context, daemon_id)
db.daemon_update(context,
daemon_id,
{'report_count': daemon_ref['report_count'] + 1})
service_ref = db.service_get(context, self.service_id)
db.service_update(context,
self.service_id,
{'report_count': service_ref['report_count'] + 1})
# TODO(termie): make this pattern be more elegant.
if getattr(self, "model_disconnected", False):

View File

@@ -84,40 +84,40 @@ class ServiceTestCase(test.BaseTestCase):
def test_report_state(self):
host = 'foo'
binary = 'bar'
daemon_ref = {'host': host,
service_ref = {'host': host,
'binary': binary,
'report_count': 0,
'id': 1}
service.db.__getattr__('report_state')
service.db.daemon_get_by_args(None,
service.db.service_get_by_args(None,
host,
binary).AndReturn(daemon_ref)
service.db.daemon_update(None, daemon_ref['id'],
binary).AndReturn(service_ref)
service.db.service_update(None, service_ref['id'],
mox.ContainsKeyValue('report_count', 1))
self.mox.ReplayAll()
s = service.Service()
rv = yield s.report_state(host, binary)
def test_report_state_no_daemon(self):
def test_report_state_no_service(self):
host = 'foo'
binary = 'bar'
daemon_create = {'host': host,
service_create = {'host': host,
'binary': binary,
'report_count': 0}
daemon_ref = {'host': host,
service_ref = {'host': host,
'binary': binary,
'report_count': 0,
'id': 1}
service.db.__getattr__('report_state')
service.db.daemon_get_by_args(None,
service.db.service_get_by_args(None,
host,
binary).AndRaise(exception.NotFound())
service.db.daemon_create(None,
daemon_create).AndReturn(daemon_ref['id'])
service.db.daemon_get(None, daemon_ref['id']).AndReturn(daemon_ref)
service.db.daemon_update(None, daemon_ref['id'],
service.db.service_create(None,
service_create).AndReturn(service_ref['id'])
service.db.service_get(None, service_ref['id']).AndReturn(service_ref)
service.db.service_update(None, service_ref['id'],
mox.ContainsKeyValue('report_count', 1))
self.mox.ReplayAll()
@@ -127,13 +127,13 @@ class ServiceTestCase(test.BaseTestCase):
def test_report_state_newly_disconnected(self):
host = 'foo'
binary = 'bar'
daemon_ref = {'host': host,
service_ref = {'host': host,
'binary': binary,
'report_count': 0,
'id': 1}
service.db.__getattr__('report_state')
service.db.daemon_get_by_args(None,
service.db.service_get_by_args(None,
host,
binary).AndRaise(Exception())
@@ -146,16 +146,16 @@ class ServiceTestCase(test.BaseTestCase):
def test_report_state_newly_connected(self):
host = 'foo'
binary = 'bar'
daemon_ref = {'host': host,
service_ref = {'host': host,
'binary': binary,
'report_count': 0,
'id': 1}
service.db.__getattr__('report_state')
service.db.daemon_get_by_args(None,
service.db.service_get_by_args(None,
host,
binary).AndReturn(daemon_ref)
service.db.daemon_update(None, daemon_ref['id'],
binary).AndReturn(service_ref)
service.db.service_update(None, service_ref['id'],
mox.ContainsKeyValue('report_count', 1))
self.mox.ReplayAll()