diff options
| author | Justin Santa Barbara <justinsb@justinsb-desktop> | 2010-12-20 22:04:12 +0000 |
|---|---|---|
| committer | Tarmac <> | 2010-12-20 22:04:12 +0000 |
| commit | 086f2d87be3c56ac8dafaf4551096868d57454db (patch) | |
| tree | 453594019a5a5306b0712e8da5ba21cbc1a3848d | |
| parent | 85b07de25094b35928f2b67d1be11748e2af6713 (diff) | |
| parent | 9b5d8600ab3cadd5f3174056eaedd0db420f1f1b (diff) | |
Add raw disk image support.
| -rw-r--r-- | .mailmap | 1 | ||||
| -rw-r--r-- | MANIFEST.in | 2 | ||||
| -rw-r--r-- | nova/api/ec2/cloud.py | 2 | ||||
| -rw-r--r-- | nova/compute/api.py | 17 | ||||
| -rw-r--r-- | nova/compute/disk.py | 22 | ||||
| -rw-r--r-- | nova/flags.py | 7 | ||||
| -rw-r--r-- | nova/tests/virt_unittest.py | 132 | ||||
| -rw-r--r-- | nova/virt/libvirt.qemu.xml.template | 33 | ||||
| -rw-r--r-- | nova/virt/libvirt.rescue.qemu.xml.template | 37 | ||||
| -rw-r--r-- | nova/virt/libvirt.rescue.uml.xml.template | 26 | ||||
| -rw-r--r-- | nova/virt/libvirt.rescue.xen.xml.template | 34 | ||||
| -rw-r--r-- | nova/virt/libvirt.uml.xml.template | 26 | ||||
| -rw-r--r-- | nova/virt/libvirt.xen.xml.template | 30 | ||||
| -rw-r--r-- | nova/virt/libvirt.xml.template | 76 | ||||
| -rw-r--r-- | nova/virt/libvirt_conn.py | 118 | ||||
| -rw-r--r-- | tools/pip-requires | 1 |
16 files changed, 280 insertions, 284 deletions
@@ -19,6 +19,7 @@ <mordred@inaugust.com> <mordred@hudson> <paul@openstack.org> <pvoccio@castor.local> <paul@openstack.org> <paul.voccio@rackspace.com> +<soren.hansen@rackspace.com> <soren@linux2go.dk> <todd@ansolabs.com> <todd@lapex> <todd@ansolabs.com> <todd@rubidine.com> <vishvananda@gmail.com> <vishvananda@yahoo.com> 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/ diff --git a/nova/api/ec2/cloud.py b/nova/api/ec2/cloud.py index ebb13aedc..8375c4399 100644 --- a/nova/api/ec2/cloud.py +++ b/nova/api/ec2/cloud.py @@ -751,7 +751,7 @@ class CloudController(object): kwargs['image_id'], min_count=int(kwargs.get('min_count', max_count)), max_count=max_count, - kernel_id=kwargs.get('kernel_id'), + kernel_id=kwargs.get('kernel_id', None), ramdisk_id=kwargs.get('ramdisk_id'), display_name=kwargs.get('display_name'), description=kwargs.get('display_description'), diff --git a/nova/compute/api.py b/nova/compute/api.py index 7420c40d2..c740814da 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, diff --git a/nova/compute/disk.py b/nova/compute/disk.py index 675cd0259..0169a9831 100644 --- a/nova/compute/disk.py +++ b/nova/compute/disk.py @@ -106,6 +106,13 @@ def partition(infile, outfile, local_bytes=0, resize=True, % (outfile, local_type, local_first, local_last)) +def extend(image, size, execute): + file_size = os.path.getsize(image) + if file_size >= size: + return + return execute('truncate -s size %s' % (image,)) + + def inject_data(image, key=None, net=None, partition=None, execute=None): """Injects a ssh key and optionally net data into a disk image. @@ -115,7 +122,7 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): If partition is not specified it mounts the image as a single partition. """ - out, err = execute('sudo losetup -f --show %s' % image) + out, err = execute('sudo losetup --find --show %s' % image) if err: raise exception.Error('Could not attach image to loopback: %s' % err) device = out.strip() @@ -129,6 +136,15 @@ def inject_data(image, key=None, net=None, partition=None, execute=None): partition) else: mapped_device = device + + # We can only loopback mount raw images. If the device isn't there, + # it's normally because it's a .vmdk or a .vdi etc + if not os.path.exists(mapped_device): + raise exception.Error('Mapped device was not found (we can' + ' only inject raw disk images): %s' % + mapped_device) + + # Configure ext2fs so that it doesn't auto-check every N boots out, err = execute('sudo tune2fs -c 0 -i 0 %s' % mapped_device) tmpdir = tempfile.mkdtemp() @@ -156,7 +172,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 +181,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/flags.py b/nova/flags.py index 87444565a..8fa0beb7a 100644 --- a/nova/flags.py +++ b/nova/flags.py @@ -235,12 +235,11 @@ 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', + '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/tests/virt_unittest.py b/nova/tests/virt_unittest.py index 85e569858..9bbba4ba9 100644 --- a/nova/tests/virt_unittest.py +++ b/nova/tests/virt_unittest.py @@ -40,19 +40,51 @@ class LibvirtConnTestCase(test.TestCase): 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 +92,14 @@ class LibvirtConnTestCase(test.TestCase): self.network.set_network_host(context.get_admin_context(), network_ref['id']) - fixed_ip = {'address': ip, + 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 +111,71 @@ class LibvirtConnTestCase(test.TestCase): (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 +187,9 @@ class LibvirtConnTestCase(test.TestCase): 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 +198,7 @@ class LibvirtConnTestCase(test.TestCase): 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 2538b1ade..000000000 --- a/nova/virt/libvirt.qemu.xml.template +++ /dev/null @@ -1,33 +0,0 @@ -<domain type='%(type)s'> - <name>%(name)s</name> - <os> - <type>hvm</type> - <kernel>%(basepath)s/kernel</kernel> - <initrd>%(basepath)s/ramdisk</initrd> - <cmdline>root=/dev/vda1 console=ttyS0</cmdline> - </os> - <features> - <acpi/> - </features> - <memory>%(memory_kb)s</memory> - <vcpu>%(vcpus)s</vcpu> - <devices> - <disk type='file'> - <source file='%(basepath)s/disk'/> - <target dev='vda' bus='virtio'/> - </disk> - <interface type='bridge'> - <source bridge='%(bridge_name)s'/> - <mac address='%(mac_address)s'/> - <!-- <model type='virtio'/> CANT RUN virtio network right now --> - <filterref filter="nova-instance-%(name)s"> - <parameter name="IP" value="%(ip_address)s" /> - <parameter name="DHCPSERVER" value="%(dhcp_server)s" /> - </filterref> - </interface> - <serial type="file"> - <source path='%(basepath)s/console.log'/> - <target port='1'/> - </serial> - </devices> -</domain> 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 @@ -<domain type='%(type)s'> - <name>%(name)s</name> - <os> - <type>hvm</type> - <kernel>%(basepath)s/rescue-kernel</kernel> - <initrd>%(basepath)s/rescue-ramdisk</initrd> - <cmdline>root=/dev/vda1 console=ttyS0</cmdline> - </os> - <features> - <acpi/> - </features> - <memory>%(memory_kb)s</memory> - <vcpu>%(vcpus)s</vcpu> - <devices> - <disk type='file'> - <source file='%(basepath)s/rescue-disk'/> - <target dev='vda' bus='virtio'/> - </disk> - <disk type='file'> - <source file='%(basepath)s/disk'/> - <target dev='vdb' bus='virtio'/> - </disk> - <interface type='bridge'> - <source bridge='%(bridge_name)s'/> - <mac address='%(mac_address)s'/> - <!-- <model type='virtio'/> CANT RUN virtio network right now --> - <filterref filter="nova-instance-%(name)s"> - <parameter name="IP" value="%(ip_address)s" /> - <parameter name="DHCPSERVER" value="%(dhcp_server)s" /> - </filterref> - </interface> - <serial type="file"> - <source path='%(basepath)s/console.log'/> - <target port='1'/> - </serial> - </devices> -</domain> 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 @@ -<domain type='%(type)s'> - <name>%(name)s</name> - <memory>%(memory_kb)s</memory> - <os> - <type>%(type)s</type> - <kernel>/usr/bin/linux</kernel> - <root>/dev/ubda1</root> - </os> - <devices> - <disk type='file'> - <source file='%(basepath)s/rescue-disk'/> - <target dev='ubd0' bus='uml'/> - </disk> - <disk type='file'> - <source file='%(basepath)s/disk'/> - <target dev='ubd1' bus='uml'/> - </disk> - <interface type='bridge'> - <source bridge='%(bridge_name)s'/> - <mac address='%(mac_address)s'/> - </interface> - <console type="file"> - <source path='%(basepath)s/console.log'/> - </console> - </devices> -</domain> 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 @@ -<domain type='%(type)s'> - <name>%(name)s</name> - <os> - <type>linux</type> - <kernel>%(basepath)s/kernel</kernel> - <initrd>%(basepath)s/ramdisk</initrd> - <root>/dev/xvda1</root> - <cmdline>ro</cmdline> - </os> - <features> - <acpi/> - </features> - <memory>%(memory_kb)s</memory> - <vcpu>%(vcpus)s</vcpu> - <devices> - <disk type='file'> - <source file='%(basepath)s/rescue-disk'/> - <target dev='sda' /> - </disk> - <disk type='file'> - <source file='%(basepath)s/disk'/> - <target dev='sdb' /> - </disk> - <interface type='bridge'> - <source bridge='%(bridge_name)s'/> - <mac address='%(mac_address)s'/> - </interface> - <console type="file"> - <source path='%(basepath)s/console.log'/> - <target port='1'/> - </console> - </devices> -</domain> - diff --git a/nova/virt/libvirt.uml.xml.template b/nova/virt/libvirt.uml.xml.template deleted file mode 100644 index bb8b47911..000000000 --- a/nova/virt/libvirt.uml.xml.template +++ /dev/null @@ -1,26 +0,0 @@ -<domain type='%(type)s'> - <name>%(name)s</name> - <memory>%(memory_kb)s</memory> - <os> - <type>%(type)s</type> - <kernel>/usr/bin/linux</kernel> - <root>/dev/ubda1</root> - </os> - <devices> - <disk type='file'> - <source file='%(basepath)s/disk'/> - <target dev='ubd0' bus='uml'/> - </disk> - <interface type='bridge'> - <source bridge='%(bridge_name)s'/> - <mac address='%(mac_address)s'/> - <filterref filter="nova-instance-%(name)s"> - <parameter name="IP" value="%(ip_address)s" /> - <parameter name="DHCPSERVER" value="%(dhcp_server)s" /> - </filterref> - </interface> - <console type="file"> - <source path='%(basepath)s/console.log'/> - </console> - </devices> -</domain> diff --git a/nova/virt/libvirt.xen.xml.template b/nova/virt/libvirt.xen.xml.template deleted file mode 100644 index 9677902c6..000000000 --- a/nova/virt/libvirt.xen.xml.template +++ /dev/null @@ -1,30 +0,0 @@ -<domain type='%(type)s'> - <name>%(name)s</name> - <os> - <type>linux</type> - <kernel>%(basepath)s/kernel</kernel> - <initrd>%(basepath)s/ramdisk</initrd> - <root>/dev/xvda1</root> - <cmdline>ro</cmdline> - </os> - <features> - <acpi/> - </features> - <memory>%(memory_kb)s</memory> - <vcpu>%(vcpus)s</vcpu> - <devices> - <disk type='file'> - <source file='%(basepath)s/disk'/> - <target dev='sda' /> - </disk> - <interface type='bridge'> - <source bridge='%(bridge_name)s'/> - <mac address='%(mac_address)s'/> - </interface> - <console type="file"> - <source path='%(basepath)s/console.log'/> - <target port='1'/> - </console> - </devices> -</domain> - 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 @@ +<domain type='${type}'> + <name>${name}</name> + <memory>${memory_kb}</memory> + <os> +#if $type == 'uml' + #set $disk_prefix = 'ubd' + #set $disk_bus = 'uml' + <type>uml</type> + <kernel>/usr/bin/linux</kernel> + <root>/dev/ubda1</root> +#else + #if $type == 'xen' + #set $disk_prefix = 'sd' + #set $disk_bus = 'scsi' + <type>linux</type> + <root>/dev/xvda1</root> + #else + #set $disk_prefix = 'vd' + #set $disk_bus = 'virtio' + <type>hvm</type> + #end if + #if $getVar('rescue', False) + <kernel>${basepath}/rescue-kernel</kernel> + <initrd>${basepath}/rescue-ramdisk</initrd> + #else + #if $getVar('kernel', None) + <kernel>${kernel}</kernel> + #if $type == 'xen' + <cmdline>ro</cmdline> + #else + <cmdline>root=/dev/vda1 console=ttyS0</cmdline> + #end if + #if $getVar('ramdisk', None) + <initrd>${ramdisk}</initrd> + #end if + #else + <boot dev="hd" /> + #end if + #end if +#end if + </os> + <features> + <acpi/> + </features> + <vcpu>${vcpus}</vcpu> + <devices> +#if $getVar('rescue', False) + <disk type='file'> + <source file='${basepath}/rescue-disk'/> + <target dev='${disk_prefix}a' bus='${disk_bus}'/> + </disk> + <disk type='file'> + <source file='${basepath}/disk'/> + <target dev='${disk_prefix}b' bus='${disk_bus}'/> + </disk> +#else + <disk type='file'> + <source file='${basepath}/disk'/> + <target dev='${disk_prefix}a' bus='${disk_bus}'/> + </disk> +#end if + <interface type='bridge'> + <source bridge='${bridge_name}'/> + <mac address='${mac_address}'/> + <!-- <model type='virtio'/> CANT RUN virtio network right now --> + <filterref filter="nova-instance-${name}"> + <parameter name="IP" value="${ip_address}" /> + <parameter name="DHCPSERVER" value="${dhcp_server}" /> + </filterref> + </interface> + <serial type="file"> + <source path='${basepath}/console.log'/> + <target port='1'/> + </serial> + </devices> +</domain> diff --git a/nova/virt/libvirt_conn.py b/nova/virt/libvirt_conn.py index 14ec0c877..ad101db2a 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). @@ -62,36 +57,20 @@ from nova.compute import instance_types from nova.compute import power_state from nova.virt import images +from Cheetah.Template import Template + libvirt = None 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: ' @@ -120,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 @@ -148,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], @@ -442,18 +412,28 @@ class LibvirtConnection(object): if not os.path.exists(basepath('disk')): images.fetch(inst.image_id, basepath('disk-raw'), user, project) - if not os.path.exists(basepath('kernel')): - images.fetch(inst.kernel_id, basepath('kernel'), user, - project) - if not os.path.exists(basepath('ramdisk')): - images.fetch(inst.ramdisk_id, basepath('ramdisk'), user, - project) + + if inst['kernel_id']: + if not os.path.exists(basepath('kernel')): + images.fetch(inst['kernel_id'], basepath('kernel'), + user, project) + if inst['ramdisk_id']: + if not os.path.exists(basepath('ramdisk')): + images.fetch(inst['ramdisk_id'], basepath('ramdisk'), + user, project) def execute(cmd, process_input=None, check_exit_code=True): return utils.execute(cmd=cmd, 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 + # partition + target_partition = None + if not inst['kernel_id']: + target_partition = "1" + key = str(inst['key_data']) net = None network_ref = db.network_get_by_instance(context.get_admin_context(), @@ -473,12 +453,20 @@ class LibvirtConnection(object): inst['name'], inst.image_id) if net: logging.info('instance %s: injecting net into image %s', - inst['name'], inst.image_id) - disk.inject_data(basepath('disk-raw'), key, net, - execute=execute) - - if os.path.exists(basepath('disk')): - utils.execute('rm -f %s' % basepath('disk')) + inst['name'], inst.image_id) + try: + disk.inject_data(basepath('disk-raw'), key, net, + partition=target_partition, + execute=execute) + except Exception as e: + # This could be a windows image, or a vmdk format disk + logging.warn('instance %s: ignoring error injecting data' + ' into image %s (%s)', + inst['name'], inst.image_id, e) + + if inst['kernel_id']: + if os.path.exists(basepath('disk')): + utils.execute('rm -f %s' % basepath('disk')) local_bytes = (instance_types.INSTANCE_TYPES[inst.instance_type] ['local_gb'] @@ -487,8 +475,13 @@ class LibvirtConnection(object): resize = True if inst['instance_type'] == 'm1.tiny' or prefix == 'rescue-': resize = False - disk.partition(basepath('disk-raw'), basepath('disk'), - local_bytes, resize, execute=execute) + + if inst['kernel_id']: + disk.partition(basepath('disk-raw'), basepath('disk'), + local_bytes, resize, execute=execute) + else: + os.rename(basepath('disk-raw'), basepath('disk')) + disk.extend(basepath('disk'), local_bytes, execute=execute) if FLAGS.libvirt_type == 'uml': utils.execute('sudo chown root %s' % basepath('disk')) @@ -514,14 +507,21 @@ class LibvirtConnection(object): 'bridge_name': network['bridge'], 'mac_address': instance['mac_address'], 'ip_address': ip_address, - 'dhcp_server': dhcp_server} - if rescue: - libvirt_xml = self.rescue_xml % xml_info - else: - libvirt_xml = self.libvirt_xml % xml_info + 'dhcp_server': dhcp_server, + 'rescue': rescue} + if not rescue: + if instance['kernel_id']: + xml_info['kernel'] = xml_info['basepath'] + "/kernel" + + if instance['ramdisk_id']: + xml_info['ramdisk'] = xml_info['basepath'] + "/ramdisk" + + 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']) - return libvirt_xml + return xml def get_info(self, instance_name): try: diff --git a/tools/pip-requires b/tools/pip-requires index 52451b8cb..e9559521b 100644 --- a/tools/pip-requires +++ b/tools/pip-requires @@ -2,6 +2,7 @@ SQLAlchemy==0.6.3 pep8==0.5.0 pylint==0.19 IPy==0.70 +Cheetah==2.4.2.1 M2Crypto==0.20.2 amqplib==0.6.1 anyjson==0.2.4 |
