summaryrefslogtreecommitdiffstats
path: root/nova/compute
diff options
context:
space:
mode:
authorjaypipes@gmail.com <>2010-12-21 10:25:39 -0500
committerjaypipes@gmail.com <>2010-12-21 10:25:39 -0500
commit887ee0aae54fc51124bb869af2bfee055a46d27a (patch)
tree3554feb1fba402ad064a4ac0b154d34f998040ff /nova/compute
parent1b4b36cec4d82009d595a601c408e2f582ef790c (diff)
parent086f2d87be3c56ac8dafaf4551096868d57454db (diff)
Merge trunk and resolve conflicts
Diffstat (limited to 'nova/compute')
-rw-r--r--nova/compute/api.py35
-rw-r--r--nova/compute/disk.py22
-rw-r--r--nova/compute/manager.py41
3 files changed, 89 insertions, 9 deletions
diff --git a/nova/compute/api.py b/nova/compute/api.py
index e701e540e..a33ed2dc4 100644
--- a/nova/compute/api.py
+++ b/nova/compute/api.py
@@ -73,14 +73,19 @@ class ComputeAPI(base.Base):
is_vpn = image_id == FLAGS.vpn_image_id
if not is_vpn:
image = self.image_service.show(context, image_id)
+
+ # If kernel_id/ramdisk_id isn't explicitly set in API call
+ # we take the defaults from the image's metadata
if kernel_id is None:
- kernel_id = image.get('kernelId', FLAGS.default_kernel)
+ kernel_id = image.get('kernelId', None)
if ramdisk_id is None:
- ramdisk_id = image.get('ramdiskId', FLAGS.default_ramdisk)
+ ramdisk_id = image.get('ramdiskId', None)
# Make sure we have access to kernel and ramdisk
- self.image_service.show(context, kernel_id)
- self.image_service.show(context, ramdisk_id)
+ if kernel_id:
+ self.image_service.show(context, kernel_id)
+ if ramdisk_id:
+ self.image_service.show(context, ramdisk_id)
if security_group is None:
security_group = ['default']
@@ -103,8 +108,8 @@ class ComputeAPI(base.Base):
base_options = {
'reservation_id': utils.generate_uid('r'),
'image_id': image_id,
- 'kernel_id': kernel_id,
- 'ramdisk_id': ramdisk_id,
+ 'kernel_id': kernel_id or '',
+ 'ramdisk_id': ramdisk_id or '',
'state_description': 'scheduling',
'user_id': context.user_id,
'project_id': context.project_id,
@@ -275,6 +280,24 @@ class ComputeAPI(base.Base):
{"method": "reboot_instance",
"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)
+ host = instance['host']
+ rpc.cast(context,
+ self.db.queue_get_for(context, FLAGS.compute_topic, host),
+ {"method": "pause_instance",
+ "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)
+ host = instance['host']
+ rpc.cast(context,
+ self.db.queue_get_for(context, FLAGS.compute_topic, host),
+ {"method": "unpause_instance",
+ "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)
diff --git a/nova/compute/disk.py b/nova/compute/disk.py
index 4263ae117..814a258cd 100644
--- a/nova/compute/disk.py
+++ b/nova/compute/disk.py
@@ -106,6 +106,13 @@ def partition(infile, outfile, local_bytes=0, resize=True,
% (outfile, local_type, local_first, local_last))
+def extend(image, size, execute):
+ file_size = os.path.getsize(image)
+ if file_size >= size:
+ return
+ return execute('truncate -s size %s' % (image,))
+
+
def inject_data(image, key=None, net=None, partition=None, execute=None):
"""Injects a ssh key and optionally net data into a disk image.
@@ -115,7 +122,7 @@ def inject_data(image, key=None, net=None, partition=None, execute=None):
If partition is not specified it mounts the image as a single partition.
"""
- out, err = execute('sudo losetup -f --show %s' % image)
+ out, err = execute('sudo losetup --find --show %s' % image)
if err:
raise exception.Error(_('Could not attach image to loopback: %s')
% err)
@@ -130,6 +137,15 @@ def inject_data(image, key=None, net=None, partition=None, execute=None):
partition)
else:
mapped_device = device
+
+ # We can only loopback mount raw images. If the device isn't there,
+ # it's normally because it's a .vmdk or a .vdi etc
+ if not os.path.exists(mapped_device):
+ raise exception.Error('Mapped device was not found (we can'
+ ' only inject raw disk images): %s' %
+ mapped_device)
+
+ # Configure ext2fs so that it doesn't auto-check every N boots
out, err = execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device)
tmpdir = tempfile.mkdtemp()
@@ -158,7 +174,7 @@ def inject_data(image, key=None, net=None, partition=None, execute=None):
execute('sudo kpartx -d %s' % device)
finally:
# remove loopback
- execute('sudo losetup -d %s' % device)
+ execute('sudo losetup --detach %s' % device)
def _inject_key_into_fs(key, fs, execute=None):
@@ -167,7 +183,7 @@ def _inject_key_into_fs(key, fs, execute=None):
key is an ssh key string.
fs is the path to the base of the filesystem into which to inject the key.
"""
- sshdir = os.path.join(os.path.join(fs, 'root'), '.ssh')
+ sshdir = os.path.join(fs, 'root', '.ssh')
execute('sudo mkdir -p %s' % sshdir) # existing dir doesn't matter
execute('sudo chown root %s' % sshdir)
execute('sudo chmod 700 %s' % sshdir)
diff --git a/nova/compute/manager.py b/nova/compute/manager.py
index 7d18d0eff..135663ab5 100644
--- a/nova/compute/manager.py
+++ b/nova/compute/manager.py
@@ -186,6 +186,47 @@ class ComputeManager(manager.Manager):
self.driver.unrescue(instance_ref)
self._update_state(context, instance_id)
+ @staticmethod
+ def _update_state_callback(self, context, instance_id, result):
+ """Update instance state when async task completes."""
+ self._update_state(context, instance_id)
+
+ @exception.wrap_exception
+ def pause_instance(self, context, instance_id):
+ """Pause an instance on this server."""
+ context = context.elevated()
+ instance_ref = self.db.instance_get(context, instance_id)
+
+ logging.debug('instance %s: pausing',
+ instance_ref['internal_id'])
+ self.db.instance_set_state(context,
+ instance_id,
+ power_state.NOSTATE,
+ 'pausing')
+ self.driver.pause(instance_ref,
+ lambda result: self._update_state_callback(self,
+ context,
+ instance_id,
+ result))
+
+ @exception.wrap_exception
+ def unpause_instance(self, context, instance_id):
+ """Unpause a paused instance on this server."""
+ context = context.elevated()
+ instance_ref = self.db.instance_get(context, instance_id)
+
+ logging.debug('instance %s: unpausing',
+ instance_ref['internal_id'])
+ self.db.instance_set_state(context,
+ instance_id,
+ power_state.NOSTATE,
+ 'unpausing')
+ self.driver.unpause(instance_ref,
+ lambda result: self._update_state_callback(self,
+ context,
+ instance_id,
+ result))
+
@exception.wrap_exception
def get_console_output(self, context, instance_id):
"""Send the console output for an instance."""