summaryrefslogtreecommitdiffstats
path: root/nova/compute
diff options
context:
space:
mode:
authorEd Leafe <ed@leafe.com>2011-01-07 07:28:30 -0600
committerEd Leafe <ed@leafe.com>2011-01-07 07:28:30 -0600
commitb024dcf6f0c1e5a2735e84d21d6edef5ff38d1cf (patch)
tree72a98ad437b83e6f24e0848739f5502c52dacdae /nova/compute
parente66f3017373dcf9135c53ae4d510b0b2a5dcecf0 (diff)
parente33102d23ec8f357c08e2583f8d9e3c1753bab4d (diff)
merged changes from trunk
Diffstat (limited to 'nova/compute')
-rw-r--r--nova/compute/api.py33
-rw-r--r--nova/compute/manager.py88
2 files changed, 119 insertions, 2 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index a4345f337..78ffcca7a 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -147,6 +147,7 @@ class API(base.Base):
'user_data': user_data or '',
'key_name': key_name,
'key_data': key_data,
+ 'locked': False,
'availability_zone': availability_zone}
elevated = context.elevated()
@@ -322,6 +323,38 @@ class API(base.Base):
"""Set the root/admin password for the given instance."""
self._cast_compute_message('set_admin_password', context, instance_id)
+ def lock(self, context, instance_id):
+ """
+ lock the instance with instance_id
+
+ """
+ instance = self.get_instance(context, instance_id)
+ host = instance['host']
+ rpc.cast(context,
+ self.db.queue_get_for(context, FLAGS.compute_topic, host),
+ {"method": "lock_instance",
+ "args": {"instance_id": instance['id']}})
+
+ def unlock(self, context, instance_id):
+ """
+ unlock the instance with instance_id
+
+ """
+ instance = self.get_instance(context, instance_id)
+ host = instance['host']
+ rpc.cast(context,
+ self.db.queue_get_for(context, FLAGS.compute_topic, host),
+ {"method": "unlock_instance",
+ "args": {"instance_id": instance['id']}})
+
+ def get_lock(self, context, instance_id):
+ """
+ return the boolean state of (instance with instance_id)'s lock
+
+ """
+ instance = self.get_instance(context, instance_id)
+ return instance['locked']
+
def attach_volume(self, context, instance_id, volume_id, device):
if not re.match("^/dev/[a-z]d[a-z]+$", device):
raise exception.ApiError(_("Invalid device specified: %s. "
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 52acfebea..10219833b 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -38,6 +38,7 @@ import datetime
import logging
import random
import string
+import functools
from nova import exception
from nova import flags
@@ -57,6 +58,38 @@ flags.DEFINE_integer('password_length', 12,
'Length of generated admin passwords')
+def checks_instance_lock(function):
+ """
+ decorator used for preventing action against locked instances
+ unless, of course, you happen to be admin
+
+ """
+
+ @functools.wraps(function)
+ def decorated_function(self, context, instance_id, *args, **kwargs):
+
+ logging.info(_("check_instance_lock: decorating: |%s|"), function)
+ logging.info(_("check_instance_lock: arguments: |%s| |%s| |%s|"),
+ self,
+ context,
+ instance_id)
+ locked = self.get_lock(context, instance_id)
+ admin = context.is_admin
+ logging.info(_("check_instance_lock: locked: |%s|"), locked)
+ logging.info(_("check_instance_lock: admin: |%s|"), admin)
+
+ # if admin or unlocked call function otherwise log error
+ if admin or not locked:
+ logging.info(_("check_instance_lock: executing: |%s|"), function)
+ function(self, context, instance_id, *args, **kwargs)
+ else:
+ logging.error(_("check_instance_lock: not executing |%s|"),
+ function)
+ return False
+
+ return decorated_function
+
+
class ComputeManager(manager.Manager):
"""Manages the running instances from creation to destruction."""
@@ -162,6 +195,7 @@ class ComputeManager(manager.Manager):
self._update_state(context, instance_id)
@exception.wrap_exception
+ @checks_instance_lock
def terminate_instance(self, context, instance_id):
"""Terminate an instance on this machine."""
context = context.elevated()
@@ -206,6 +240,7 @@ class ComputeManager(manager.Manager):
self.db.instance_destroy(context, instance_id)
@exception.wrap_exception
+ @checks_instance_lock
def reboot_instance(self, context, instance_id):
"""Reboot an instance on this server."""
context = context.elevated()
@@ -279,6 +314,7 @@ class ComputeManager(manager.Manager):
return "".join([random.choice(chrs) for i in xrange(length)])
@exception.wrap_exception
+ @checks_instance_lock
def rescue_instance(self, context, instance_id):
"""Rescue an instance on this server."""
context = context.elevated()
@@ -294,6 +330,7 @@ class ComputeManager(manager.Manager):
self._update_state(context, instance_id)
@exception.wrap_exception
+ @checks_instance_lock
def unrescue_instance(self, context, instance_id):
"""Rescue an instance on this server."""
context = context.elevated()
@@ -313,6 +350,7 @@ class ComputeManager(manager.Manager):
self._update_state(context, instance_id)
@exception.wrap_exception
+ @checks_instance_lock
def pause_instance(self, context, instance_id):
"""Pause an instance on this server."""
context = context.elevated()
@@ -330,6 +368,7 @@ class ComputeManager(manager.Manager):
result))
@exception.wrap_exception
+ @checks_instance_lock
def unpause_instance(self, context, instance_id):
"""Unpause a paused instance on this server."""
context = context.elevated()
@@ -357,8 +396,12 @@ class ComputeManager(manager.Manager):
return self.driver.get_diagnostics(instance_ref)
@exception.wrap_exception
+ @checks_instance_lock
def suspend_instance(self, context, instance_id):
- """suspend the instance with instance_id"""
+ """
+ suspend the instance with instance_id
+
+ """
context = context.elevated()
instance_ref = self.db.instance_get(context, instance_id)
@@ -373,8 +416,12 @@ class ComputeManager(manager.Manager):
result))
@exception.wrap_exception
+ @checks_instance_lock
def resume_instance(self, context, instance_id):
- """resume the suspended instance with instance_id"""
+ """
+ resume the suspended instance with instance_id
+
+ """
context = context.elevated()
instance_ref = self.db.instance_get(context, instance_id)
@@ -389,6 +436,41 @@ class ComputeManager(manager.Manager):
result))
@exception.wrap_exception
+ def lock_instance(self, context, instance_id):
+ """
+ lock the instance with instance_id
+
+ """
+ context = context.elevated()
+ instance_ref = self.db.instance_get(context, instance_id)
+
+ logging.debug(_('instance %s: locking'), instance_id)
+ self.db.instance_update(context, instance_id, {'locked': True})
+
+ @exception.wrap_exception
+ def unlock_instance(self, context, instance_id):
+ """
+ unlock the instance with instance_id
+
+ """
+ context = context.elevated()
+ instance_ref = self.db.instance_get(context, instance_id)
+
+ logging.debug(_('instance %s: unlocking'), instance_id)
+ self.db.instance_update(context, instance_id, {'locked': False})
+
+ @exception.wrap_exception
+ def get_lock(self, context, instance_id):
+ """
+ return the boolean state of (instance with instance_id)'s lock
+
+ """
+ context = context.elevated()
+ logging.debug(_('instance %s: getting locked state'), instance_id)
+ instance_ref = self.db.instance_get(context, instance_id)
+ return instance_ref['locked']
+
+ @exception.wrap_exception
def get_console_output(self, context, instance_id):
"""Send the console output for an instance."""
context = context.elevated()
@@ -398,6 +480,7 @@ class ComputeManager(manager.Manager):
return self.driver.get_console_output(instance_ref)
@exception.wrap_exception
+ @checks_instance_lock
def attach_volume(self, context, instance_id, volume_id, mountpoint):
"""Attach a volume to an instance."""
context = context.elevated()
@@ -427,6 +510,7 @@ class ComputeManager(manager.Manager):
return True
@exception.wrap_exception
+ @checks_instance_lock
def detach_volume(self, context, instance_id, volume_id):
"""Detach a volume from an instance."""
context = context.elevated()