From 73af1a84eb682423bf40323387d739778765e138 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Fri, 16 Jul 2010 21:52:10 +0000 Subject: make nova-volume start with twisteds daemonize stuff --- bin/nova-compute | 9 +++----- bin/nova-volume | 61 +++++++++++++++++++++++++++++++++++--------------- nova/volume/storage.py | 25 ++++++++++++++++----- 3 files changed, 65 insertions(+), 30 deletions(-) diff --git a/bin/nova-compute b/bin/nova-compute index 5635efbaf..4b559beb4 100755 --- a/bin/nova-compute +++ b/bin/nova-compute @@ -33,9 +33,6 @@ NOVA_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'nova') if os.path.exists(NOVA_PATH): sys.path.insert(0, os.path.dirname(NOVA_PATH)) - -from carrot import connection -from carrot import messaging from twisted.internet import task from twisted.application import service @@ -50,8 +47,8 @@ FLAGS = flags.FLAGS # context when the twistd.serve() call is made below so any # flags we define here will have to be conditionally defined, # flags defined by imported modules are safe. -if 'node_report_state_interval' not in FLAGS: - flags.DEFINE_integer('node_report_state_interval', 10, +if 'compute_report_state_interval' not in FLAGS: + flags.DEFINE_integer('compute_report_state_interval', 10, 'seconds between nodes reporting state to cloud', lower_bound=1) logging.getLogger().setLevel(logging.DEBUG) @@ -75,7 +72,7 @@ def main(): bin_name = os.path.basename(__file__) pulse = task.LoopingCall(n.report_state, FLAGS.node_name, bin_name) - pulse.start(interval=FLAGS.node_report_state_interval, now=False) + pulse.start(interval=FLAGS.compute_report_state_interval, now=False) injected = consumer_all.attach_to_twisted() injected = consumer_node.attach_to_twisted() diff --git a/bin/nova-volume b/bin/nova-volume index df9fb5c7a..64b726627 100755 --- a/bin/nova-volume +++ b/bin/nova-volume @@ -22,22 +22,37 @@ """ import logging -from tornado import ioloop +import os +import sys + +# NOTE(termie): kludge so that we can run this from the bin directory in the +# checkout without having to screw with paths +NOVA_PATH = os.path.join(os.path.dirname(os.path.dirname(__file__)), 'nova') +if os.path.exists(NOVA_PATH): + sys.path.insert(0, os.path.dirname(NOVA_PATH)) + +from twisted.internet import task +from twisted.application import service from nova import flags from nova import rpc -from nova import server -from nova import utils +from nova import twistd from nova.volume import storage FLAGS = flags.FLAGS -flags.DEFINE_integer('storage_report_state_interval', 10, - 'seconds between broadcasting state to cloud', - lower_bound=1) +# NOTE(termie): This file will necessarily be re-imported under different +# context when the twistd.serve() call is made below so any +# flags we define here will have to be conditionally defined, +# flags defined by imported modules are safe. +if 'volume_report_state_interval' not in FLAGS: + flags.DEFINE_integer('volume_report_state_interval', 10, + 'seconds between nodes reporting state to cloud', + lower_bound=1) -def main(argv): +def main(): + logging.warn('Starting volume node') bs = storage.BlockStore() conn = rpc.Connection.instance() @@ -51,19 +66,29 @@ def main(argv): topic='%s.%s' % (FLAGS.storage_topic, FLAGS.node_name), proxy=bs) - io_inst = ioloop.IOLoop.instance() - scheduler = ioloop.PeriodicCallback( - lambda: bs.report_state(), - FLAGS.storage_report_state_interval * 1000, - io_loop=io_inst) + bin_name = os.path.basename(__file__) + pulse = task.LoopingCall(bs.report_state, FLAGS.node_name, bin_name) + pulse.start(interval=FLAGS.volume_report_state_interval, now=False) + + injected = consumer_all.attach_to_twisted() + injected = consumer_node.attach_to_twisted() - injected = consumer_all.attachToTornado(io_inst) - injected = consumer_node.attachToTornado(io_inst) - scheduler.start() - io_inst.start() + # This is the parent service that twistd will be looking for when it + # parses this file, return it so that we can get it into globals below + application = service.Application(bin_name) + bs.setServiceParent(application) + return application +# NOTE(termie): When this script is executed from the commandline what it will +# actually do is tell the twistd application runner that it +# should run this file as a twistd application (see below). if __name__ == '__main__': - utils.default_flagfile() - server.serve('nova-volume', main) + twistd.serve(__file__) +# NOTE(termie): When this script is loaded by the twistd application runner +# this code path will be executed and twistd will expect a +# variable named 'application' to be available, it will then +# handle starting it and stopping it. +if __name__ == '__builtin__': + application = main() diff --git a/nova/volume/storage.py b/nova/volume/storage.py index 5424b092f..121bc01e6 100644 --- a/nova/volume/storage.py +++ b/nova/volume/storage.py @@ -28,8 +28,8 @@ import os import shutil import socket import tempfile -import time -from tornado import ioloop + +from twisted.application import service from twisted.internet import defer from nova import datastore @@ -38,6 +38,7 @@ from nova import flags from nova import process from nova import utils from nova import validate +from nova.compute import model FLAGS = flags.FLAGS @@ -81,7 +82,7 @@ def get_volume(volume_id): return volume_class(volume_id=volume_id) raise exception.Error("Volume does not exist") -class BlockStore(object): +class BlockStore(object, service.Service): """ There is one BlockStore running on each volume node. However, each BlockStore can report on the state of @@ -103,9 +104,21 @@ class BlockStore(object): except Exception, err: pass - def report_state(self): - #TODO: aggregate the state of the system - pass + @defer.inlineCallbacks + def report_state(self, nodename, daemon): + # TODO(termie): make this pattern be more elegant. -todd + try: + record = model.Daemon(nodename, daemon) + record.heartbeat() + if getattr(self, "model_disconnected", False): + self.model_disconnected = False + logging.error("Recovered model server connection!") + + except model.ConnectionError, ex: + if not getattr(self, "model_disconnected", False): + self.model_disconnected = True + logging.exception("model server went away") + yield @validate.rangetest(size=(0, 1000)) def create_volume(self, size, user_id, project_id): -- cgit