summaryrefslogtreecommitdiffstats
path: root/nova/compute
diff options
context:
space:
mode:
authorSandy Walsh <sandy.walsh@rackspace.com>2011-01-05 22:23:23 -0400
committerSandy Walsh <sandy.walsh@rackspace.com>2011-01-05 22:23:23 -0400
commitd32633399622141e47cba44e25549e3d4e04077f (patch)
tree200e0bc0b532be88fdef0027b4cf845e79a95698 /nova/compute
parent401c3374c708d9f80d12eeea39360a26483c30da (diff)
parent275d06792fd5de40b82ef461e3d565c3d0ed3700 (diff)
Fixed trunk merge conflicts as spotted by dubs.
Diffstat (limited to 'nova/compute')
-rw-r--r--nova/compute/__init__.py15
-rw-r--r--nova/compute/api.py183
-rw-r--r--nova/compute/manager.py23
3 files changed, 122 insertions, 99 deletions
diff --git a/nova/compute/__init__.py b/nova/compute/__init__.py
index a5df2ec1a..b94f971d1 100644
--- a/nova/compute/__init__.py
+++ b/nova/compute/__init__.py
@@ -16,17 +16,4 @@
# License for the specific language governing permissions and limitations
# under the License.
-"""
-:mod:`nova.compute` -- Compute Nodes using LibVirt
-=====================================================
-
-.. automodule:: nova.compute
- :platform: Unix
- :synopsis: Thin wrapper around libvirt for VM mgmt.
-.. moduleauthor:: Jesse Andrews <jesse@ansolabs.com>
-.. moduleauthor:: Devin Carlen <devin.carlen@gmail.com>
-.. moduleauthor:: Vishvananda Ishaya <vishvananda@yahoo.com>
-.. moduleauthor:: Joshua McKenty <joshua@cognition.ca>
-.. moduleauthor:: Manish Singh <yosh@gimp.org>
-.. moduleauthor:: Andy Smith <andy@anarkystic.com>
-"""
+from nova.compute.api import API
diff --git a/nova/compute/api.py b/nova/compute/api.py
index f9595bde5..7ab7eb6ad 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -17,7 +17,7 @@
# under the License.
"""
-Handles all API requests relating to instances (guest vms).
+Handles all requests relating to instances (guest vms).
"""
import datetime
@@ -27,36 +27,41 @@ import time
from nova import db
from nova import exception
from nova import flags
+from nova import network
from nova import quota
from nova import rpc
from nova import utils
+from nova import volume
from nova.compute import instance_types
from nova.db import base
FLAGS = flags.FLAGS
-def generate_default_hostname(internal_id):
+def generate_default_hostname(instance_id):
"""Default function to generate a hostname given an instance reference."""
- return str(internal_id)
+ return str(instance_id)
-class ComputeAPI(base.Base):
+class API(base.Base):
"""API for interacting with the compute manager."""
- def __init__(self, network_manager=None, image_service=None, **kwargs):
- if not network_manager:
- network_manager = utils.import_object(FLAGS.network_manager)
- self.network_manager = network_manager
+ def __init__(self, image_service=None, network_api=None, volume_api=None,
+ **kwargs):
if not image_service:
image_service = utils.import_object(FLAGS.image_service)
self.image_service = image_service
- super(ComputeAPI, self).__init__(**kwargs)
+ if not network_api:
+ network_api = network.API()
+ self.network_api = network_api
+ if not volume_api:
+ volume_api = volume.API()
+ self.volume_api = volume_api
+ super(API, self).__init__(**kwargs)
def get_network_topic(self, context, instance_id):
try:
- instance = self.db.instance_get_by_internal_id(context,
- instance_id)
+ instance = self.get(context, instance_id)
except exception.NotFound as e:
logging.warning("Instance %d was not found in get_network_topic",
instance_id)
@@ -70,18 +75,18 @@ class ComputeAPI(base.Base):
topic,
{"method": "get_network_topic", "args": {'fake': 1}})
- def create_instances(self, context, instance_type, image_id, min_count=1,
- max_count=1, kernel_id=None, ramdisk_id=None,
- display_name='', description='', key_name=None,
- key_data=None, security_group='default',
- availability_zone=None,
- user_data=None,
- generate_hostname=generate_default_hostname):
- """Create the number of instances requested if quote and
+ def create(self, context, instance_type,
+ image_id, kernel_id=None, ramdisk_id=None,
+ min_count=1, max_count=1,
+ display_name='', display_description='',
+ key_name=None, key_data=None, security_group='default',
+ availability_zone=None, user_data=None,
+ generate_hostname=generate_default_hostname):
+ """Create the number of instances requested if quota and
other arguments check out ok."""
- num_instances = quota.allowed_instances(context, max_count,
- instance_type)
+ type_data = instance_types.INSTANCE_TYPES[instance_type]
+ num_instances = quota.allowed_instances(context, max_count, type_data)
if num_instances < min_count:
logging.warn("Quota exceeeded for %s, tried to run %s instances",
context.project_id, min_count)
@@ -96,7 +101,7 @@ class ComputeAPI(base.Base):
kernel_id = image.get('kernelId', None)
if ramdisk_id is None:
ramdisk_id = image.get('ramdiskId', None)
- #No kernel and ramdisk for raw images
+ # No kernel and ramdisk for raw images
if kernel_id == str(FLAGS.null_kernel):
kernel_id = None
ramdisk_id = None
@@ -126,7 +131,6 @@ class ComputeAPI(base.Base):
key_pair = db.key_pair_get(context, context.user_id, key_name)
key_data = key_pair['public_key']
- type_data = instance_types.INSTANCE_TYPES[instance_type]
base_options = {
'reservation_id': utils.generate_uid('r'),
'image_id': image_id,
@@ -141,7 +145,7 @@ class ComputeAPI(base.Base):
'vcpus': type_data['vcpus'],
'local_gb': type_data['local_gb'],
'display_name': display_name,
- 'display_description': description,
+ 'display_description': display_description,
'user_data': user_data or '',
'key_name': key_name,
'key_data': key_data,
@@ -156,7 +160,6 @@ class ComputeAPI(base.Base):
**base_options)
instance = self.db.instance_create(context, instance)
instance_id = instance['id']
- internal_id = instance['internal_id']
elevated = context.elevated()
if not security_groups:
@@ -167,11 +170,11 @@ class ComputeAPI(base.Base):
security_group_id)
# Set sane defaults if not specified
- updates = dict(hostname=generate_hostname(internal_id))
+ updates = dict(hostname=generate_hostname(instance_id))
if 'display_name' not in instance:
- updates['display_name'] = "Server %s" % internal_id
+ updates['display_name'] = "Server %s" % instance_id
- instance = self.update_instance(context, instance_id, **updates)
+ instance = self.update(context, instance_id, **updates)
instances.append(instance)
logging.debug(_("Casting to scheduler for %s/%s's instance %s"),
@@ -201,7 +204,7 @@ class ComputeAPI(base.Base):
'project_id': context.project_id}
db.security_group_create(context, values)
- def update_instance(self, context, instance_id, **kwargs):
+ def update(self, context, instance_id, **kwargs):
"""Updates the instance in the datastore.
:param context: The security context
@@ -215,134 +218,172 @@ class ComputeAPI(base.Base):
"""
return self.db.instance_update(context, instance_id, kwargs)
- def delete_instance(self, context, instance_id):
- logging.debug("Going to try and terminate %d" % instance_id)
+ def delete(self, context, instance_id):
+ logging.debug("Going to try and terminate %s" % instance_id)
try:
- instance = self.db.instance_get_by_internal_id(context,
- instance_id)
+ instance = self.get(context, instance_id)
except exception.NotFound as e:
- logging.warning(_("Instance %d was not found during terminate"),
+ logging.warning(_("Instance %s was not found during terminate"),
instance_id)
raise e
if (instance['state_description'] == 'terminating'):
- logging.warning(_("Instance %d is already being terminated"),
+ logging.warning(_("Instance %s is already being terminated"),
instance_id)
return
- self.update_instance(context,
- instance['id'],
- state_description='terminating',
- state=0,
- terminated_at=datetime.datetime.utcnow())
+ self.update(context,
+ instance['id'],
+ state_description='terminating',
+ state=0,
+ terminated_at=datetime.datetime.utcnow())
host = instance['host']
if host:
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "terminate_instance",
- "args": {"instance_id": instance['id']}})
+ "args": {"instance_id": instance_id}})
else:
- self.db.instance_destroy(context, instance['id'])
-
- def get_instances(self, context, project_id=None):
- """Get all instances, possibly filtered by project ID or
- user ID. If there is no filter and the context is an admin,
- it will retreive all instances in the system."""
+ self.db.instance_destroy(context, instance_id)
+
+ def get(self, context, instance_id):
+ """Get a single instance with the given ID."""
+ return self.db.instance_get_by_id(context, instance_id)
+
+ def get_all(self, context, project_id=None, reservation_id=None,
+ fixed_ip=None):
+ """Get all instances, possibly filtered by one of the
+ given parameters. If there is no filter and the context is
+ an admin, it will retreive all instances in the system."""
+ if reservation_id is not None:
+ return self.db.instance_get_all_by_reservation(context,
+ reservation_id)
+ if fixed_ip is not None:
+ return self.db.fixed_ip_get_instance(context, fixed_ip)
if project_id or not context.is_admin:
if not context.project:
return self.db.instance_get_all_by_user(context,
context.user_id)
if project_id is None:
project_id = context.project_id
- return self.db.instance_get_all_by_project(context, project_id)
+ return self.db.instance_get_all_by_project(context,
+ project_id)
return self.db.instance_get_all(context)
- def get_instance(self, context, instance_id):
- return self.db.instance_get_by_internal_id(context, instance_id)
-
def snapshot(self, context, instance_id, name):
"""Snapshot the given instance."""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance['host']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "snapshot_instance",
- "args": {"instance_id": instance['id'], "name": name}})
+ "args": {"instance_id": instance_id, "name": name}})
def reboot(self, context, instance_id):
"""Reboot the given instance."""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance['host']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "reboot_instance",
- "args": {"instance_id": instance['id']}})
+ "args": {"instance_id": instance_id}})
def pause(self, context, instance_id):
"""Pause the given instance."""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance['host']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "pause_instance",
- "args": {"instance_id": instance['id']}})
+ "args": {"instance_id": instance_id}})
def unpause(self, context, instance_id):
"""Unpause the given instance."""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance['host']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "unpause_instance",
- "args": {"instance_id": instance['id']}})
+ "args": {"instance_id": instance_id}})
def get_diagnostics(self, context, instance_id):
"""Retrieve diagnostics for the given instance."""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance["host"]
return rpc.call(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "get_diagnostics",
- "args": {"instance_id": instance["id"]}})
+ "args": {"instance_id": instance_id}})
def get_actions(self, context, instance_id):
"""Retrieve actions for the given instance."""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
- return self.db.instance_get_actions(context, instance["id"])
+ return self.db.instance_get_actions(context, instance_id)
def suspend(self, context, instance_id):
"""suspend the instance with instance_id"""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance['host']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "suspend_instance",
- "args": {"instance_id": instance['id']}})
+ "args": {"instance_id": instance_id}})
def resume(self, context, instance_id):
"""resume the instance with instance_id"""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance['host']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "resume_instance",
- "args": {"instance_id": instance['id']}})
+ "args": {"instance_id": instance_id}})
def rescue(self, context, instance_id):
"""Rescue the given instance."""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance['host']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "rescue_instance",
- "args": {"instance_id": instance['id']}})
+ "args": {"instance_id": instance_id}})
def unrescue(self, context, instance_id):
"""Unrescue the given instance."""
- instance = self.db.instance_get_by_internal_id(context, instance_id)
+ instance = self.get(context, instance_id)
host = instance['host']
rpc.cast(context,
self.db.queue_get_for(context, FLAGS.compute_topic, host),
{"method": "unrescue_instance",
- "args": {"instance_id": instance['id']}})
+ "args": {"instance_id": instance_id}})
+
+ 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. "
+ "Example device: /dev/vdb") % device)
+ self.volume_api.check_attach(context, volume_id)
+ instance = self.get(context, instance_id)
+ host = instance['host']
+ rpc.cast(context,
+ self.db.queue_get_for(context, FLAGS.compute_topic, host),
+ {"method": "attach_volume",
+ "args": {"volume_id": volume_id,
+ "instance_id": instance_id,
+ "mountpoint": device}})
+
+ def detach_volume(self, context, volume_id):
+ instance = self.db.volume_get_instance(context.elevated(), volume_id)
+ if not instance:
+ raise exception.ApiError(_("Volume isn't attached to anything!"))
+ self.volume_api.check_detach(context, volume_id)
+ host = instance['host']
+ rpc.cast(context,
+ self.db.queue_get_for(context, FLAGS.compute_topic, host),
+ {"method": "detach_volume",
+ "args": {"instance_id": instance['id'],
+ "volume_id": volume_id}})
+ return instance
+
+ def associate_floating_ip(self, context, instance_id, address):
+ instance = self.get(context, instance_id)
+ self.network_api.associate_floating_ip(context, address,
+ instance['fixed_ip'])
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 6e8f34347..ca6065890 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -211,7 +211,7 @@ class ComputeManager(manager.Manager):
if instance_ref['state'] != power_state.RUNNING:
logging.warn(_('trying to reboot a non-running '
'instance: %s (state: %s excepted: %s)'),
- instance_ref['internal_id'],
+ instance_id,
instance_ref['state'],
power_state.RUNNING)
@@ -239,7 +239,7 @@ class ComputeManager(manager.Manager):
if instance_ref['state'] != power_state.RUNNING:
logging.warn(_('trying to snapshot a non-running '
'instance: %s (state: %s excepted: %s)'),
- instance_ref['internal_id'],
+ instance_id,
instance_ref['state'],
power_state.RUNNING)
@@ -251,8 +251,7 @@ class ComputeManager(manager.Manager):
context = context.elevated()
instance_ref = self.db.instance_get(context, instance_id)
- logging.debug(_('instance %s: rescuing'),
- instance_ref['internal_id'])
+ logging.debug(_('instance %s: rescuing'), instance_id)
self.db.instance_set_state(context,
instance_id,
power_state.NOSTATE,
@@ -267,8 +266,7 @@ class ComputeManager(manager.Manager):
context = context.elevated()
instance_ref = self.db.instance_get(context, instance_id)
- logging.debug(_('instance %s: unrescuing'),
- instance_ref['internal_id'])
+ logging.debug(_('instance %s: unrescuing'), instance_id)
self.db.instance_set_state(context,
instance_id,
power_state.NOSTATE,
@@ -287,8 +285,7 @@ class ComputeManager(manager.Manager):
context = context.elevated()
instance_ref = self.db.instance_get(context, instance_id)
- logging.debug('instance %s: pausing',
- instance_ref['internal_id'])
+ logging.debug('instance %s: pausing', instance_id)
self.db.instance_set_state(context,
instance_id,
power_state.NOSTATE,
@@ -305,8 +302,7 @@ class ComputeManager(manager.Manager):
context = context.elevated()
instance_ref = self.db.instance_get(context, instance_id)
- logging.debug('instance %s: unpausing',
- instance_ref['internal_id'])
+ logging.debug('instance %s: unpausing', instance_id)
self.db.instance_set_state(context,
instance_id,
power_state.NOSTATE,
@@ -324,7 +320,7 @@ class ComputeManager(manager.Manager):
if instance_ref["state"] == power_state.RUNNING:
logging.debug(_("instance %s: retrieving diagnostics"),
- instance_ref["internal_id"])
+ instance_id)
return self.driver.get_diagnostics(instance_ref)
@exception.wrap_exception
@@ -333,8 +329,7 @@ class ComputeManager(manager.Manager):
context = context.elevated()
instance_ref = self.db.instance_get(context, instance_id)
- logging.debug(_('instance %s: suspending'),
- instance_ref['internal_id'])
+ logging.debug(_('instance %s: suspending'), instance_id)
self.db.instance_set_state(context, instance_id,
power_state.NOSTATE,
'suspending')
@@ -350,7 +345,7 @@ class ComputeManager(manager.Manager):
context = context.elevated()
instance_ref = self.db.instance_get(context, instance_id)
- logging.debug(_('instance %s: resuming'), instance_ref['internal_id'])
+ logging.debug(_('instance %s: resuming'), instance_id)
self.db.instance_set_state(context, instance_id,
power_state.NOSTATE,
'resuming')