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(-) 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 ++++++++++++++++++++++---- nova/endpoint/cloud.py | 4 ++-- 3 files changed, 39 insertions(+), 17 deletions(-) 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, diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index 3b7b4804b..b7a4fe20e 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -544,8 +544,8 @@ class CloudController(object): for num in range(int(kwargs['max_count'])): inst = self.instdir.new() inst['image_id'] = image_id - inst['kernel_id'] = kernel_id - inst['ramdisk_id'] = ramdisk_id + inst['kernel_id'] = kernel_id or '' + inst['ramdisk_id'] = ramdisk_id or '' inst['user_data'] = kwargs.get('user_data', '') inst['instance_type'] = kwargs.get('instance_type', 'm1.small') inst['reservation_id'] = reservation_id -- 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 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(-) 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 c599914304b262067c19b2968ab50826b4d9bcd3 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 30 Jul 2010 12:54:03 -0700 Subject: Removed duplicate toXml method --- nova/virt/libvirt_conn.py | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 43b5eded2..6bc5ebf89 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -228,20 +228,6 @@ class LibvirtConnection(object): return os.path.abspath(os.path.join(instance.datamodel['basepath'], path)) - def toXml(self, instance): - # TODO(termie): cache? - logging.debug("Starting the toXML method") - libvirt_xml = open(FLAGS.libvirt_xml_template).read() - xml_info = instance.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(instance.datamodel.copy()) - libvirt_xml = libvirt_xml % xml_info - logging.debug("Finished the toXML method") - - return libvirt_xml - def toXml(self): # TODO(termie): cache? logging.debug("Starting the toXML method") -- cgit From 6526f21d9bf5a53546240ec29099d68933165500 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 30 Jul 2010 13:13:00 -0700 Subject: Added Cheetah to pip-requires --- tools/pip-requires | 1 + 1 file changed, 1 insertion(+) diff --git a/tools/pip-requires b/tools/pip-requires index 4eb47ca2b..a235d6246 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -1,4 +1,5 @@ IPy==0.70 +Cheetah==2.4.2.1 M2Crypto==0.20.2 amqplib==0.6.1 anyjson==0.2.4 -- cgit From 7985f5fb32432630b3fef775f601900f89346ed2 Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 30 Jul 2010 13:35:21 -0700 Subject: Accept a configurable libvirt_uri --- nova/virt/libvirt_conn.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 6bc5ebf89..8d473296a 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -49,6 +49,9 @@ FLAGS = flags.FLAGS flags.DEFINE_string('libvirt_xml_template', utils.abspath('compute/libvirt.xml.template'), 'Libvirt XML Template') +flags.DEFINE_string('libvirt_uri', + 'qemu:///system', + 'Libvirt URI to connect to') def get_connection(read_only): # These are loaded late so that there's no need to install these @@ -67,10 +70,11 @@ class LibvirtConnection(object): auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], 'root', None] + libvirt_uri = str(FLAGS.libvirt_uri) if read_only: - self._conn = libvirt.openReadOnly('qemu:///system') + self._conn = libvirt.openReadOnly(libvirt_uri) else: - self._conn = libvirt.openAuth('qemu:///system', auth, 0) + self._conn = libvirt.openAuth(libvirt_uri, auth, 0) def list_instances(self): -- cgit From 6227cb13c311624998b9c2c6e55fc0d261cfcb6c Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Sat, 31 Jul 2010 20:49:21 -0700 Subject: Recognize 'magic' kernel value that means "don't use a kernel" - currently aki-00000000 --- nova/endpoint/cloud.py | 10 ++++++++-- nova/flags.py | 3 +++ 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/nova/endpoint/cloud.py b/nova/endpoint/cloud.py index b4157e48c..344352a93 100644 --- a/nova/endpoint/cloud.py +++ b/nova/endpoint/cloud.py @@ -523,9 +523,15 @@ class CloudController(object): kernel_id = kwargs.get('kernel_id', kernel_id) ramdisk_id = kwargs.get('ramdisk_id', ramdisk_id) + if kernel_id == str(FLAGS.null_kernel): + kernel_id = None + ramdisk_id = None + # make sure we have access to kernel and ramdisk - self._get_image(context, kernel_id) - self._get_image(context, ramdisk_id) + if kernel_id: + self._get_image(context, kernel_id) + if ramdisk_id: + self._get_image(context, ramdisk_id) logging.debug("Going to run instances...") reservation_id = utils.generate_uid('r') diff --git a/nova/flags.py b/nova/flags.py index f35f5fa10..caae33e14 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -57,6 +57,9 @@ DEFINE_string('ec2_url', 'http://127.0.0.1:8773/services/Cloud', 'Url to ec2 api server') +DEFINE_string('null_kernel', + 'aki-00000000', + 'Kernel image that indicates not to use a kernel (use a raw disk image instead)') DEFINE_string('default_image', 'ami-11111', 'default image to use, testing only') -- 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 +++ nova/virt/libvirt_conn.py | 48 ++++++++++++++++++++++++++++++++++------------- 2 files changed, 38 insertions(+), 13 deletions(-) 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) diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 8d473296a..d18158678 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -195,32 +195,54 @@ class LibvirtConnection(object): user = manager.AuthManager().get_user(data['user_id']) if not os.path.exists(basepath('disk')): yield images.fetch(data['image_id'], basepath('disk-raw'), user) - if not os.path.exists(basepath('kernel')): - yield images.fetch(data['kernel_id'], basepath('kernel'), user) - if not os.path.exists(basepath('ramdisk')): - yield images.fetch(data['ramdisk_id'], basepath('ramdisk'), user) + + using_kernel = data['kernel_id'] and True + + if using_kernel: + if not os.path.exists(basepath('kernel')): + yield images.fetch(data['kernel_id'], basepath('kernel'), user) + if not os.path.exists(basepath('ramdisk')): + yield images.fetch(data['ramdisk_id'], basepath('ramdisk'), user) execute = lambda cmd, input=None: \ process.simple_execute(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 if FLAGS.simple_network: - with open(FLAGS.simple_network_template) as f: - net = f.read() % {'address': data['private_dns_name'], + 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} - if key or net: + + with open(FLAGS.simple_network_template) as f: + 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) + try: + yield disk.inject_data(basepath('disk-raw'), key=key, net=net, dns=dns, remove_network_udev=True, partition=target_partition, execute=execute) + except Exception as e: + # This could be a windows image, or a vmdk format disk + logging.warn('Could not inject data; ignoring. (%s)' % e) - if os.path.exists(basepath('disk')): - yield process.simple_execute('rm -f %s' % basepath('disk')) + if using_kernel: + if os.path.exists(basepath('disk')): + yield process.simple_execute('rm -f %s' % basepath('disk')) bytes = (instance_types.INSTANCE_TYPES[data['instance_type']]['local_gb'] * 1024 * 1024 * 1024) @@ -232,15 +254,15 @@ class LibvirtConnection(object): return os.path.abspath(os.path.join(instance.datamodel['basepath'], path)) - def toXml(self): + def toXml(self, instance): # TODO(termie): cache? logging.debug("Starting the toXML method") template_contents = open(FLAGS.libvirt_xml_template).read() - xml_info = self.datamodel.copy() + xml_info = instance.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()) + xml_info['nova'] = json.dumps(instance.datamodel.copy()) if xml_info['kernel_id']: xml_info['kernel'] = xml_info['basepath'] + "/kernel" -- 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(-) 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 - nova/flags.py | 3 ++- nova/virt/libvirt.uml.xml.template | 2 +- nova/virt/libvirt.xen.xml.template | 2 +- nova/virt/libvirt_conn.py | 2 ++ 6 files changed, 7 insertions(+), 25 deletions(-) delete mode 100644 nova/compute/resolv.conf.template 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} diff --git a/nova/flags.py b/nova/flags.py index 2b96a15f7..d2c22e46b 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -202,7 +202,8 @@ DEFINE_string('default_ramdisk', 'ari-11111', DEFINE_string('default_instance_type', 'm1.small', 'default instance type to use, testing only') DEFINE_string('null_kernel', 'aki-00000000', - 'kernel image that indicates not to use a kernel, to use a raw disk image instead') + 'kernel image that indicates not to use a kernel, ' + ' but to use a raw disk image instead') DEFINE_string('vpn_image_id', 'ami-CLOUDPIPE', 'AMI for cloudpipe vpn server') DEFINE_string('vpn_key_suffix', diff --git a/nova/virt/libvirt.uml.xml.template b/nova/virt/libvirt.uml.xml.template index f6e5fad69..da9588049 100644 --- a/nova/virt/libvirt.uml.xml.template +++ b/nova/virt/libvirt.uml.xml.template @@ -12,7 +12,7 @@ - + diff --git a/nova/virt/libvirt.xen.xml.template b/nova/virt/libvirt.xen.xml.template index 9508ad3b7..8f650e512 100644 --- a/nova/virt/libvirt.xen.xml.template +++ b/nova/virt/libvirt.xen.xml.template @@ -23,7 +23,7 @@ - + diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index ba5d6dbac..ece98087b 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -72,6 +72,7 @@ flags.DEFINE_bool('allow_project_net_traffic', True, 'Whether to allow in project network traffic') + def get_connection(read_only): # These are loaded late so that there's no need to install these # libraries when not using libvirt. @@ -126,6 +127,7 @@ class LibvirtConnection(object): auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], 'root', None] + if read_only: return libvirt.openReadOnly(uri) else: -- cgit From f8028c0a4cd1c3cfb8a9c6b4c397fd67ce912cce Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Thu, 14 Oct 2010 13:48:34 -0700 Subject: Removed stray spaces that were causing an unnecessary diff line --- nova/virt/libvirt_conn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index ece98087b..68791c28a 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -127,7 +127,7 @@ class LibvirtConnection(object): auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], 'root', None] - + if read_only: return libvirt.openReadOnly(uri) else: -- cgit From 98623a160078dfed7347dcd1539b0cd27e51644a Mon Sep 17 00:00:00 2001 From: Justin Santa Barbara Date: Fri, 15 Oct 2010 11:06:16 -0700 Subject: Removed 'and True' oddity --- nova/virt/libvirt_conn.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 68791c28a..d78a8f0db 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -324,7 +324,7 @@ class LibvirtConnection(object): if not os.path.exists(basepath('disk')): yield images.fetch(inst.image_id, basepath('disk-raw'), user, project) - using_kernel = inst.kernel_id and True + using_kernel = inst.kernel_id if using_kernel: if not os.path.exists(basepath('kernel')): yield images.fetch(inst.kernel_id, basepath('kernel'), user, project) -- 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/api/ec2/cloud.py | 2 +- nova/compute/disk.py | 6 +++--- nova/virt/libvirt_conn.py | 13 ++++++------- 3 files changed, 10 insertions(+), 11 deletions(-) diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index 1cf4abcc9..a5acd1f6d 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -801,7 +801,7 @@ class CloudController(object): if kernel_id == str(FLAGS.null_kernel): kernel_id = None ramdisk_id = None - + # make sure we have access to kernel and ramdisk if kernel_id: self.image_service.show(context, kernel_id) 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) diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 09cb29773..81dbbaad5 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -467,13 +467,13 @@ class LibvirtConnection(object): process_input=process_input, check_exit_code=check_exit_code) - # 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 + # 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 = str(inst['key_data']) net = None network_ref = db.network_get_by_instance(context.get_admin_context(), @@ -493,11 +493,10 @@ class LibvirtConnection(object): inst['name'], inst.image_id) if net: logging.info('instance %s: injecting net into image %s', - inst['name'], inst.image_id) - execute=execute) + inst['name'], inst.image_id) try: yield disk.inject_data(basepath('disk-raw'), key, net, - partition=target_partition, + partition=target_partition, execute=execute) except Exception as e: # This could be a windows image, or a vmdk format disk @@ -557,7 +556,7 @@ class LibvirtConnection(object): if xml_info['ramdisk_id'] or xml_info['kernel_id']: xml_info['disk'] = xml_info['basepath'] + "/disk" - xml = str(Template(self.libvirt_xml, searchList=[ xml_info ] )) + xml = str(Template(self.libvirt_xml, searchList=[xml_info])) logging.debug('instance %s: finished toXML method', instance['name']) return xml -- 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 ++-- nova/flags.py | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) 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' % diff --git a/nova/flags.py b/nova/flags.py index cf481b55f..a61033201 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -237,7 +237,7 @@ DEFINE_string('default_ramdisk', 'ari-11111', DEFINE_string('default_instance_type', 'm1.small', 'default instance type to use, testing only') DEFINE_string('null_kernel', 'aki-00000000', - 'kernel image that indicates not to use a kernel, ' + 'kernel image that indicates not to use a kernel,' ' but to use a raw disk image instead') DEFINE_string('vpn_image_id', 'ami-CLOUDPIPE', 'AMI for cloudpipe vpn server') -- cgit From 364b4204ba9e4d04b0d0293a9c5fd62320ae3a63 Mon Sep 17 00:00:00 2001 From: Rick Clark Date: Wed, 1 Dec 2010 16:23:34 -0600 Subject: Changed null_kernel flag from aki-00000000 to nokernel --- nova/flags.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/nova/flags.py b/nova/flags.py index a61033201..be81fd7ed 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -236,7 +236,7 @@ DEFINE_string('default_ramdisk', 'ari-11111', 'default ramdisk to use, testing only') DEFINE_string('default_instance_type', 'm1.small', 'default instance type to use, testing only') -DEFINE_string('null_kernel', 'aki-00000000', +DEFINE_string('null_kernel', 'nokernel', 'kernel image that indicates not to use a kernel,' ' but to use a raw disk image instead') -- cgit From bfe019e0de486eea09e4702262cd228791a4694c Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 14 Dec 2010 15:33:18 +0100 Subject: Now that we have a templating engine, let's use it. Consolidate all the libvirt templates into one, extending the unit tests to make sure I didn't mess up. --- nova/tests/virt_unittest.py | 135 +++++++++++++++++++++++------ nova/virt/libvirt.qemu.xml.template | 37 -------- nova/virt/libvirt.rescue.qemu.xml.template | 37 -------- nova/virt/libvirt.rescue.uml.xml.template | 26 ------ nova/virt/libvirt.rescue.xen.xml.template | 34 -------- nova/virt/libvirt.uml.xml.template | 26 ------ nova/virt/libvirt.xen.xml.template | 35 -------- nova/virt/libvirt.xml.template | 76 ++++++++++++++++ nova/virt/libvirt_conn.py | 60 +++---------- 9 files changed, 199 insertions(+), 267 deletions(-) delete mode 100644 nova/virt/libvirt.qemu.xml.template delete mode 100644 nova/virt/libvirt.rescue.qemu.xml.template delete mode 100644 nova/virt/libvirt.rescue.uml.xml.template delete mode 100644 nova/virt/libvirt.rescue.xen.xml.template delete mode 100644 nova/virt/libvirt.uml.xml.template delete mode 100644 nova/virt/libvirt.xen.xml.template create mode 100644 nova/virt/libvirt.xml.template diff --git a/nova/tests/virt_unittest.py b/nova/tests/virt_unittest.py index d49383fb7..bcc995a5f 100644 --- a/nova/tests/virt_unittest.py +++ b/nova/tests/virt_unittest.py @@ -40,19 +40,53 @@ class LibvirtConnTestCase(test.TrialTestCase): self.network = utils.import_object(FLAGS.network_manager) FLAGS.instances_path = '' - def test_get_uri_and_template(self): - ip = '10.11.12.13' - - instance = {'internal_id': 1, - 'memory_kb': '1024000', - 'basepath': '/some/path', - 'bridge_name': 'br100', - 'mac_address': '02:12:34:46:56:67', - 'vcpus': 2, - 'project_id': 'fake', - 'bridge': 'br101', - 'instance_type': 'm1.small'} - + test_ip = '10.11.12.13' + test_instance = { + 'memory_kb' : '1024000', + 'basepath' : '/some/path', + 'bridge_name' : 'br100', + 'mac_address' : '02:12:34:46:56:67', + 'vcpus' : 2, + 'project_id' : 'fake', + 'bridge' : 'br101', + 'instance_type' : 'm1.small'} + + def test_xml_and_uri_no_ramdisk_no_kernel(self): + instance_data = dict(self.test_instance) + self.do_test_xml_and_uri(instance_data, + expect_kernel=False, expect_ramdisk=False) + + def test_xml_and_uri_no_ramdisk(self): + instance_data = dict(self.test_instance) + instance_data['kernel_id'] = 'aki-deadbeef' + self.do_test_xml_and_uri(instance_data, + expect_kernel=True, expect_ramdisk=False) + + def test_xml_and_uri_no_kernel(self): + instance_data = dict(self.test_instance) + instance_data['ramdisk_id'] = 'ari-deadbeef' + self.do_test_xml_and_uri(instance_data, + expect_kernel=False, expect_ramdisk=False) + + def test_xml_and_uri(self): + instance_data = dict(self.test_instance) + instance_data['ramdisk_id'] = 'ari-deadbeef' + instance_data['kernel_id'] = 'aki-deadbeef' + self.do_test_xml_and_uri(instance_data, + expect_kernel=True, expect_ramdisk=True) + + def test_xml_and_uri_rescue(self): + instance_data = dict(self.test_instance) + instance_data['ramdisk_id'] = 'ari-deadbeef' + instance_data['kernel_id'] = 'aki-deadbeef' + self.do_test_xml_and_uri(instance_data, + expect_kernel=True, expect_ramdisk=True, + rescue=True) + + + def do_test_xml_and_uri(self, instance, + expect_ramdisk, expect_kernel, + rescue=False): user_context = context.RequestContext(project=self.project, user=self.user) instance_ref = db.instance_create(user_context, instance) @@ -60,13 +94,14 @@ class LibvirtConnTestCase(test.TrialTestCase): self.network.set_network_host(context.get_admin_context(), network_ref['id']) - fixed_ip = {'address': ip, - 'network_id': network_ref['id']} + fixed_ip = { 'address' : self.test_ip, + 'network_id' : network_ref['id'] } ctxt = context.get_admin_context() fixed_ip_ref = db.fixed_ip_create(ctxt, fixed_ip) - db.fixed_ip_update(ctxt, ip, {'allocated': True, - 'instance_id': instance_ref['id']}) + db.fixed_ip_update(ctxt, self.test_ip, + { 'allocated': True, + 'instance_id': instance_ref['id'] }) type_uri_map = {'qemu': ('qemu:///system', [(lambda t: t.find('.').get('type'), 'qemu'), @@ -78,23 +113,71 @@ class LibvirtConnTestCase(test.TrialTestCase): (lambda t: t.find('./devices/emulator'), None)]), 'uml': ('uml:///system', [(lambda t: t.find('.').get('type'), 'uml'), - (lambda t: t.find('./os/type').text, 'uml')])} + (lambda t: t.find('./os/type').text, 'uml')]), + 'xen': ('xen:///', + [(lambda t: t.find('.').get('type'), 'xen'), + (lambda t: t.find('./os/type').text, 'linux')]), + } + + for hypervisor_type in ['qemu', 'kvm', 'xen']: + check_list = type_uri_map[hypervisor_type][1] + + if rescue: + check = (lambda t: t.find('./os/kernel').text.split('/')[1], + 'rescue-kernel') + check_list.append(check) + check = (lambda t: t.find('./os/initrd').text.split('/')[1], + 'rescue-ramdisk') + check_list.append(check) + else: + if expect_kernel: + check = (lambda t: t.find('./os/kernel').text.split('/')[1], + 'kernel') + else: + check = (lambda t: t.find('./os/kernel'), None) + check_list.append(check) + + if expect_ramdisk: + check = (lambda t: t.find('./os/initrd').text.split('/')[1], + 'ramdisk') + else: + check = (lambda t: t.find('./os/initrd'), None) + check_list.append(check) common_checks = [ (lambda t: t.find('.').tag, 'domain'), - (lambda t: t.find('./devices/interface/filterref/parameter').\ - get('name'), 'IP'), - (lambda t: t.find('./devices/interface/filterref/parameter').\ - get('value'), '10.11.12.13')] + (lambda t: t.find('./devices/interface/filterref/parameter' + ).get('name'), 'IP'), + (lambda t: t.find('./devices/interface/filterref/parameter' + ).get('value'), '10.11.12.13'), + (lambda t: t.findall('./devices/interface/filterref/parameter' + )[1].get('name'), 'DHCPSERVER'), + (lambda t: t.findall('./devices/interface/filterref/parameter' + )[1].get('value'), '10.0.0.1'), + (lambda t: t.find('./devices/serial/source').get('path' + ).split('/')[1], 'console.log'), + (lambda t: t.find('./memory').text, '2097152')] + + if rescue: + common_checks += [(lambda t: t.findall('./devices/disk/source' + )[0].get('file').split('/')[1], + 'rescue-disk'), + (lambda t: t.findall('./devices/disk/source' + )[1].get('file').split('/')[1], + 'disk')] + else: + common_checks += [(lambda t: t.findall('./devices/disk/source' + )[0].get('file').split('/')[1], + 'disk')] for (libvirt_type, (expected_uri, checks)) in type_uri_map.iteritems(): FLAGS.libvirt_type = libvirt_type conn = libvirt_conn.LibvirtConnection(True) - uri, _template, _rescue = conn.get_uri_and_templates() + uri = conn.get_uri() self.assertEquals(uri, expected_uri) - xml = conn.to_xml(instance_ref) + xml = conn.to_xml(instance_ref, rescue) tree = xml_to_tree(xml) for i, (check, expected_result) in enumerate(checks): self.assertEqual(check(tree), @@ -106,6 +189,8 @@ class LibvirtConnTestCase(test.TrialTestCase): expected_result, '%s failed common check %d' % (xml, i)) + # This test is supposed to make sure we don't override a specifically set uri + # # Deliberately not just assigning this string to FLAGS.libvirt_uri and # checking against that later on. This way we make sure the # implementation doesn't fiddle around with the FLAGS. @@ -114,7 +199,7 @@ class LibvirtConnTestCase(test.TrialTestCase): for (libvirt_type, (expected_uri, checks)) in type_uri_map.iteritems(): FLAGS.libvirt_type = libvirt_type conn = libvirt_conn.LibvirtConnection(True) - uri, _template, _rescue = conn.get_uri_and_templates() + uri = conn.get_uri() self.assertEquals(uri, testuri) def tearDown(self): diff --git a/nova/virt/libvirt.qemu.xml.template b/nova/virt/libvirt.qemu.xml.template deleted file mode 100644 index 739eceaaa..000000000 --- a/nova/virt/libvirt.qemu.xml.template +++ /dev/null @@ -1,37 +0,0 @@ - - ${name} - - hvm -#if $getVar('kernel', None) - ${kernel} - #if $getVar('ramdisk', None) - ${ramdisk} - #end if - root=/dev/vda1 console=ttyS0 -#end if - - - - - ${memory_kb} - ${vcpus} - - - - - - - - - - - - - - - - - - - - diff --git a/nova/virt/libvirt.rescue.qemu.xml.template b/nova/virt/libvirt.rescue.qemu.xml.template deleted file mode 100644 index c0ffbdcee..000000000 --- a/nova/virt/libvirt.rescue.qemu.xml.template +++ /dev/null @@ -1,37 +0,0 @@ - - %(name)s - - hvm - %(basepath)s/rescue-kernel - %(basepath)s/rescue-ramdisk - root=/dev/vda1 console=ttyS0 - - - - - %(memory_kb)s - %(vcpus)s - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/nova/virt/libvirt.rescue.uml.xml.template b/nova/virt/libvirt.rescue.uml.xml.template deleted file mode 100644 index 836f47532..000000000 --- a/nova/virt/libvirt.rescue.uml.xml.template +++ /dev/null @@ -1,26 +0,0 @@ - - %(name)s - %(memory_kb)s - - %(type)s - /usr/bin/linux - /dev/ubda1 - - - - - - - - - - - - - - - - - - - diff --git a/nova/virt/libvirt.rescue.xen.xml.template b/nova/virt/libvirt.rescue.xen.xml.template deleted file mode 100644 index 3b8d27237..000000000 --- a/nova/virt/libvirt.rescue.xen.xml.template +++ /dev/null @@ -1,34 +0,0 @@ - - %(name)s - - linux - %(basepath)s/kernel - %(basepath)s/ramdisk - /dev/xvda1 - ro - - - - - %(memory_kb)s - %(vcpus)s - - - - - - - - - - - - - - - - - - - - diff --git a/nova/virt/libvirt.uml.xml.template b/nova/virt/libvirt.uml.xml.template deleted file mode 100644 index da9588049..000000000 --- a/nova/virt/libvirt.uml.xml.template +++ /dev/null @@ -1,26 +0,0 @@ - - ${name} - ${memory_kb} - - ${type} - /usr/bin/linux - /dev/ubda1 - - - - - - - - - - - - - - - - - - - diff --git a/nova/virt/libvirt.xen.xml.template b/nova/virt/libvirt.xen.xml.template deleted file mode 100644 index 8f650e512..000000000 --- a/nova/virt/libvirt.xen.xml.template +++ /dev/null @@ -1,35 +0,0 @@ - - ${name} - - linux -#if $getVar('kernel', None) - ${kernel} - #if $getVar('ramdisk', None) - ${ramdisk} - #end if - root=/dev/vda1 console=ttyS0 -#end if - /dev/xvda1 - ro - - - - - ${memory_kb} - ${vcpus} - - - - - - - - - - - - - - - - diff --git a/nova/virt/libvirt.xml.template b/nova/virt/libvirt.xml.template new file mode 100644 index 000000000..13d087330 --- /dev/null +++ b/nova/virt/libvirt.xml.template @@ -0,0 +1,76 @@ + + ${name} + ${memory_kb} + +#if $type == 'uml' + #set $disk_prefix = 'ubd' + #set $disk_bus = 'uml' + uml + /usr/bin/linux + /dev/ubda1 +#else + #if $type == 'xen' + #set $disk_prefix = 'sd' + #set $disk_bus = 'scsi' + linux + /dev/xvda1 + #else + #set $disk_prefix = 'vd' + #set $disk_bus = 'virtio' + hvm + #end if + #if $getVar('rescue', False) + ${basepath}/rescue-kernel + ${basepath}/rescue-ramdisk + #else + #if $getVar('kernel', None) + ${kernel} + #if $type == 'xen' + ro + #else + root=/dev/vda1 console=ttyS0 + #end if + #if $getVar('ramdisk', None) + ${ramdisk} + #end if + #else + + #end if + #end if +#end if + + + + + ${vcpus} + +#if $getVar('rescue', False) + + + + + + + + +#else + + + + +#end if + + + + + + + + + + + + + + + diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 81dbbaad5..2865c18ac 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -27,12 +27,7 @@ Supports KVM, QEMU, UML, and XEN. :libvirt_type: Libvirt domain type. Can be kvm, qemu, uml, xen (default: kvm). :libvirt_uri: Override for the default libvirt URI (depends on libvirt_type). -:libvirt_xml_template: Libvirt XML Template (QEmu/KVM). -:libvirt_xen_xml_template: Libvirt XML Template (Xen). -:libvirt_uml_xml_template: Libvirt XML Template (User Mode Linux). -:libvirt_rescue_xml_template: XML template for rescue mode (KVM & QEMU). -:libvirt_rescue_xen_xml_template: XML templage for rescue mode (XEN). -:libvirt_rescue_uml_xml_template: XML template for rescue mode (UML). +:libvirt_xml_template: Libvirt XML Template. :rescue_image_id: Rescue ami image (default: ami-rescue). :rescue_kernel_id: Rescue aki image (default: aki-rescue). :rescue_ramdisk_id: Rescue ari image (default: ari-rescue). @@ -70,31 +65,13 @@ libxml2 = None FLAGS = flags.FLAGS -flags.DEFINE_string('libvirt_rescue_xml_template', - utils.abspath('virt/libvirt.rescue.qemu.xml.template'), - 'Libvirt RESCUE XML Template for QEmu/KVM') -flags.DEFINE_string('libvirt_rescue_xen_xml_template', - utils.abspath('virt/libvirt.rescue.xen.xml.template'), - 'Libvirt RESCUE XML Template for xen') -flags.DEFINE_string('libvirt_rescue_uml_xml_template', - utils.abspath('virt/libvirt.rescue.uml.xml.template'), - 'Libvirt RESCUE XML Template for user-mode-linux') # TODO(vish): These flags should probably go into a shared location flags.DEFINE_string('rescue_image_id', 'ami-rescue', 'Rescue ami image') flags.DEFINE_string('rescue_kernel_id', 'aki-rescue', 'Rescue aki image') flags.DEFINE_string('rescue_ramdisk_id', 'ari-rescue', 'Rescue ari image') flags.DEFINE_string('libvirt_xml_template', - utils.abspath('virt/libvirt.qemu.xml.template'), - 'Libvirt XML Template for QEmu/KVM') -flags.DEFINE_string('libvirt_xen_xml_template', - utils.abspath('virt/libvirt.xen.xml.template'), - 'Libvirt XML Template for Xen') -flags.DEFINE_string('libvirt_uml_xml_template', - utils.abspath('virt/libvirt.uml.xml.template'), - 'Libvirt XML Template for user-mode-linux') -flags.DEFINE_string('injected_network_template', - utils.abspath('virt/interfaces.template'), - 'Template file for injected network') + utils.abspath('virt/libvirt.xml.template'), + 'Libvirt XML Template') flags.DEFINE_string('libvirt_type', 'kvm', 'Libvirt domain type (valid options are: ' @@ -122,12 +99,9 @@ def get_connection(read_only): class LibvirtConnection(object): def __init__(self, read_only): - (self.libvirt_uri, - template_file, - rescue_file) = self.get_uri_and_templates() + self.libvirt_uri = self.get_uri() - self.libvirt_xml = open(template_file).read() - self.rescue_xml = open(rescue_file).read() + self.libvirt_xml = open(FLAGS.libvirt_xml_template).read() self._wrapped_conn = None self.read_only = read_only @@ -150,20 +124,14 @@ class LibvirtConnection(object): return False raise - def get_uri_and_templates(self): + def get_uri(self): if FLAGS.libvirt_type == 'uml': uri = FLAGS.libvirt_uri or 'uml:///system' - template_file = FLAGS.libvirt_uml_xml_template - rescue_file = FLAGS.libvirt_rescue_uml_xml_template elif FLAGS.libvirt_type == 'xen': uri = FLAGS.libvirt_uri or 'xen:///' - template_file = FLAGS.libvirt_xen_xml_template - rescue_file = FLAGS.libvirt_rescue_xen_xml_template else: uri = FLAGS.libvirt_uri or 'qemu:///system' - template_file = FLAGS.libvirt_xml_template - rescue_file = FLAGS.libvirt_rescue_xml_template - return uri, template_file, rescue_file + return uri def _connect(self, uri, read_only): auth = [[libvirt.VIR_CRED_AUTHNAME, libvirt.VIR_CRED_NOECHOPROMPT], @@ -543,18 +511,16 @@ class LibvirtConnection(object): 'bridge_name': network['bridge'], 'mac_address': instance['mac_address'], 'ip_address': ip_address, - 'dhcp_server': dhcp_server} - if rescue: - xml = self.rescue_xml % xml_info - else: - if xml_info['kernel_id']: + 'dhcp_server': dhcp_server, + 'rescue': rescue} + if not rescue: + if instance['kernel_id']: xml_info['kernel'] = xml_info['basepath'] + "/kernel" - if xml_info['ramdisk_id']: + if instance['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" + xml_info['disk'] = xml_info['basepath'] + "/disk" xml = str(Template(self.libvirt_xml, searchList=[xml_info])) logging.debug('instance %s: finished toXML method', instance['name']) -- 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 +++++++ nova/virt/libvirt_conn.py | 21 +++++++++++++-------- 2 files changed, 20 insertions(+), 8 deletions(-) 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): diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 5dcb05b1f..3529be333 100644 --- a/nova/virt/libvirt_conn.py +++ b/nova/virt/libvirt_conn.py @@ -421,13 +421,13 @@ class LibvirtConnection(object): yield images.fetch(inst.image_id, basepath('disk-raw'), user, project) - if inst.kernel_id: + if inst['kernel_id']: if not os.path.exists(basepath('kernel')): - yield images.fetch(inst.kernel_id, basepath('kernel'), + yield images.fetch(inst['kernel_id'], basepath('kernel'), user, project) - if inst.ramdisk_id: + if inst['ramdisk_id']: if not os.path.exists(basepath('ramdisk')): - yield images.fetch(inst.ramdisk_id, basepath('ramdisk'), + yield images.fetch(inst['ramdisk_id'], basepath('ramdisk'), user, project) execute = lambda cmd, process_input = None, check_exit_code = True: \ @@ -439,7 +439,7 @@ class LibvirtConnection(object): # partitioned disk image where the target partition is the first # partition target_partition = None - if not inst.kernel_id: + if not inst['kernel_id']: target_partition = "1" key = str(inst['key_data']) @@ -472,7 +472,7 @@ class LibvirtConnection(object): ' into image %s (%s)', inst['name'], inst.image_id, e) - if inst.kernel_id: + if inst['kernel_id']: if os.path.exists(basepath('disk')): yield process.simple_execute('rm -f %s' % basepath('disk')) @@ -483,8 +483,13 @@ class LibvirtConnection(object): resize = True if inst['instance_type'] == 'm1.tiny' or prefix == 'rescue-': resize = False - yield disk.partition(basepath('disk-raw'), basepath('disk'), - local_bytes, resize, execute=execute) + + if inst['kernel_id']: + yield disk.partition(basepath('disk-raw'), basepath('disk'), + local_bytes, resize, execute=execute) + else: + os.rename(basepath('disk-raw'), basepath('disk')) + yield disk.extend(basepath('disk'), local_bytes, execute=execute) if FLAGS.libvirt_type == 'uml': yield process.simple_execute('sudo chown root %s' % -- cgit From 9c2fa95298000c0c9d3953f0ef87823ed604949a Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Tue, 14 Dec 2010 23:35:54 +0100 Subject: Remove default_{kernel,ramdisk} flags. They are not used anymore. --- nova/flags.py | 4 ---- 1 file changed, 4 deletions(-) diff --git a/nova/flags.py b/nova/flags.py index 45f5d7469..5c265f4ea 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -228,10 +228,6 @@ DEFINE_string('ec2_url', 'http://127.0.0.1:8773/services/Cloud', DEFINE_string('default_image', 'ami-11111', 'default image to use, testing only') -DEFINE_string('default_kernel', 'aki-11111', - 'default kernel to use, testing only') -DEFINE_string('default_ramdisk', 'ari-11111', - 'default ramdisk to use, testing only') DEFINE_string('default_instance_type', 'm1.small', 'default instance type to use, testing only') DEFINE_string('null_kernel', 'nokernel', -- cgit From e84f46e739c56b7ae186866f33c713a0ac98e770 Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Wed, 15 Dec 2010 13:15:19 +0100 Subject: Make sure the new, consolidated template gets included. --- MANIFEST.in | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MANIFEST.in b/MANIFEST.in index 982b727aa..199ce30b6 100644 --- a/MANIFEST.in +++ b/MANIFEST.in @@ -13,7 +13,7 @@ include nova/cloudpipe/client.ovpn.template include nova/compute/fakevirtinstance.xml include nova/compute/interfaces.template include nova/virt/interfaces.template -include nova/virt/libvirt.*.xml.template +include nova/virt/libvirt*.xml.template include nova/tests/CA/ include nova/tests/CA/cacert.pem include nova/tests/CA/private/ -- 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(+) 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 9b5d8600ab3cadd5f3174056eaedd0db420f1f1b Mon Sep 17 00:00:00 2001 From: Soren Hansen Date: Mon, 20 Dec 2010 22:53:07 +0100 Subject: Add my @linux2go.dk address to .mailmap --- .mailmap | 1 + 1 file changed, 1 insertion(+) diff --git a/.mailmap b/.mailmap index 2a6eb8d7d..8041e2341 100644 --- a/.mailmap +++ b/.mailmap @@ -19,6 +19,7 @@ + -- cgit