From 35dc27bbcb3a29ae662a0f8ccfed7a0f76a49c13 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Mon, 19 Jul 2010 14:17:43 -0700 Subject: Ask curl to set exit code if resource was not found --- nova/compute/node.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/node.py b/nova/compute/node.py index d681ec661..8f829995b 100644 --- a/nova/compute/node.py +++ b/nova/compute/node.py @@ -450,7 +450,7 @@ class Instance(object): def _fetch_s3_image(self, image, path): url = _image_url('%s/image' % image) - d = self._pool.simpleExecute('curl --silent %s -o %s' % (url, path)) + d = self._pool.simpleExecute('curl --silent --fail %s -o %s' % (url, path)) return d def _fetch_local_image(self, image, path): -- cgit From 63513736b0340efd197a7b905208fa90d63ab260 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 20 Jul 2010 00:32:42 -0700 Subject: Able to boot without kernel or ramdisk. libvirt.xml.template is now a Cheetah template --- nova/compute/libvirt.xml.template | 26 +++++++++++++++----------- nova/compute/node.py | 26 ++++++++++++++++++++++---- 2 files changed, 37 insertions(+), 15 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/libvirt.xml.template b/nova/compute/libvirt.xml.template index a763e8a4d..6fb63feae 100644 --- a/nova/compute/libvirt.xml.template +++ b/nova/compute/libvirt.xml.template @@ -1,31 +1,35 @@ - %(name)s + ${name} - hvm - %(basepath)s/kernel - %(basepath)s/ramdisk + hvm +#if $getVar('kernel', None) + ${kernel} + #if $getVar('ramdisk', None) + ${ramdisk} + #end if root=/dev/vda1 console=ttyS0 +#end if - %(memory_kb)s - %(vcpus)s + ${memory_kb} + ${vcpus} /usr/bin/kvm - + - - + + - + - %(nova)s + ${nova} diff --git a/nova/compute/node.py b/nova/compute/node.py index 8f829995b..7c3b9a677 100644 --- a/nova/compute/node.py +++ b/nova/compute/node.py @@ -34,6 +34,7 @@ from twisted.internet import defer from twisted.internet import task from twisted.application import service +from Cheetah.Template import Template try: import libvirt @@ -312,13 +313,30 @@ class Instance(object): def toXml(self): # TODO(termie): cache? logging.debug("Starting the toXML method") - libvirt_xml = open(FLAGS.libvirt_xml_template).read() + template_contents = open(FLAGS.libvirt_xml_template).read() xml_info = self.datamodel.copy() # TODO(joshua): Make this xml express the attached disks as well # TODO(termie): lazy lazy hack because xml is annoying xml_info['nova'] = json.dumps(self.datamodel.copy()) - libvirt_xml = libvirt_xml % xml_info + + if xml_info['kernel_id']: + xml_info['kernel'] = xml_info['basepath'] + "/kernel" + + if xml_info['ramdisk_id']: + xml_info['ramdisk'] = xml_info['basepath'] + "/ramdisk" + + if xml_info['ramdisk_id'] or xml_info['kernel_id']: + xml_info['disk'] = xml_info['basepath'] + "/disk" + else: + xml_info['disk'] = xml_info['basepath'] + "/disk-raw" + + try: + libvirt_xml = str(Template(template_contents, searchList=[ xml_info ] )) + except Exception as e: + logging.warning("Error running template: %s" % e) + raise + logging.debug("Finished the toXML method") return libvirt_xml @@ -487,9 +505,9 @@ class Instance(object): if not os.path.exists(basepath('disk')): yield _fetch_file(data['image_id'], basepath('disk-raw')) - if not os.path.exists(basepath('kernel')): + if data['kernel_id'] and not os.path.exists(basepath('kernel')): yield _fetch_file(data['kernel_id'], basepath('kernel')) - if not os.path.exists(basepath('ramdisk')): + if data['ramdisk_id'] and not os.path.exists(basepath('ramdisk')): yield _fetch_file(data['ramdisk_id'], basepath('ramdisk')) execute = lambda cmd, input=None: self._pool.simpleExecute(cmd=cmd, -- cgit From 9cf32d6d65035299ecfcb0563cef8ddab3c0ee4c Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 20 Jul 2010 14:25:43 -0700 Subject: Able to set up DNS, and remove udev network rules --- nova/compute/disk.py | 29 +++++++++++++++----- nova/compute/libvirt.xml.template | 1 + nova/compute/network.py | 3 +++ nova/compute/node.py | 57 ++++++++++++++++++++++++++------------- nova/compute/resolv.conf.template | 1 + 5 files changed, 66 insertions(+), 25 deletions(-) create mode 100644 nova/compute/resolv.conf.template (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index 08a22556e..abbbc01c2 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -84,7 +84,7 @@ def partition(infile, outfile, local_bytes=0, local_type='ext2', execute=None): % (infile, outfile, sector_size, primary_first)) @defer.inlineCallbacks -def inject_data(image, key=None, net=None, partition=None, execute=None): +def inject_data(image, key=None, net=None, dns=None, remove_network_udev=False, partition=None, execute=None): """Injects a ssh key and optionally net data into a disk image. it will mount the image as a fully partitioned disk and attempt to inject @@ -93,7 +93,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 = yield execute('sudo losetup -f --show %s' % image) + out, err = yield execute('sudo losetup --find --show %s' % image) if err: raise exception.Error('Could not attach image to loopback: %s' % err) device = out.strip() @@ -107,6 +107,8 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): partition) else: mapped_device = device + + # Configure ext2fs so that it doesn't auto-check every N boots out, err = yield execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device) tmpdir = tempfile.mkdtemp() @@ -123,6 +125,11 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): yield _inject_key_into_fs(key, tmpdir, execute=execute) if net: yield _inject_net_into_fs(net, tmpdir, execute=execute) + if dns: + yield _inject_dns_into_fs(dns, tmpdir, execute=execute) + if remove_network_udev: + yield _remove_network_udev(tmpdir, execute=execute) + finally: # unmount device yield execute('sudo umount %s' % mapped_device) @@ -134,11 +141,11 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): yield execute('sudo kpartx -d %s' % device) finally: # remove loopback - yield execute('sudo losetup -d %s' % device) + yield execute('sudo losetup --detach %s' % device) @defer.inlineCallbacks def _inject_key_into_fs(key, fs, execute=None): - sshdir = os.path.join(os.path.join(fs, 'root'), '.ssh') + sshdir = os.path.join(fs, 'root', '.ssh') yield execute('sudo mkdir -p %s' % sshdir) # existing dir doesn't matter yield execute('sudo chown root %s' % sshdir) yield execute('sudo chmod 700 %s' % sshdir) @@ -147,7 +154,17 @@ def _inject_key_into_fs(key, fs, execute=None): @defer.inlineCallbacks def _inject_net_into_fs(net, fs, execute=None): - netfile = os.path.join(os.path.join(os.path.join( - fs, 'etc'), 'network'), 'interfaces') + netfile = os.path.join(fs, 'etc', 'network', 'interfaces') yield execute('sudo tee %s' % netfile, net) +@defer.inlineCallbacks +def _inject_dns_into_fs(dns, fs, execute=None): + dnsfile = os.path.join(fs, 'etc', 'resolv.conf') + yield execute('sudo tee %s' % dnsfile, dns) + +@defer.inlineCallbacks +def _remove_network_udev(fs, execute=None): + # This is correct for Ubuntu, but might not be right for other distros + rulesfile = os.path.join(fs, 'etc', 'udev', 'rules.d', '70-persistent-net.rules') + yield execute('rm -f %s' % rulesfile) + diff --git a/nova/compute/libvirt.xml.template b/nova/compute/libvirt.xml.template index 6fb63feae..3bfec9b3a 100644 --- a/nova/compute/libvirt.xml.template +++ b/nova/compute/libvirt.xml.template @@ -16,6 +16,7 @@ ${memory_kb} ${vcpus} + /usr/bin/kvm diff --git a/nova/compute/network.py b/nova/compute/network.py index bdb8a22f9..0b24ca7d1 100644 --- a/nova/compute/network.py +++ b/nova/compute/network.py @@ -62,6 +62,9 @@ flags.DEFINE_list('simple_network_ips', ['192.168.0.2'], flags.DEFINE_string('simple_network_template', utils.abspath('compute/interfaces.template'), 'Template file for simple network') +flags.DEFINE_string('simple_network_dns_template', + utils.abspath('compute/resolv.conf.template'), + 'Template file for DNS settings for simple network') flags.DEFINE_string('simple_network_netmask', '255.255.255.0', 'Netmask for simple network') flags.DEFINE_string('simple_network_network', '192.168.0.0', diff --git a/nova/compute/node.py b/nova/compute/node.py index 7c3b9a677..56429b0f0 100644 --- a/nova/compute/node.py +++ b/nova/compute/node.py @@ -505,37 +505,56 @@ class Instance(object): if not os.path.exists(basepath('disk')): yield _fetch_file(data['image_id'], basepath('disk-raw')) - if data['kernel_id'] and not os.path.exists(basepath('kernel')): - yield _fetch_file(data['kernel_id'], basepath('kernel')) - if data['ramdisk_id'] and not os.path.exists(basepath('ramdisk')): - yield _fetch_file(data['ramdisk_id'], basepath('ramdisk')) + + using_kernel = data['kernel_id'] and True + + if using_kernel: + if os.path.exists(basepath('kernel')): + yield _fetch_file(data['kernel_id'], basepath('kernel')) + if data['ramdisk_id'] and not os.path.exists(basepath('ramdisk')): + yield _fetch_file(data['ramdisk_id'], basepath('ramdisk')) execute = lambda cmd, input=None: self._pool.simpleExecute(cmd=cmd, input=input, error_ok=1) + # For now, we assume that if we're not using a kernel, we're using a partitioned disk image + # where the target partition is the first partition + target_partition = None + if not using_kernel: + target_partition = "1" + key = data['key_data'] net = None + dns = None if FLAGS.simple_network: + network_info = { + 'address': data['private_dns_name'], + 'network': FLAGS.simple_network_network, + 'netmask': FLAGS.simple_network_netmask, + 'gateway': FLAGS.simple_network_gateway, + 'broadcast': FLAGS.simple_network_broadcast, + 'dns': FLAGS.simple_network_dns} + with open(FLAGS.simple_network_template) as f: - net = f.read() % {'address': data['private_dns_name'], - 'network': FLAGS.simple_network_network, - 'netmask': FLAGS.simple_network_netmask, - 'gateway': FLAGS.simple_network_gateway, - 'broadcast': FLAGS.simple_network_broadcast, - 'dns': FLAGS.simple_network_dns} - if key or net: + net = f.read() % network_info + + with open(FLAGS.simple_network_dns_template) as f: + dns =str(Template(f.read(), searchList=[ network_info ] )) + + if key or net or dns: logging.info('Injecting data into image %s', data['image_id']) - yield disk.inject_data(basepath('disk-raw'), key, net, execute=execute) - - if os.path.exists(basepath('disk')): - yield self._pool.simpleExecute('rm -f %s' % basepath('disk')) + yield disk.inject_data(basepath('disk-raw'), key=key, net=net, dns=dns, remove_network_udev=True, partition=target_partition, execute=execute) - bytes = (INSTANCE_TYPES[data['instance_type']]['local_gb'] - * 1024 * 1024 * 1024) - yield disk.partition( - basepath('disk-raw'), basepath('disk'), bytes, execute=execute) + if using_kernel: + if os.path.exists(basepath('disk')): + yield self._pool.simpleExecute('rm -f %s' % basepath('disk')) + bytes = (INSTANCE_TYPES[data['instance_type']]['local_gb'] + * 1024 * 1024 * 1024) + yield disk.partition( + basepath('disk-raw'), basepath('disk'), bytes, execute=execute) + @defer.inlineCallbacks @exception.wrap_exception def spawn(self): diff --git a/nova/compute/resolv.conf.template b/nova/compute/resolv.conf.template new file mode 100644 index 000000000..7ddb55190 --- /dev/null +++ b/nova/compute/resolv.conf.template @@ -0,0 +1 @@ +nameserver ${dns} -- cgit From 5bb1d8d5ab8581696a98a159b293b992e72eec49 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Tue, 20 Jul 2010 14:31:55 -0700 Subject: Cleanups --- nova/compute/node.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/node.py b/nova/compute/node.py index 56429b0f0..ba140a219 100644 --- a/nova/compute/node.py +++ b/nova/compute/node.py @@ -509,7 +509,7 @@ class Instance(object): using_kernel = data['kernel_id'] and True if using_kernel: - if os.path.exists(basepath('kernel')): + if not os.path.exists(basepath('kernel')): yield _fetch_file(data['kernel_id'], basepath('kernel')) if data['ramdisk_id'] and not os.path.exists(basepath('ramdisk')): yield _fetch_file(data['ramdisk_id'], basepath('ramdisk')) @@ -540,7 +540,7 @@ class Instance(object): net = f.read() % network_info with open(FLAGS.simple_network_dns_template) as f: - dns =str(Template(f.read(), searchList=[ network_info ] )) + dns = str(Template(f.read(), searchList=[ network_info ] )) if key or net or dns: logging.info('Injecting data into image %s', data['image_id']) -- cgit From 6c32e87c1be80230cf058586cee5a94cd25670b8 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Sat, 31 Jul 2010 21:35:58 -0700 Subject: Fixed up some of the raw disk stuff that broke in the abstraction out of libvirt --- nova/compute/disk.py | 3 +++ 1 file changed, 3 insertions(+) (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index 848ce8b54..cace849fa 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -109,6 +109,9 @@ def inject_data(image, key=None, net=None, dns=None, remove_network_udev=False, else: mapped_device = device + if not os.path.exists(mapped_device): + raise exception.Error('Mapped device was not found: %s' % mapped_device) + # Configure ext2fs so that it doesn't auto-check every N boots out, err = yield execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device) -- cgit From 759bab6059ef2e4c463a73e12fe85fe4b147eba7 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Sat, 21 Aug 2010 13:07:03 +0100 Subject: Clarified what the 'Mapped device not found' exception really means. Fixed TODO. Some formatting to be closer to 80 chars --- nova/compute/disk.py | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index 6099eb4ba..4ede9a7aa 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -87,7 +87,9 @@ def partition(infile, outfile, local_bytes=0, local_type='ext2', execute=None): @defer.inlineCallbacks -def inject_data(image, key=None, net=None, dns=None, remove_network_udev=False, partition=None, execute=None): +def inject_data( image, key=None, net=None, dns=None, + remove_network_udev=False, + partition=None, execute=None): """Injects a ssh key and optionally net data into a disk image. it will mount the image as a fully partitioned disk and attempt to inject @@ -111,8 +113,12 @@ def inject_data(image, key=None, net=None, dns=None, remove_network_udev=False, 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: %s' % 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 = yield execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device) @@ -172,7 +178,9 @@ def _inject_dns_into_fs(dns, fs, execute=None): @defer.inlineCallbacks def _remove_network_udev(fs, execute=None): - # This is correct for Ubuntu, but might not be right for other distros + # TODO(justinsb): This is correct for Ubuntu, but might not be right for + # other distros. There is a much bigger discussion to be had about what + # we inject and how we inject it. rulesfile = os.path.join(fs, 'etc', 'udev', 'rules.d', '70-persistent-net.rules') yield execute('rm -f %s' % rulesfile) -- cgit From 9732c0af89f21490cc8d6bc80799bbc8b36fb441 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 14 Oct 2010 13:38:35 -0700 Subject: Minimized diff, fixed formatting --- nova/compute/disk.py | 22 +--------------------- nova/compute/resolv.conf.template | 1 - 2 files changed, 1 insertion(+), 22 deletions(-) delete mode 100644 nova/compute/resolv.conf.template (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index 4ede9a7aa..b1ddb0a1f 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -87,9 +87,7 @@ def partition(infile, outfile, local_bytes=0, local_type='ext2', execute=None): @defer.inlineCallbacks -def inject_data( image, key=None, net=None, dns=None, - remove_network_udev=False, - partition=None, execute=None): +def inject_data(image, key=None, net=None, partition=None, execute=None): """Injects a ssh key and optionally net data into a disk image. it will mount the image as a fully partitioned disk and attempt to inject @@ -137,11 +135,6 @@ def inject_data( image, key=None, net=None, dns=None, yield _inject_key_into_fs(key, tmpdir, execute=execute) if net: yield _inject_net_into_fs(net, tmpdir, execute=execute) - if dns: - yield _inject_dns_into_fs(dns, tmpdir, execute=execute) - if remove_network_udev: - yield _remove_network_udev(tmpdir, execute=execute) - finally: # unmount device yield execute('sudo umount %s' % mapped_device) @@ -171,16 +164,3 @@ def _inject_net_into_fs(net, fs, execute=None): netfile = os.path.join(fs, 'etc', 'network', 'interfaces') yield execute('sudo tee %s' % netfile, net) -@defer.inlineCallbacks -def _inject_dns_into_fs(dns, fs, execute=None): - dnsfile = os.path.join(fs, 'etc', 'resolv.conf') - yield execute('sudo tee %s' % dnsfile, dns) - -@defer.inlineCallbacks -def _remove_network_udev(fs, execute=None): - # TODO(justinsb): This is correct for Ubuntu, but might not be right for - # other distros. There is a much bigger discussion to be had about what - # we inject and how we inject it. - rulesfile = os.path.join(fs, 'etc', 'udev', 'rules.d', '70-persistent-net.rules') - yield execute('rm -f %s' % rulesfile) - diff --git a/nova/compute/resolv.conf.template b/nova/compute/resolv.conf.template deleted file mode 100644 index 7ddb55190..000000000 --- a/nova/compute/resolv.conf.template +++ /dev/null @@ -1 +0,0 @@ -nameserver ${dns} -- cgit From 2337fab0979b72bbc7e7730e94518a0e835a2751 Mon Sep 17 00:00:00 2001 From: Andy Smith Date: Mon, 25 Oct 2010 03:45:19 +0900 Subject: part way through porting the codebase off of twisted this provides a very basic eventlet-based service replacement for the twistd-based services, a replacement for task.LoopingCall also adds nova-combined with the goal of running a single service when doing local testing and dev --- nova/compute/disk.py | 66 ++++++++++++++++++++++--------------------------- nova/compute/manager.py | 28 ++++++++------------- 2 files changed, 40 insertions(+), 54 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index e362b4507..ad4c2c092 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -25,8 +25,6 @@ import logging import os import tempfile -from twisted.internet import defer - from nova import exception from nova import flags @@ -38,7 +36,6 @@ flags.DEFINE_integer('block_size', 1024 * 1024 * 256, 'block_size to use for dd') -@defer.inlineCallbacks def partition(infile, outfile, local_bytes=0, resize=True, local_type='ext2', execute=None): """Takes a single partition represented by infile and writes a bootable @@ -60,10 +57,10 @@ def partition(infile, outfile, local_bytes=0, resize=True, file_size = os.path.getsize(infile) if resize and file_size < FLAGS.minimum_root_size: last_sector = FLAGS.minimum_root_size / sector_size - 1 - yield execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d' - % (infile, last_sector, sector_size)) - yield execute('e2fsck -fp %s' % infile, check_exit_code=False) - yield execute('resize2fs %s' % infile) + execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d' + % (infile, last_sector, sector_size)) + execute('e2fsck -fp %s' % infile, check_exit_code=False) + execute('resize2fs %s' % infile) file_size = FLAGS.minimum_root_size elif file_size % sector_size != 0: logging.warn("Input partition size not evenly divisible by" @@ -82,30 +79,29 @@ def partition(infile, outfile, local_bytes=0, resize=True, last_sector = local_last # e # create an empty file - yield execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d' - % (outfile, mbr_last, sector_size)) + execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d' + % (outfile, mbr_last, sector_size)) # make mbr partition - yield execute('parted --script %s mklabel msdos' % outfile) + execute('parted --script %s mklabel msdos' % outfile) # append primary file - yield execute('dd if=%s of=%s bs=%s conv=notrunc,fsync oflag=append' - % (infile, outfile, FLAGS.block_size)) + execute('dd if=%s of=%s bs=%s conv=notrunc,fsync oflag=append' + % (infile, outfile, FLAGS.block_size)) # make primary partition - yield execute('parted --script %s mkpart primary %ds %ds' - % (outfile, primary_first, primary_last)) + execute('parted --script %s mkpart primary %ds %ds' + % (outfile, primary_first, primary_last)) if local_bytes > 0: # make the file bigger - yield execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d' - % (outfile, last_sector, sector_size)) + execute('dd if=/dev/zero of=%s count=1 seek=%d bs=%d' + % (outfile, last_sector, sector_size)) # make and format local partition - yield execute('parted --script %s mkpartfs primary %s %ds %ds' - % (outfile, local_type, local_first, local_last)) + execute('parted --script %s mkpartfs primary %s %ds %ds' + % (outfile, local_type, local_first, local_last)) -@defer.inlineCallbacks 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,26 +111,26 @@ 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 = yield execute('sudo losetup -f --show %s' % image) + out, err = execute('sudo losetup -f --show %s' % image) if err: raise exception.Error('Could not attach image to loopback: %s' % err) device = out.strip() try: if not partition is None: # create partition - out, err = yield execute('sudo kpartx -a %s' % device) + out, err = execute('sudo kpartx -a %s' % device) if err: raise exception.Error('Failed to load partition: %s' % err) mapped_device = '/dev/mapper/%sp%s' % (device.split('/')[-1], partition) else: mapped_device = device - out, err = yield execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device) + out, err = execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device) tmpdir = tempfile.mkdtemp() try: # mount loopback to dir - out, err = yield execute( + out, err = execute( 'sudo mount %s %s' % (mapped_device, tmpdir)) if err: raise exception.Error('Failed to mount filesystem: %s' % err) @@ -142,35 +138,33 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): try: if key: # inject key file - yield _inject_key_into_fs(key, tmpdir, execute=execute) + _inject_key_into_fs(key, tmpdir, execute=execute) if net: - yield _inject_net_into_fs(net, tmpdir, execute=execute) + _inject_net_into_fs(net, tmpdir, execute=execute) finally: # unmount device - yield execute('sudo umount %s' % mapped_device) + execute('sudo umount %s' % mapped_device) finally: # remove temporary directory - yield execute('rmdir %s' % tmpdir) + execute('rmdir %s' % tmpdir) if not partition is None: # remove partitions - yield execute('sudo kpartx -d %s' % device) + execute('sudo kpartx -d %s' % device) finally: # remove loopback - yield execute('sudo losetup -d %s' % device) + execute('sudo losetup -d %s' % device) -@defer.inlineCallbacks def _inject_key_into_fs(key, fs, execute=None): sshdir = os.path.join(os.path.join(fs, 'root'), '.ssh') - yield execute('sudo mkdir -p %s' % sshdir) # existing dir doesn't matter - yield execute('sudo chown root %s' % sshdir) - yield execute('sudo chmod 700 %s' % sshdir) + execute('sudo mkdir -p %s' % sshdir) # existing dir doesn't matter + execute('sudo chown root %s' % sshdir) + execute('sudo chmod 700 %s' % sshdir) keyfile = os.path.join(sshdir, 'authorized_keys') - yield execute('sudo tee -a %s' % keyfile, '\n' + key.strip() + '\n') + execute('sudo tee -a %s' % keyfile, '\n' + key.strip() + '\n') -@defer.inlineCallbacks def _inject_net_into_fs(net, fs, execute=None): netfile = os.path.join(os.path.join(os.path.join( fs, 'etc'), 'network'), 'interfaces') - yield execute('sudo tee %s' % netfile, net) + execute('sudo tee %s' % netfile, net) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 523bb8893..a105a1dd0 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -25,8 +25,6 @@ import datetime import logging import os -from twisted.internet import defer - from nova import exception from nova import flags from nova import manager @@ -54,7 +52,7 @@ class ComputeManager(manager.Manager): self.network_manager = utils.import_object(FLAGS.network_manager) self.volume_manager = utils.import_object(FLAGS.volume_manager) super(ComputeManager, self).__init__(*args, **kwargs) - + def _update_state(self, context, instance_id): """Update the state of an instance from the driver info""" # FIXME(ja): include other fields from state? @@ -62,12 +60,10 @@ class ComputeManager(manager.Manager): state = self.driver.get_info(instance_ref.name)['state'] self.db.instance_set_state(context, instance_id, state) - @defer.inlineCallbacks @exception.wrap_exception def refresh_security_group(self, context, security_group_id, **_kwargs): - yield self.driver.refresh_security_group(security_group_id) + self.driver.refresh_security_group(security_group_id) - @defer.inlineCallbacks @exception.wrap_exception def run_instance(self, context, instance_id, **_kwargs): """Launch a new instance with specified options.""" @@ -89,7 +85,7 @@ class ComputeManager(manager.Manager): 'spawning') try: - yield self.driver.spawn(instance_ref) + self.driver.spawn(instance_ref) now = datetime.datetime.utcnow() self.db.instance_update(context, instance_id, @@ -103,7 +99,6 @@ class ComputeManager(manager.Manager): self._update_state(context, instance_id) - @defer.inlineCallbacks @exception.wrap_exception def terminate_instance(self, context, instance_id): """Terminate an instance on this machine.""" @@ -116,12 +111,11 @@ class ComputeManager(manager.Manager): raise exception.Error('trying to destroy already destroyed' ' instance: %s' % instance_id) - yield self.driver.destroy(instance_ref) + self.driver.destroy(instance_ref) # TODO(ja): should we keep it in a terminated state for a bit? self.db.instance_destroy(context, instance_id) - @defer.inlineCallbacks @exception.wrap_exception def reboot_instance(self, context, instance_id): """Reboot an instance on this server.""" @@ -142,7 +136,7 @@ class ComputeManager(manager.Manager): instance_id, power_state.NOSTATE, 'rebooting') - yield self.driver.reboot(instance_ref) + self.driver.reboot(instance_ref) self._update_state(context, instance_id) @exception.wrap_exception @@ -154,7 +148,6 @@ class ComputeManager(manager.Manager): return self.driver.get_console_output(instance_ref) - @defer.inlineCallbacks @exception.wrap_exception def attach_volume(self, context, instance_id, volume_id, mountpoint): """Attach a volume to an instance.""" @@ -164,13 +157,12 @@ class ComputeManager(manager.Manager): instance_ref = self.db.instance_get(context, instance_id) dev_path = yield self.volume_manager.setup_compute_volume(context, volume_id) - yield self.driver.attach_volume(instance_ref['ec2_id'], - dev_path, - mountpoint) + self.driver.attach_volume(instance_ref['ec2_id'], + dev_path, + mountpoint) self.db.volume_attached(context, volume_id, instance_id, mountpoint) defer.returnValue(True) - @defer.inlineCallbacks @exception.wrap_exception def detach_volume(self, context, instance_id, volume_id): """Detach a volume from an instance.""" @@ -180,7 +172,7 @@ class ComputeManager(manager.Manager): volume_id) instance_ref = self.db.instance_get(context, instance_id) volume_ref = self.db.volume_get(context, volume_id) - yield self.driver.detach_volume(instance_ref['ec2_id'], - volume_ref['mountpoint']) + self.driver.detach_volume(instance_ref['ec2_id'], + volume_ref['mountpoint']) self.db.volume_detached(context, volume_id) defer.returnValue(True) -- cgit From 4b74a1b243d87d53e660029728d12a9c067deeac Mon Sep 17 00:00:00 2001 From: Rick Clark Date: Tue, 30 Nov 2010 13:08:39 -0600 Subject: Cleaned up pep8 errors --- nova/compute/disk.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index d5a08c01f..d762b8087 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -137,9 +137,9 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): # 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) + 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 = yield execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device) -- cgit From ffa41022463c23a67dda2a6de74b6d5203cb37ac Mon Sep 17 00:00:00 2001 From: Rick Clark Date: Tue, 30 Nov 2010 16:09:31 -0600 Subject: Fixed termie's tiny bits from the prior merge request --- nova/compute/disk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index d762b8087..9ba827519 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -134,8 +134,8 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): 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 + # 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' % -- cgit From 5f72a004dee0cb8de3f2daee1976fa978f6e51f3 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 9 Dec 2010 16:41:35 +0000 Subject: pause from compute.manager <-> xenapi --- nova/compute/manager.py | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index dd8d41129..c0339a71f 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -194,6 +194,38 @@ class ComputeManager(manager.Manager): yield self.driver.unrescue(instance_ref) self._update_state(context, instance_id) + @defer.inlineCallbacks + @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') + yield self.driver.pause(instance_ref) + self._update_state(context, instance_id) + + @defer.inlineCallbacks + @exception.wrap_exception + def resume_instance(self, context, instance_id): + """Resume a paused instance on this server.""" + context = context.elevated() + instance_ref = self.db.instance_get(context, instance_id) + + logging.debug('instance %s: resuming', + instance_ref['internal_id']) + self.db.instance_set_state(context, + instance_id, + power_state.NOSTATE, + 'resume') + yield self.driver.resume(instance_ref) + self._update_state(context, instance_id) + @exception.wrap_exception def get_console_output(self, context, instance_id): """Send the console output for an instance.""" -- cgit From 294102984964e8853fcaf32485c273cbdcc7748a Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 9 Dec 2010 17:54:30 +0000 Subject: changed resume to unpause --- nova/compute/manager.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index c0339a71f..61ed3136b 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -212,18 +212,18 @@ class ComputeManager(manager.Manager): @defer.inlineCallbacks @exception.wrap_exception - def resume_instance(self, context, instance_id): - """Resume a paused instance on this server.""" + 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: resuming', + logging.debug('instance %s: unpausing', instance_ref['internal_id']) self.db.instance_set_state(context, instance_id, power_state.NOSTATE, - 'resume') - yield self.driver.resume(instance_ref) + 'unpausing') + yield self.driver.unpause(instance_ref) self._update_state(context, instance_id) @exception.wrap_exception -- cgit From 90c89f5f7b24bb6c95d405d42f7f15292b5452a9 Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 9 Dec 2010 17:03:49 -0400 Subject: pause and unpause code/tests in place. To the point it stuffs request in the queue. --- nova/compute/api.py | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 8e0efa4cc..e25e6cc78 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -275,6 +275,27 @@ class ComputeAPI(base.Base): {"method": "reboot_instance", "args": {"instance_id": instance['id']}}) + def pause(self, context, instance_id): + """Pause the given instance.""" + logging.debug("IN PAUSE - 1") + instance = self.db.instance_get_by_internal_id(context, instance_id) + logging.debug("IN PAUSE - 2") + 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) -- cgit From 54e4174a0b6a3c1dd4105617b06bb7a69f45202c Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Thu, 9 Dec 2010 17:32:27 -0400 Subject: remove debug messages --- nova/compute/api.py | 2 -- 1 file changed, 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index e25e6cc78..79da79cd1 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -277,9 +277,7 @@ class ComputeAPI(base.Base): def pause(self, context, instance_id): """Pause the given instance.""" - logging.debug("IN PAUSE - 1") instance = self.db.instance_get_by_internal_id(context, instance_id) - logging.debug("IN PAUSE - 2") host = instance['host'] rpc.cast(context, self.db.queue_get_for(context, FLAGS.compute_topic, host), -- cgit From 12802a76c775a35e9d5a651bf896cfa25bec547f Mon Sep 17 00:00:00 2001 From: "jaypipes@gmail.com" <> Date: Sat, 11 Dec 2010 15:23:40 -0500 Subject: First round of i18n-ifying strings in Nova --- nova/compute/api.py | 12 ++++++------ nova/compute/disk.py | 16 +++++++++------- nova/compute/instance_types.py | 2 +- nova/compute/manager.py | 32 ++++++++++++++++---------------- nova/compute/monitor.py | 12 ++++++------ 5 files changed, 38 insertions(+), 36 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 8e0efa4cc..e701e540e 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -120,7 +120,7 @@ class ComputeAPI(base.Base): elevated = context.elevated() instances = [] - logging.debug("Going to run %s instances...", num_instances) + logging.debug(_("Going to run %s instances..."), num_instances) for num in range(num_instances): instance = dict(mac_address=utils.generate_mac(), launch_index=num, @@ -157,7 +157,7 @@ class ComputeAPI(base.Base): {"method": "setup_fixed_ip", "args": {"address": address}}) - logging.debug("Casting to scheduler for %s/%s's instance %s", + logging.debug(_("Casting to scheduler for %s/%s's instance %s"), context.project_id, context.user_id, instance_id) rpc.cast(context, FLAGS.scheduler_topic, @@ -204,12 +204,12 @@ class ComputeAPI(base.Base): instance = self.db.instance_get_by_internal_id(context, instance_id) except exception.NotFound as e: - logging.warning("Instance %d was not found during terminate", + logging.warning(_("Instance %d 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 %d is already being terminated"), instance_id) return @@ -223,7 +223,7 @@ class ComputeAPI(base.Base): address = self.db.instance_get_floating_address(context, instance['id']) if address: - logging.debug("Disassociating address %s" % address) + logging.debug(_("Disassociating address %s") % address) # NOTE(vish): Right now we don't really care if the ip is # disassociated. We may need to worry about # checking this later. Perhaps in the scheduler? @@ -234,7 +234,7 @@ class ComputeAPI(base.Base): address = self.db.instance_get_fixed_address(context, instance['id']) if address: - logging.debug("Deallocating address %s" % address) + logging.debug(_("Deallocating address %s") % address) # NOTE(vish): Currently, nothing needs to be done on the # network node until release. If this changes, # we will need to cast here. diff --git a/nova/compute/disk.py b/nova/compute/disk.py index 4338d39f0..8701c3968 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -70,12 +70,12 @@ def partition(infile, outfile, local_bytes=0, resize=True, yield execute('resize2fs %s' % infile) file_size = FLAGS.minimum_root_size elif file_size % sector_size != 0: - logging.warn("Input partition size not evenly divisible by" - " sector size: %d / %d", file_size, sector_size) + logging.warn(_("Input partition size not evenly divisible by" + " sector size: %d / %d"), file_size, sector_size) primary_sectors = file_size / sector_size if local_bytes % sector_size != 0: - logging.warn("Bytes for local storage not evenly divisible" - " by sector size: %d / %d", local_bytes, sector_size) + logging.warn(_("Bytes for local storage not evenly divisible" + " by sector size: %d / %d"), local_bytes, sector_size) local_sectors = local_bytes / sector_size mbr_last = 62 # a @@ -121,14 +121,15 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): """ out, err = yield execute('sudo losetup -f --show %s' % image) if err: - raise exception.Error('Could not attach image to loopback: %s' % err) + raise exception.Error(_('Could not attach image to loopback: %s') + % err) device = out.strip() try: if not partition is None: # create partition out, err = yield execute('sudo kpartx -a %s' % device) if err: - raise exception.Error('Failed to load partition: %s' % err) + raise exception.Error(_('Failed to load partition: %s') % err) mapped_device = '/dev/mapper/%sp%s' % (device.split('/')[-1], partition) else: @@ -141,7 +142,8 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): out, err = yield execute( 'sudo mount %s %s' % (mapped_device, tmpdir)) if err: - raise exception.Error('Failed to mount filesystem: %s' % err) + raise exception.Error(_('Failed to mount filesystem: %s') + % err) try: if key: diff --git a/nova/compute/instance_types.py b/nova/compute/instance_types.py index a2679e0fc..000b3a6d9 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -37,7 +37,7 @@ def get_by_type(instance_type): if instance_type is None: return FLAGS.default_instance_type if instance_type not in INSTANCE_TYPES: - raise exception.ApiError("Unknown instance type: %s", + raise exception.ApiError(_("Unknown instance type: %s"), instance_type) return instance_type diff --git a/nova/compute/manager.py b/nova/compute/manager.py index dd8d41129..a63ad5e1b 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -91,8 +91,8 @@ class ComputeManager(manager.Manager): context = context.elevated() instance_ref = self.db.instance_get(context, instance_id) if instance_ref['name'] in self.driver.list_instances(): - raise exception.Error("Instance has already been created") - logging.debug("instance %s: starting...", instance_id) + raise exception.Error(_("Instance has already been created")) + logging.debug(_("instance %s: starting..."), instance_id) self.network_manager.setup_compute_network(context, instance_id) self.db.instance_update(context, instance_id, @@ -111,7 +111,7 @@ class ComputeManager(manager.Manager): instance_id, {'launched_at': now}) except Exception: # pylint: disable-msg=W0702 - logging.exception("instance %s: Failed to spawn", + logging.exception(_("instance %s: Failed to spawn"), instance_ref['name']) self.db.instance_set_state(context, instance_id, @@ -124,7 +124,7 @@ class ComputeManager(manager.Manager): def terminate_instance(self, context, instance_id): """Terminate an instance on this machine.""" context = context.elevated() - logging.debug("instance %s: terminating", instance_id) + logging.debug(_("instance %s: terminating"), instance_id) instance_ref = self.db.instance_get(context, instance_id) volumes = instance_ref.get('volumes', []) or [] @@ -132,8 +132,8 @@ class ComputeManager(manager.Manager): self.detach_volume(context, instance_id, volume['id']) if instance_ref['state'] == power_state.SHUTOFF: self.db.instance_destroy(context, instance_id) - raise exception.Error('trying to destroy already destroyed' - ' instance: %s' % instance_id) + raise exception.Error(_('trying to destroy already destroyed' + ' instance: %s') % instance_id) yield self.driver.destroy(instance_ref) # TODO(ja): should we keep it in a terminated state for a bit? @@ -148,13 +148,13 @@ class ComputeManager(manager.Manager): self._update_state(context, instance_id) if instance_ref['state'] != power_state.RUNNING: - logging.warn('trying to reboot a non-running ' - 'instance: %s (state: %s excepted: %s)', + logging.warn(_('trying to reboot a non-running ' + 'instance: %s (state: %s excepted: %s)'), instance_ref['internal_id'], instance_ref['state'], power_state.RUNNING) - logging.debug('instance %s: rebooting', instance_ref['name']) + logging.debug(_('instance %s: rebooting'), instance_ref['name']) self.db.instance_set_state(context, instance_id, power_state.NOSTATE, @@ -169,7 +169,7 @@ class ComputeManager(manager.Manager): context = context.elevated() instance_ref = self.db.instance_get(context, instance_id) - logging.debug('instance %s: rescuing', + logging.debug(_('instance %s: rescuing'), instance_ref['internal_id']) self.db.instance_set_state(context, instance_id, @@ -185,7 +185,7 @@ class ComputeManager(manager.Manager): context = context.elevated() instance_ref = self.db.instance_get(context, instance_id) - logging.debug('instance %s: unrescuing', + logging.debug(_('instance %s: unrescuing'), instance_ref['internal_id']) self.db.instance_set_state(context, instance_id, @@ -198,7 +198,7 @@ class ComputeManager(manager.Manager): def get_console_output(self, context, instance_id): """Send the console output for an instance.""" context = context.elevated() - logging.debug("instance %s: getting console output", instance_id) + logging.debug(_("instance %s: getting console output"), instance_id) instance_ref = self.db.instance_get(context, instance_id) return self.driver.get_console_output(instance_ref) @@ -208,7 +208,7 @@ class ComputeManager(manager.Manager): def attach_volume(self, context, instance_id, volume_id, mountpoint): """Attach a volume to an instance.""" context = context.elevated() - logging.debug("instance %s: attaching volume %s to %s", instance_id, + logging.debug(_("instance %s: attaching volume %s to %s"), instance_id, volume_id, mountpoint) instance_ref = self.db.instance_get(context, instance_id) dev_path = yield self.volume_manager.setup_compute_volume(context, @@ -225,7 +225,7 @@ class ComputeManager(manager.Manager): # NOTE(vish): The inline callback eats the exception info so we # log the traceback here and reraise the same # ecxception below. - logging.exception("instance %s: attach failed %s, removing", + logging.exception(_("instance %s: attach failed %s, removing"), instance_id, mountpoint) yield self.volume_manager.remove_compute_volume(context, volume_id) @@ -237,13 +237,13 @@ class ComputeManager(manager.Manager): def detach_volume(self, context, instance_id, volume_id): """Detach a volume from an instance.""" context = context.elevated() - logging.debug("instance %s: detaching volume %s", + logging.debug(_("instance %s: detaching volume %s"), instance_id, volume_id) instance_ref = self.db.instance_get(context, instance_id) volume_ref = self.db.volume_get(context, volume_id) if instance_ref['name'] not in self.driver.list_instances(): - logging.warn("Detaching volume from unknown instance %s", + logging.warn(_("Detaching volume from unknown instance %s"), instance_ref['name']) else: yield self.driver.detach_volume(instance_ref['name'], diff --git a/nova/compute/monitor.py b/nova/compute/monitor.py index 22653113a..60c347a5e 100644 --- a/nova/compute/monitor.py +++ b/nova/compute/monitor.py @@ -255,7 +255,7 @@ class Instance(object): Updates the instances statistics and stores the resulting graphs in the internal object store on the cloud controller. """ - logging.debug('updating %s...', self.instance_id) + logging.debug(_('updating %s...'), self.instance_id) try: data = self.fetch_cpu_stats() @@ -285,7 +285,7 @@ class Instance(object): graph_disk(self, '1w') graph_disk(self, '1m') except Exception: - logging.exception('unexpected error during update') + logging.exception(_('unexpected error during update')) self.last_updated = utcnow() @@ -351,7 +351,7 @@ class Instance(object): rd += rd_bytes wr += wr_bytes except TypeError: - logging.error('Cannot get blockstats for "%s" on "%s"', + logging.error(_('Cannot get blockstats for "%s" on "%s"'), disk, self.instance_id) raise @@ -373,7 +373,7 @@ class Instance(object): rx += stats[0] tx += stats[4] except TypeError: - logging.error('Cannot get ifstats for "%s" on "%s"', + logging.error(_('Cannot get ifstats for "%s" on "%s"'), interface, self.instance_id) raise @@ -408,7 +408,7 @@ class InstanceMonitor(object, service.Service): try: conn = virt_connection.get_connection(read_only=True) except Exception, exn: - logging.exception('unexpected exception getting connection') + logging.exception(_('unexpected exception getting connection')) time.sleep(FLAGS.monitoring_instances_delay) return @@ -423,7 +423,7 @@ class InstanceMonitor(object, service.Service): if not domain_id in self._instances: instance = Instance(conn, domain_id) self._instances[domain_id] = instance - logging.debug('Found instance: %s', domain_id) + logging.debug(_('Found instance: %s'), domain_id) for key in self._instances.keys(): instance = self._instances[key] -- cgit From 1395d31badc43bdce036e8da3927af22a22ca91e Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Mon, 13 Dec 2010 18:25:17 -0800 Subject: Fixed power state update with Twisted callback --- nova/compute/manager.py | 21 +++++++++++++++++---- 1 file changed, 17 insertions(+), 4 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 61ed3136b..ae33fe5b9 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -194,6 +194,13 @@ class ComputeManager(manager.Manager): yield 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 Deferred task completes. + This staticmethod must be wrappered in a + lambda to pass in self, context & instance_id.""" + self._update_state(context, instance_id) + @defer.inlineCallbacks @exception.wrap_exception def pause_instance(self, context, instance_id): @@ -207,8 +214,11 @@ class ComputeManager(manager.Manager): instance_id, power_state.NOSTATE, 'pausing') - yield self.driver.pause(instance_ref) - self._update_state(context, instance_id) + yield self.driver.pause(instance_ref, + lambda result : self._update_state_callback(self, + context, + instance_id, + result)) @defer.inlineCallbacks @exception.wrap_exception @@ -223,8 +233,11 @@ class ComputeManager(manager.Manager): instance_id, power_state.NOSTATE, 'unpausing') - yield self.driver.unpause(instance_ref) - self._update_state(context, instance_id) + yield 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): -- cgit From fa7d288e6af3d997d6275d9e6778e932be9f1c3f Mon Sep 17 00:00:00 2001 From: Sandy Walsh Date: Tue, 14 Dec 2010 17:56:42 -0400 Subject: pep8 --- nova/compute/api.py | 1 - nova/compute/manager.py | 18 ++++++++---------- 2 files changed, 8 insertions(+), 11 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 79da79cd1..7420c40d2 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -293,7 +293,6 @@ class ComputeAPI(base.Base): {"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/manager.py b/nova/compute/manager.py index ae33fe5b9..0c0ba7450 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -196,9 +196,7 @@ class ComputeManager(manager.Manager): @staticmethod def _update_state_callback(self, context, instance_id, result): - """Update instance state when Deferred task completes. - This staticmethod must be wrappered in a - lambda to pass in self, context & instance_id.""" + """Update instance state when Deferred task completes.""" self._update_state(context, instance_id) @defer.inlineCallbacks @@ -214,10 +212,10 @@ class ComputeManager(manager.Manager): instance_id, power_state.NOSTATE, 'pausing') - yield self.driver.pause(instance_ref, - lambda result : self._update_state_callback(self, - context, - instance_id, + yield self.driver.pause(instance_ref, + lambda result: self._update_state_callback(self, + context, + instance_id, result)) @defer.inlineCallbacks @@ -234,9 +232,9 @@ class ComputeManager(manager.Manager): power_state.NOSTATE, 'unpausing') yield self.driver.unpause(instance_ref, - lambda result : self._update_state_callback(self, - context, - instance_id, + lambda result: self._update_state_callback(self, + context, + instance_id, result)) @exception.wrap_exception -- cgit From aab6a89ba1e9ace73dcb4fa68a67957e29c47f84 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 14 Dec 2010 23:34:08 +0100 Subject: Don't attempt to fiddle with partitions for whole-disk-images. --- nova/compute/disk.py | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index 9ba827519..a77c30a19 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -108,6 +108,13 @@ def partition(infile, outfile, local_bytes=0, resize=True, yield execute('parted --script %s mkpartfs primary %s %ds %ds' % (outfile, local_type, local_first, local_last)) +@defer.inlineCallbacks +def extend(image, size, execute): + file_size = os.path.getsize(image) + if file_size >= size: + return + yield execute('truncate -s size %s' % (image,)) + @defer.inlineCallbacks def inject_data(image, key=None, net=None, partition=None, execute=None): -- cgit From a2a8406b5d793545c8ecb359e18b80bba618c509 Mon Sep 17 00:00:00 2001 From: termie Date: Tue, 14 Dec 2010 16:05:39 -0800 Subject: updates per review --- nova/compute/manager.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 051ce579d..f90f28b78 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -203,7 +203,7 @@ class ComputeManager(manager.Manager): volume_id, mountpoint) instance_ref = self.db.instance_get(context, instance_id) dev_path = self.volume_manager.setup_compute_volume(context, - volume_id) + volume_id) try: self.driver.attach_volume(instance_ref['name'], dev_path, @@ -238,7 +238,7 @@ class ComputeManager(manager.Manager): instance_ref['name']) else: self.driver.detach_volume(instance_ref['name'], - volume_ref['mountpoint']) + volume_ref['mountpoint']) self.volume_manager.remove_compute_volume(context, volume_id) self.db.volume_detached(context, volume_id) return True -- cgit From 9b049acc27d477a1ab9e13c9e064e59d8bd0a3ae Mon Sep 17 00:00:00 2001 From: termie Date: Thu, 16 Dec 2010 10:52:30 -0800 Subject: pep8 fixes --- nova/compute/manager.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index f90f28b78..7eb60e262 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -64,7 +64,7 @@ class ComputeManager(manager.Manager): self.network_manager = utils.import_object(FLAGS.network_manager) self.volume_manager = utils.import_object(FLAGS.volume_manager) super(ComputeManager, self).__init__(*args, **kwargs) - + def _update_state(self, context, instance_id): """Update the state of an instance from the driver info.""" # FIXME(ja): include other fields from state? -- cgit From e91590145962827e68bbb3518990d7d94e99608d Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 20 Dec 2010 20:37:56 +0100 Subject: PEP8 fixups --- nova/compute/disk.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nova/compute') diff --git a/nova/compute/disk.py b/nova/compute/disk.py index 3d5e07724..0169a9831 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -105,12 +105,14 @@ def partition(infile, outfile, local_bytes=0, resize=True, execute('parted --script %s mkpartfs primary %s %ds %ds' % (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. -- cgit From de383023e4d5c30d3ad4474af104f6b659e1bd32 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Mon, 20 Dec 2010 21:04:54 +0000 Subject: directly copy ip allocation into compute --- nova/compute/api.py | 44 --------------------------------------- nova/compute/manager.py | 55 +++++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 53 insertions(+), 46 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 8e0efa4cc..2dae9cdbc 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -145,18 +145,6 @@ class ComputeAPI(base.Base): instance = self.update_instance(context, instance_id, **updates) instances.append(instance) - # TODO(vish): This probably should be done in the scheduler - # or in compute as a call. The network should be - # allocated after the host is assigned and setup - # can happen at the same time. - address = self.network_manager.allocate_fixed_ip(context, - instance_id, - is_vpn) - rpc.cast(elevated, - self._get_network_topic(context), - {"method": "setup_fixed_ip", - "args": {"address": address}}) - logging.debug("Casting to scheduler for %s/%s's instance %s", context.project_id, context.user_id, instance_id) rpc.cast(context, @@ -219,28 +207,6 @@ class ComputeAPI(base.Base): state=0, terminated_at=datetime.datetime.utcnow()) - # FIXME(ja): where should network deallocate occur? - address = self.db.instance_get_floating_address(context, - instance['id']) - if address: - logging.debug("Disassociating address %s" % address) - # NOTE(vish): Right now we don't really care if the ip is - # disassociated. We may need to worry about - # checking this later. Perhaps in the scheduler? - rpc.cast(context, - self._get_network_topic(context), - {"method": "disassociate_floating_ip", - "args": {"floating_address": address}}) - - address = self.db.instance_get_fixed_address(context, instance['id']) - if address: - logging.debug("Deallocating address %s" % address) - # NOTE(vish): Currently, nothing needs to be done on the - # network node until release. If this changes, - # we will need to cast here. - self.network_manager.deallocate_fixed_ip(context.elevated(), - address) - host = instance['host'] if host: rpc.cast(context, @@ -293,13 +259,3 @@ class ComputeAPI(base.Base): {"method": "unrescue_instance", "args": {"instance_id": instance['id']}}) - def _get_network_topic(self, context): - """Retrieves the network host for a project""" - network_ref = self.network_manager.get_network(context) - host = network_ref['host'] - if not host: - host = rpc.call(context, - FLAGS.network_topic, - {"method": "set_network_host", - "args": {"network_id": network_ref['id']}}) - return self.db.queue_get_for(context, FLAGS.network_topic, host) diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 7eb60e262..6d705f983 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -40,6 +40,7 @@ import logging from nova import exception from nova import flags from nova import manager +from nova import rpc from nova import utils from nova.compute import power_state @@ -76,6 +77,17 @@ class ComputeManager(manager.Manager): state = power_state.NOSTATE self.db.instance_set_state(context, instance_id, state) + def _get_network_topic(self, context): + """Retrieves the network host for a project""" + network_ref = self.network_manager.get_network(context) + host = network_ref['host'] + if not host: + host = rpc.call(context, + FLAGS.network_topic, + {"method": "set_network_host", + "args": {"network_id": network_ref['id']}}) + return self.db.queue_get_for(context, FLAGS.network_topic, host) + @exception.wrap_exception def refresh_security_group(self, context, security_group_id, **_kwargs): """This call passes stright through to the virtualization driver.""" @@ -89,11 +101,26 @@ class ComputeManager(manager.Manager): if instance_ref['name'] in self.driver.list_instances(): raise exception.Error("Instance has already been created") logging.debug("instance %s: starting...", instance_id) - self.network_manager.setup_compute_network(context, instance_id) self.db.instance_update(context, instance_id, {'host': self.host}) + self.db.instance_set_state(context, + instance_id, + power_state.NOSTATE, + 'networking') + + is_vpn = instance_ref['image_id'] == FLAGS.vpn_image_id + address = self.network_manager.allocate_fixed_ip(context, + instance_id, + is_vpn) + rpc.cast(context, + self._get_network_topic(context), + {"method": "setup_fixed_ip", + "args": {"address": address}}) + + self.network_manager.setup_compute_network(context, instance_id) + # TODO(vish) check to make sure the availability zone matches self.db.instance_set_state(context, instance_id, @@ -119,9 +146,33 @@ class ComputeManager(manager.Manager): def terminate_instance(self, context, instance_id): """Terminate an instance on this machine.""" context = context.elevated() - logging.debug("instance %s: terminating", instance_id) instance_ref = self.db.instance_get(context, instance_id) + + address = self.db.instance_get_floating_address(context, + instance_ref['id']) + if address: + logging.debug("Disassociating address %s" % address) + # NOTE(vish): Right now we don't really care if the ip is + # disassociated. We may need to worry about + # checking this later. + rpc.cast(context, + self._get_network_topic(context), + {"method": "disassociate_floating_ip", + "args": {"floating_address": address}}) + + address = self.db.instance_get_fixed_address(context, + instance_ref['id']) + if address: + logging.debug("Deallocating address %s" % address) + # NOTE(vish): Currently, nothing needs to be done on the + # network node until release. If this changes, + # we will need to cast here. + self.network_manager.deallocate_fixed_ip(context.elevated(), + address) + + logging.debug("instance %s: terminating", instance_id) + volumes = instance_ref.get('volumes', []) or [] for volume in volumes: self.detach_volume(context, instance_id, volume['id']) -- cgit From 3a0878b7a94ba3411feb9a7944f42c9f352d3a45 Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 21 Dec 2010 03:34:30 +0000 Subject: add a few extra joined objects to get instance --- nova/compute/manager.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 3b7fd9c32..b3e97011f 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -158,7 +158,6 @@ class ComputeManager(manager.Manager): instance_ref = self.db.instance_get(context, instance_id) - if not FLAGS.stub_network: address = self.db.instance_get_floating_address(context, instance_ref['id']) -- cgit From fb24146290e6cf49397441d36878652da376f66d Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 21 Dec 2010 03:43:47 +0000 Subject: pep8 and removed extra imports --- nova/compute/api.py | 1 - 1 file changed, 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 606344c03..1dbe6e02d 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -275,4 +275,3 @@ class ComputeAPI(base.Base): self.db.queue_get_for(context, FLAGS.compute_topic, host), {"method": "unrescue_instance", "args": {"instance_id": instance['id']}}) - -- cgit From f0195ebfd2cc56cee5797fff19fb9702c51df51b Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Tue, 21 Dec 2010 21:47:13 +0000 Subject: fix reboot command to work even if a host is rebooted --- nova/compute/manager.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/compute') diff --git a/nova/compute/manager.py b/nova/compute/manager.py index a84af6bb9..6d3ea966d 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -138,8 +138,8 @@ class ComputeManager(manager.Manager): def reboot_instance(self, context, instance_id): """Reboot an instance on this server.""" context = context.elevated() - instance_ref = self.db.instance_get(context, instance_id) self._update_state(context, instance_id) + instance_ref = self.db.instance_get(context, instance_id) if instance_ref['state'] != power_state.RUNNING: logging.warn('trying to reboot a non-running ' @@ -153,6 +153,7 @@ class ComputeManager(manager.Manager): instance_id, power_state.NOSTATE, 'rebooting') + self.network_manager.setup_compute_network(context, instance_id) self.driver.reboot(instance_ref) self._update_state(context, instance_id) @@ -168,6 +169,7 @@ class ComputeManager(manager.Manager): instance_id, power_state.NOSTATE, 'rescuing') + self.network_manager.setup_compute_network(context, instance_id) self.driver.rescue(instance_ref) self._update_state(context, instance_id) -- cgit From 7af11742b6bab492eb87c212d05bf77c0c13aea9 Mon Sep 17 00:00:00 2001 From: Thierry Carrez Date: Wed, 22 Dec 2010 12:24:53 +0100 Subject: Populate user_data field from run-instances call parameter, default to empty string to avoid metadata base64 decoding failure, LP: #691598 --- nova/compute/api.py | 2 ++ 1 file changed, 2 insertions(+) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index c740814da..8fdc0fc9e 100644 --- a/nova/compute/api.py +++ b/nova/compute/api.py @@ -57,6 +57,7 @@ class ComputeAPI(base.Base): max_count=1, kernel_id=None, ramdisk_id=None, display_name='', description='', key_name=None, key_data=None, security_group='default', + user_data=None, generate_hostname=generate_default_hostname): """Create the number of instances requested if quote and other arguments check out ok.""" @@ -120,6 +121,7 @@ class ComputeAPI(base.Base): 'local_gb': type_data['local_gb'], 'display_name': display_name, 'display_description': description, + 'user_data': user_data or '', 'key_name': key_name, 'key_data': key_data} -- cgit From 81191660cf6d1e5ea47630ed45041dc923f6b57a Mon Sep 17 00:00:00 2001 From: Vishvananda Ishaya Date: Wed, 22 Dec 2010 20:59:53 +0000 Subject: merge trunk and upgrade to cheetah templating --- nova/compute/api.py | 47 ++++++++++++++++++++------- nova/compute/disk.py | 38 ++++++++++++++++------ nova/compute/instance_types.py | 3 +- nova/compute/manager.py | 73 +++++++++++++++++++++++++++++++++--------- nova/compute/monitor.py | 12 +++---- 5 files changed, 128 insertions(+), 45 deletions(-) (limited to 'nova/compute') diff --git a/nova/compute/api.py b/nova/compute/api.py index 8e0efa4cc..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, @@ -120,7 +125,7 @@ class ComputeAPI(base.Base): elevated = context.elevated() instances = [] - logging.debug("Going to run %s instances...", num_instances) + logging.debug(_("Going to run %s instances..."), num_instances) for num in range(num_instances): instance = dict(mac_address=utils.generate_mac(), launch_index=num, @@ -157,7 +162,7 @@ class ComputeAPI(base.Base): {"method": "setup_fixed_ip", "args": {"address": address}}) - logging.debug("Casting to scheduler for %s/%s's instance %s", + logging.debug(_("Casting to scheduler for %s/%s's instance %s"), context.project_id, context.user_id, instance_id) rpc.cast(context, FLAGS.scheduler_topic, @@ -204,12 +209,12 @@ class ComputeAPI(base.Base): instance = self.db.instance_get_by_internal_id(context, instance_id) except exception.NotFound as e: - logging.warning("Instance %d was not found during terminate", + logging.warning(_("Instance %d 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 %d is already being terminated"), instance_id) return @@ -223,7 +228,7 @@ class ComputeAPI(base.Base): address = self.db.instance_get_floating_address(context, instance['id']) if address: - logging.debug("Disassociating address %s" % address) + logging.debug(_("Disassociating address %s") % address) # NOTE(vish): Right now we don't really care if the ip is # disassociated. We may need to worry about # checking this later. Perhaps in the scheduler? @@ -234,7 +239,7 @@ class ComputeAPI(base.Base): address = self.db.instance_get_fixed_address(context, instance['id']) if address: - logging.debug("Deallocating address %s" % address) + logging.debug(_("Deallocating address %s") % address) # NOTE(vish): Currently, nothing needs to be done on the # network node until release. If this changes, # we will need to cast here. @@ -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 675cd0259..814a258cd 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -67,12 +67,12 @@ def partition(infile, outfile, local_bytes=0, resize=True, execute('resize2fs %s' % infile) file_size = FLAGS.minimum_root_size elif file_size % sector_size != 0: - logging.warn("Input partition size not evenly divisible by" - " sector size: %d / %d", file_size, sector_size) + logging.warn(_("Input partition size not evenly divisible by" + " sector size: %d / %d"), file_size, sector_size) primary_sectors = file_size / sector_size if local_bytes % sector_size != 0: - logging.warn("Bytes for local storage not evenly divisible" - " by sector size: %d / %d", local_bytes, sector_size) + logging.warn(_("Bytes for local storage not evenly divisible" + " by sector size: %d / %d"), local_bytes, sector_size) local_sectors = local_bytes / sector_size mbr_last = 62 # a @@ -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,20 +122,30 @@ 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) + raise exception.Error(_('Could not attach image to loopback: %s') + % err) device = out.strip() try: if not partition is None: # create partition out, err = execute('sudo kpartx -a %s' % device) if err: - raise exception.Error('Failed to load partition: %s' % err) + raise exception.Error(_('Failed to load partition: %s') % err) mapped_device = '/dev/mapper/%sp%s' % (device.split('/')[-1], 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() @@ -137,7 +154,8 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): out, err = execute( 'sudo mount %s %s' % (mapped_device, tmpdir)) if err: - raise exception.Error('Failed to mount filesystem: %s' % err) + raise exception.Error(_('Failed to mount filesystem: %s') + % err) try: if key: @@ -156,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): @@ -165,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/instance_types.py b/nova/compute/instance_types.py index 6e47170bd..196d6a8df 100644 --- a/nova/compute/instance_types.py +++ b/nova/compute/instance_types.py @@ -38,7 +38,8 @@ def get_by_type(instance_type): if instance_type is None: return FLAGS.default_instance_type if instance_type not in INSTANCE_TYPES: - raise exception.ApiError("Unknown instance type: %s" % instance_type) + raise exception.ApiError(_("Unknown instance type: %s"), + instance_type) return instance_type diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 59d4fb29d..cc607f9d4 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -93,8 +93,8 @@ class ComputeManager(manager.Manager): context = context.elevated() instance_ref = self.db.instance_get(context, instance_id) if instance_ref['name'] in self.driver.list_instances(): - raise exception.Error("Instance has already been created") - logging.debug("instance %s: starting...", instance_id) + raise exception.Error(_("Instance has already been created")) + logging.debug(_("instance %s: starting..."), instance_id) self.network_manager.setup_compute_network(context, instance_id) self.db.instance_update(context, instance_id, @@ -113,7 +113,7 @@ class ComputeManager(manager.Manager): instance_id, {'launched_at': now}) except Exception: # pylint: disable-msg=W0702 - logging.exception("instance %s: Failed to spawn", + logging.exception(_("instance %s: Failed to spawn"), instance_ref['name']) self.db.instance_set_state(context, instance_id, @@ -125,7 +125,7 @@ class ComputeManager(manager.Manager): def terminate_instance(self, context, instance_id): """Terminate an instance on this machine.""" context = context.elevated() - logging.debug("instance %s: terminating", instance_id) + logging.debug(_("instance %s: terminating"), instance_id) instance_ref = self.db.instance_get(context, instance_id) volumes = instance_ref.get('volumes', []) or [] @@ -133,8 +133,8 @@ class ComputeManager(manager.Manager): self.detach_volume(context, instance_id, volume['id']) if instance_ref['state'] == power_state.SHUTOFF: self.db.instance_destroy(context, instance_id) - raise exception.Error('trying to destroy already destroyed' - ' instance: %s' % instance_id) + raise exception.Error(_('trying to destroy already destroyed' + ' instance: %s') % instance_id) self.driver.destroy(instance_ref) # TODO(ja): should we keep it in a terminated state for a bit? @@ -148,13 +148,13 @@ class ComputeManager(manager.Manager): self._update_state(context, instance_id) if instance_ref['state'] != power_state.RUNNING: - logging.warn('trying to reboot a non-running ' - 'instance: %s (state: %s excepted: %s)', + logging.warn(_('trying to reboot a non-running ' + 'instance: %s (state: %s excepted: %s)'), instance_ref['internal_id'], instance_ref['state'], power_state.RUNNING) - logging.debug('instance %s: rebooting', instance_ref['name']) + logging.debug(_('instance %s: rebooting'), instance_ref['name']) self.db.instance_set_state(context, instance_id, power_state.NOSTATE, @@ -168,7 +168,7 @@ class ComputeManager(manager.Manager): context = context.elevated() instance_ref = self.db.instance_get(context, instance_id) - logging.debug('instance %s: rescuing', + logging.debug(_('instance %s: rescuing'), instance_ref['internal_id']) self.db.instance_set_state(context, instance_id, @@ -183,7 +183,7 @@ class ComputeManager(manager.Manager): context = context.elevated() instance_ref = self.db.instance_get(context, instance_id) - logging.debug('instance %s: unrescuing', + logging.debug(_('instance %s: unrescuing'), instance_ref['internal_id']) self.db.instance_set_state(context, instance_id, @@ -192,11 +192,52 @@ 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.""" context = context.elevated() - logging.debug("instance %s: getting console output", instance_id) + logging.debug(_("instance %s: getting console output"), instance_id) instance_ref = self.db.instance_get(context, instance_id) return self.driver.get_console_output(instance_ref) @@ -205,7 +246,7 @@ class ComputeManager(manager.Manager): def attach_volume(self, context, instance_id, volume_id, mountpoint): """Attach a volume to an instance.""" context = context.elevated() - logging.debug("instance %s: attaching volume %s to %s", instance_id, + logging.debug(_("instance %s: attaching volume %s to %s"), instance_id, volume_id, mountpoint) instance_ref = self.db.instance_get(context, instance_id) dev_path = self.volume_manager.setup_compute_volume(context, @@ -222,7 +263,7 @@ class ComputeManager(manager.Manager): # NOTE(vish): The inline callback eats the exception info so we # log the traceback here and reraise the same # ecxception below. - logging.exception("instance %s: attach failed %s, removing", + logging.exception(_("instance %s: attach failed %s, removing"), instance_id, mountpoint) self.volume_manager.remove_compute_volume(context, volume_id) @@ -234,13 +275,13 @@ class ComputeManager(manager.Manager): def detach_volume(self, context, instance_id, volume_id): """Detach a volume from an instance.""" context = context.elevated() - logging.debug("instance %s: detaching volume %s", + logging.debug(_("instance %s: detaching volume %s"), instance_id, volume_id) instance_ref = self.db.instance_get(context, instance_id) volume_ref = self.db.volume_get(context, volume_id) if instance_ref['name'] not in self.driver.list_instances(): - logging.warn("Detaching volume from unknown instance %s", + logging.warn(_("Detaching volume from unknown instance %s"), instance_ref['name']) else: self.driver.detach_volume(instance_ref['name'], diff --git a/nova/compute/monitor.py b/nova/compute/monitor.py index 22653113a..60c347a5e 100644 --- a/nova/compute/monitor.py +++ b/nova/compute/monitor.py @@ -255,7 +255,7 @@ class Instance(object): Updates the instances statistics and stores the resulting graphs in the internal object store on the cloud controller. """ - logging.debug('updating %s...', self.instance_id) + logging.debug(_('updating %s...'), self.instance_id) try: data = self.fetch_cpu_stats() @@ -285,7 +285,7 @@ class Instance(object): graph_disk(self, '1w') graph_disk(self, '1m') except Exception: - logging.exception('unexpected error during update') + logging.exception(_('unexpected error during update')) self.last_updated = utcnow() @@ -351,7 +351,7 @@ class Instance(object): rd += rd_bytes wr += wr_bytes except TypeError: - logging.error('Cannot get blockstats for "%s" on "%s"', + logging.error(_('Cannot get blockstats for "%s" on "%s"'), disk, self.instance_id) raise @@ -373,7 +373,7 @@ class Instance(object): rx += stats[0] tx += stats[4] except TypeError: - logging.error('Cannot get ifstats for "%s" on "%s"', + logging.error(_('Cannot get ifstats for "%s" on "%s"'), interface, self.instance_id) raise @@ -408,7 +408,7 @@ class InstanceMonitor(object, service.Service): try: conn = virt_connection.get_connection(read_only=True) except Exception, exn: - logging.exception('unexpected exception getting connection') + logging.exception(_('unexpected exception getting connection')) time.sleep(FLAGS.monitoring_instances_delay) return @@ -423,7 +423,7 @@ class InstanceMonitor(object, service.Service): if not domain_id in self._instances: instance = Instance(conn, domain_id) self._instances[domain_id] = instance - logging.debug('Found instance: %s', domain_id) + logging.debug(_('Found instance: %s'), domain_id) for key in self._instances.keys(): instance = self._instances[key] -- cgit