diff options
| author | Sandy Walsh <sandy.walsh@rackspace.com> | 2011-01-05 22:23:23 -0400 |
|---|---|---|
| committer | Sandy Walsh <sandy.walsh@rackspace.com> | 2011-01-05 22:23:23 -0400 |
| commit | d32633399622141e47cba44e25549e3d4e04077f (patch) | |
| tree | 200e0bc0b532be88fdef0027b4cf845e79a95698 /nova/compute | |
| parent | 401c3374c708d9f80d12eeea39360a26483c30da (diff) | |
| parent | 275d06792fd5de40b82ef461e3d565c3d0ed3700 (diff) | |
Fixed trunk merge conflicts as spotted by dubs.
Diffstat (limited to 'nova/compute')
| -rw-r--r-- | nova/compute/__init__.py | 15 | ||||
| -rw-r--r-- | nova/compute/api.py | 183 | ||||
| -rw-r--r-- | nova/compute/manager.py | 23 |
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') |
