summaryrefslogtreecommitdiffstats
path: root/nova/compute
diff options
context:
space:
mode:
authorJustin Santa Barbara <justin@fathomdb.com>2011-03-14 14:17:58 -0700
committerJustin Santa Barbara <justin@fathomdb.com>2011-03-14 14:17:58 -0700
commitc94ec9a5bab6c07b402b68e2f4ff081247a27cda (patch)
tree437e4e1cbb128812af04a6aa9cb2ab50661bf89a /nova/compute
parent119bbe04f3c1de06a8c40502c314f13c89561564 (diff)
Initial implementation of refresh instance states
Diffstat (limited to 'nova/compute')
-rw-r--r--nova/compute/driver.py38
-rw-r--r--nova/compute/manager.py56
-rw-r--r--nova/compute/power_state.py16
3 files changed, 105 insertions, 5 deletions
diff --git a/nova/compute/driver.py b/nova/compute/driver.py
new file mode 100644
index 000000000..bda82c60a
--- /dev/null
+++ b/nova/compute/driver.py
@@ -0,0 +1,38 @@
+# vim: tabstop=4 shiftwidth=4 softtabstop=4
+
+# Copyright 2011 Justin Santa Barbara
+# All Rights Reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License"); you may
+# not use this file except in compliance with the License. You may obtain
+# a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+# License for the specific language governing permissions and limitations
+# under the License.
+
+"""
+Driver base-classes:
+
+ (Beginning of) the contract that compute drivers must follow, and shared
+ types that support that contract
+"""
+
+from nova.compute import power_state
+
+
+class InstanceInfo(object):
+ def __init__(self, name, state):
+ self.name = name
+ assert state in power_state.valid_states()
+ self.state = state
+
+
+class ComputeDriver(object):
+ def list_instances_detail(self):
+ """Return a list of InstanceInfo for all registered VMs"""
+ raise NotImplementedError()
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 0cab10fc3..057371d40 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -2,6 +2,7 @@
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
+# Copyright 2011 Justin Santa Barbara
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
@@ -51,6 +52,7 @@ from nova import manager
from nova import rpc
from nova import utils
from nova.compute import power_state
+from nova.compute import driver
FLAGS = flags.FLAGS
flags.DEFINE_string('instances_path', '$state_path/instances',
@@ -115,7 +117,9 @@ class ComputeManager(manager.Manager):
# and redocument the module docstring
if not compute_driver:
compute_driver = FLAGS.compute_driver
- self.driver = utils.import_object(compute_driver)
+ self.driver = utils.check_instance(utils.import_object(
+ compute_driver),
+ driver.ComputeDriver)
self.network_manager = utils.import_object(FLAGS.network_manager)
self.volume_manager = utils.import_object(FLAGS.volume_manager)
super(ComputeManager, self).__init__(*args, **kwargs)
@@ -974,3 +978,53 @@ class ComputeManager(manager.Manager):
for volume in instance_ref['volumes']:
self.db.volume_update(ctxt, volume['id'], {'status': 'in-use'})
+
+ def periodic_tasks(self, context=None):
+ """Tasks to be run at a periodic interval."""
+ super(ComputeManager, self).periodic_tasks(context)
+ try:
+ self._poll_instance_states(context)
+ except Exception as ex:
+ LOG.warning(_("Error during instance poll: %s"),
+ unicode(ex))
+
+ def _poll_instance_states(self, context):
+ vm_instances = self.driver.list_instances_detail(context)
+ vm_instances = dict((vm.name, vm) for vm in vm_instances)
+
+ # Keep a list of VMs not in the DB, cross them off as we find them
+ vms_not_found_in_db = [vm.name for vm in vm_instances]
+
+ db_instances = self.db.instance_get_all_by_host(context, self.host)
+ for db_instance in db_instances:
+ name = db_instance['name']
+ vm_instance = vm_instances.get(name)
+ if vm_instance is None:
+ LOG.info(_("Found instance '%(name)' in DB but no VM. "
+ "Shutting off.") % locals())
+ vm_state = power_state.SHUTOFF
+ else:
+ vm_state = vm_instance.state
+ vms_not_found_in_db.remove(name)
+
+ db_state = db_instance['state']
+ if vm_state != db_state:
+ LOG.info(_("DB/VM state mismatch. Changing state from "
+ "%(db_state) to %(vm_state)") % locals())
+ self.db.instance_set_state(context,
+ db_instance['id'],
+ vm_state)
+
+ if vm_state == power_state.SHUTOFF:
+ # TODO(soren): This is what the compute manager does when you
+ # terminate an instance. At some point I figure we'll have a
+ # "terminated" state and some sort of cleanup job that runs
+ # occasionally, cleaning them out.
+ self.db.instance_destroy(context, db_instance['id'])
+
+ # Are there VMs not in the DB?
+ for vm_not_found_in_db in vms_not_found_in_db:
+ name = vm_not_found_in_db
+ #TODO(justinsb): What to do here? Adopt it? Shut it down?
+ LOG.warning(_("Found VM not in DB: %(name). Ignoring")
+ % locals())
diff --git a/nova/compute/power_state.py b/nova/compute/power_state.py
index adfc2dff0..145362f97 100644
--- a/nova/compute/power_state.py
+++ b/nova/compute/power_state.py
@@ -2,6 +2,7 @@
# Copyright 2010 United States Government as represented by the
# Administrator of the National Aeronautics and Space Administration.
+# Copyright 2011 Justin Santa Barbara
# All Rights Reserved.
# Copyright (c) 2010 Citrix Systems, Inc.
#
@@ -19,6 +20,7 @@
"""The various power states that a VM can be in."""
+#NOTE(justinsb): These are the virDomainState values from libvirt
NOSTATE = 0x00
RUNNING = 0x01
BLOCKED = 0x02
@@ -29,9 +31,8 @@ CRASHED = 0x06
SUSPENDED = 0x07
FAILED = 0x08
-
-def name(code):
- d = {
+#TODO(justinsb): Power state really needs to be a proper class...
+_STATE_MAP = {
NOSTATE: 'pending',
RUNNING: 'running',
BLOCKED: 'blocked',
@@ -41,4 +42,11 @@ def name(code):
CRASHED: 'crashed',
SUSPENDED: 'suspended',
FAILED: 'failed to spawn'}
- return d[code]
+
+
+def name(code):
+ return _STATE_MAP[code]
+
+
+def valid_states():
+ return _STATE_MAP.values()