diff options
| author | Sandy Walsh <sandy.walsh@rackspace.com> | 2011-02-17 12:12:19 -0800 |
|---|---|---|
| committer | Sandy Walsh <sandy.walsh@rackspace.com> | 2011-02-17 12:12:19 -0800 |
| commit | aa71a25c9f9bf5df3aea781138fa8d69654f06d9 (patch) | |
| tree | e0274c08dbc6fab6c339246606cf984262444b8b | |
| parent | 984db08a205bdd9196c3e1cc3415873a853c33ba (diff) | |
| download | nova-aa71a25c9f9bf5df3aea781138fa8d69654f06d9.tar.gz nova-aa71a25c9f9bf5df3aea781138fa8d69654f06d9.tar.xz nova-aa71a25c9f9bf5df3aea781138fa8d69654f06d9.zip | |
zone list now comes from scheduler zonemanager
| -rw-r--r-- | nova/api/openstack/zones.py | 32 | ||||
| -rw-r--r-- | nova/scheduler/manager.py | 82 | ||||
| -rw-r--r-- | nova/scheduler/zone_manager.py | 11 |
3 files changed, 46 insertions, 79 deletions
diff --git a/nova/api/openstack/zones.py b/nova/api/openstack/zones.py index 16e5e366b..bd2c488d9 100644 --- a/nova/api/openstack/zones.py +++ b/nova/api/openstack/zones.py @@ -19,6 +19,7 @@ import logging from nova import flags from nova import wsgi from nova import db +from nova import rpc FLAGS = flags.FLAGS @@ -33,6 +34,10 @@ def _filter_keys(item, keys): return dict((k, v) for k, v in item.iteritems() if k in keys) +def _exclude_keys(item, keys): + return dict((k, v) for k, v in item.iteritems() if k not in keys) + + def _scrub_zone(zone): return _filter_keys(zone, ('id', 'api_url')) @@ -44,11 +49,34 @@ class Controller(wsgi.Controller): "attributes": { "zone": ["id", "api_url", "name", "capabilities"]}}} + def _call_scheduler(self, method, context, params=None): + """Generic handler for RPC calls to the scheduler. + + :param params: Optional dictionary of arguments to be passed to the + scheduler worker + + :retval: Result returned by scheduler worker + """ + if not params: + params = {} + queue = FLAGS.scheduler_topic + kwargs = {'method': method, 'args': params} + return rpc.call(context, queue, kwargs) + def index(self, req): """Return all zones in brief""" - items = db.zone_get_all(req.environ['nova.context']) + # Ask the ZoneManager in the Scheduler for most recent data. + items = self._call_scheduler('get_zone_list', + req.environ['nova.context']) + for item in items: + item['api_url'] = item['api_url'].replace('\\/', '/') + + # Or fall-back to the database ... + if len(items) == 0: + items = db.zone_get_all(req.environ['nova.context']) items = common.limited(items, req) - items = [_scrub_zone(item) for item in items] + items = [_exclude_keys(item, ['username', 'password']) + for item in items] return dict(zones=items) def detail(self, req): diff --git a/nova/scheduler/manager.py b/nova/scheduler/manager.py index 693f8cb4b..00a0f4100 100644 --- a/nova/scheduler/manager.py +++ b/nova/scheduler/manager.py @@ -22,11 +22,6 @@ Scheduler Service """ import functools -import novatools -import thread - -from datetime import datetime -from eventlet.greenpool import GreenPool from nova import db from nova import flags @@ -34,83 +29,14 @@ from nova import log as logging from nova import manager from nova import rpc from nova import utils +from nova.scheduler.zone_manager import ZoneManager LOG = logging.getLogger('nova.scheduler.manager') FLAGS = flags.FLAGS flags.DEFINE_string('scheduler_driver', 'nova.scheduler.chance.ChanceScheduler', 'Driver to use for the scheduler') -flags.DEFINE_integer('zone_db_check_interval', - 60, - 'Seconds between getting fresh zone info from db.') - - -class ZoneState(object): - """Holds the state of all connected child zones.""" - def __init__(self): - self.is_active = True - self.name = None - self.capabilities = None - self.retry = 0 - self.last_seen = datetime.min - - def update(self, zone): - """Update zone credentials from db""" - self.zone_id = zone.id - self.api_url = zone.api_url - self.username = zone.username - self.password = zone.password - - -def _poll_zone(zone): - """Eventlet worker to poll a zone.""" - logging.debug("_POLL_ZONE: STARTING") - os = novatools.OpenStack(zone.username, zone.password, zone.api_url) - zone_metadata = os.zones.info() - logging.debug("_POLL_ZONE: GOT %s" % zone_metadata._info) - - # Stuff this in our cache. - - -class ZoneManager(object): - """Keeps the zone states updated.""" - def __init__(self): - self.last_zone_db_check = datetime.min - self.zone_states = {} - - def _refresh_from_db(self, context): - """Make our zone state map match the db.""" - # Add/update existing zones ... - zones = db.zone_get_all(context) - existing = self.zone_states.keys() - db_keys = [] - for zone in zones: - db_keys.append(zone.id) - if zone.id not in existing: - self.zone_states[zone.id] = ZoneState() - self.zone_states[zone.id].update(zone) - - # Cleanup zones removed from db ... - for zone_id in self.zone_states.keys(): - if zone_id not in db_keys: - del self.zone_states[zone_id] - - def _poll_zones(self, context): - """Try to connect to each child zone and get update.""" - - green_pool = GreenPool() - green_pool.imap(_poll_zone, self.zone_states.values()) - - def ping(self, context=None): - """Ping should be called periodically to update zone status.""" - logging.debug("ZoneManager PING") - diff = datetime.now() - self.last_zone_db_check - if diff.seconds >= FLAGS.zone_db_check_interval: - logging.debug("ZoneManager RECHECKING DB ") - self.last_zone_db_check = datetime.now() - self._refresh_from_db(context) - self._poll_zones(context) - + class SchedulerManager(manager.Manager): """Chooses a host to run instances on.""" @@ -129,6 +55,10 @@ class SchedulerManager(manager.Manager): """Poll child zones periodically to get status.""" self.zone_manager.ping(context) + def get_zone_list(self, context=None): + """Get a list of zones from the ZoneManager.""" + return self.zone_manager.get_zone_list() + def _schedule(self, method, context, topic, *args, **kwargs): """Tries to call schedule_* method on the driver to retrieve host. diff --git a/nova/scheduler/zone_manager.py b/nova/scheduler/zone_manager.py index a35acb000..4fa528973 100644 --- a/nova/scheduler/zone_manager.py +++ b/nova/scheduler/zone_manager.py @@ -21,6 +21,7 @@ ZoneManager oversees all communications with child Zones. import novatools import thread +import traceback from datetime import datetime from eventlet.greenpool import GreenPool @@ -63,6 +64,11 @@ class ZoneState(object): self.capabilities = zone_metadata["capabilities"] self.is_active = True + def to_dict(self): + return dict(name=self.name, capabilities=self.capabilities, + is_active=self.is_active, api_url=self.api_url, + id=self.zone_id) + def log_error(self, exception): """Something went wrong. Check to see if zone should be marked as offline.""" @@ -91,7 +97,7 @@ def _poll_zone(zone): try: zone.update_metadata(_call_novatools(zone)) except Exception, e: - zone.log_error(e) + zone.log_error(traceback.format_exc()) class ZoneManager(object): @@ -100,6 +106,9 @@ class ZoneManager(object): self.last_zone_db_check = datetime.min self.zone_states = {} + def get_zone_list(self): + return [ zone.to_dict() for zone in self.zone_states.values() ] + def _refresh_from_db(self, context): """Make our zone state map match the db.""" # Add/update existing zones ... |
