From 41e4e18a0324593c0076c3936d63bb6dcca487cb Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Mon, 14 Feb 2011 23:12:34 +0000 Subject: First cut on XenServer unified-images --- nova/virt/xenapi/vm_utils.py | 47 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 43 insertions(+), 4 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 4bbd522c1..6d6067da5 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -266,7 +266,9 @@ class VMHelper(HelperBase): session, instance_id, sr_ref, vm_vdi_ref, original_parent_uuid) #TODO(sirp): we need to assert only one parent, not parents two deep - return template_vm_ref, [template_vdi_uuid, parent_uuid] + template_vdi_uuids = {'image': parent_uuid, + 'snap': template_vdi_uuid} + return template_vm_ref, template_vdi_uuids @classmethod def upload_image(cls, session, instance_id, vdi_uuids, image_id): @@ -303,15 +305,36 @@ class VMHelper(HelperBase): return cls._fetch_image_objectstore(session, instance_id, image, access, user.secret, type) + @classmethod - def _fetch_image_glance(cls, session, instance_id, image, access, type): + def _fetch_image_glance_vhd(cls, session, instance_id, image, access, type): + LOG.debug(_("Asking xapi to fetch vhd image %(image)s") + % locals()) + + sr_ref = find_sr(session) + if sr_ref is None: + raise exception.NotFound('Cannot find SR to write VDI to') + + params = {'image_id': image, + 'glance_host': FLAGS.glance_host, + 'glance_port': FLAGS.glance_port} + + kwargs = {'params': pickle.dumps(params)} + task = session.async_call_plugin('glance', 'get_vdi', kwargs) + vdi_uuid = session.wait_for_task(instance_id, task) + scan_sr(session, instance_id, sr_ref) + LOG.debug(_("Xapi 'get_vdi' returned VDI UUID %(vdi_uuid)s") % locals()) + return vdi_uuid + + @classmethod + def _fetch_image_glance_disk(cls, session, instance_id, image, access, type): sr = find_sr(session) if sr is None: raise exception.NotFound('Cannot find SR to write VDI to') - c = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) + client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) - meta, image_file = c.get_image(image) + meta, image_file = client.get_image(image) virtual_size = int(meta['size']) vdi_size = virtual_size LOG.debug(_("Size for image %(image)s:%(virtual_size)d") % locals()) @@ -344,6 +367,22 @@ class VMHelper(HelperBase): else: return session.get_xenapi().VDI.get_uuid(vdi) + @classmethod + def _fetch_image_glance(cls, session, instance_id, image, access, type): + client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) + meta = client.get_image_meta(image) + properties = meta['properties'] + disk_format = properties.get('disk_format', None) + + # TODO(sirp): When Glance treats disk_format as a first class + # attribute, we should start using that rather than an image-property + if disk_format == 'vhd': + return cls._fetch_image_glance_vhd( + session, instance_id, image, access, type) + else: + return cls._fetch_image_glance_disk( + session, instance_id, image, access, type) + @classmethod def _fetch_image_objectstore(cls, session, instance_id, image, access, secret, type): -- cgit From fe6efb38ee30c5a3e532cd19faef0fec063b7446 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 01:37:54 +0000 Subject: Adding DISK_VHD to ImageTypes --- nova/virt/xenapi/vm_utils.py | 38 ++++++++++++++++++++++++++++++-------- nova/virt/xenapi/vmops.py | 22 +++++++++++++++------- 2 files changed, 45 insertions(+), 15 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 6d6067da5..a6312d00c 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -63,11 +63,14 @@ class ImageType: 0 - kernel/ramdisk image (goes on dom0's filesystem) 1 - disk image (local SR, partitioned by objectstore plugin) 2 - raw disk image (local SR, NOT partitioned by plugin) + 3 - vhd disk image (local SR, NOT inspected by XS, PV assumed for + linux, HVM assumed for Windows) """ KERNEL_RAMDISK = 0 DISK = 1 DISK_RAW = 2 + DISK_VHD = 3 class VMHelper(HelperBase): @@ -368,15 +371,34 @@ class VMHelper(HelperBase): return session.get_xenapi().VDI.get_uuid(vdi) @classmethod - def _fetch_image_glance(cls, session, instance_id, image, access, type): - client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) - meta = client.get_image_meta(image) - properties = meta['properties'] - disk_format = properties.get('disk_format', None) + def determine_disk_image_type(cls, instance): + instance_id = instance.id + if instance.kernel_id: + #if kernel is not present we must download a raw disk + LOG.debug(_("Instance %(instance_id)s will use DISK format") % + locals()) + return ImageType.DISK - # TODO(sirp): When Glance treats disk_format as a first class - # attribute, we should start using that rather than an image-property - if disk_format == 'vhd': + if FLAGS.xenapi_image_service == 'glance': + # if using glance, then we could be VHD format + client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) + meta = client.get_image_meta(instance.image_id) + properties = meta['properties'] + disk_format = properties.get('disk_format', None) + # TODO(sirp): When Glance treats disk_format as a first class + # attribute, we should start using that rather than an image-property + if disk_format == 'vhd': + LOG.debug(_("Instance %(instance_id)s will use DISK_VHD format") % + locals()) + return ImageType.DISK_VHD + + LOG.debug(_("Instance %(instance_id)s will use DISK_RAW format") % + locals()) + return ImageType.DISK_RAW + + @classmethod + def _fetch_image_glance(cls, session, instance_id, image, access, type): + if type == ImageType.DISK_VHD: return cls._fetch_image_glance_vhd( session, instance_id, image, access, type) else: diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index e84ce20c4..34ceea358 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -74,27 +74,34 @@ class VMOps(object): user = AuthManager().get_user(instance.user_id) project = AuthManager().get_project(instance.project_id) - #if kernel is not present we must download a raw disk - if instance.kernel_id: - disk_image_type = ImageType.DISK - else: - disk_image_type = ImageType.DISK_RAW + + disk_image_type = VMHelper.determine_disk_image_type(instance) + vdi_uuid = VMHelper.fetch_image(self._session, instance.id, instance.image_id, user, project, disk_image_type) + vdi_ref = self._session.call_xenapi('VDI.get_by_uuid', vdi_uuid) - #Have a look at the VDI and see if it has a PV kernel + pv_kernel = False - if not instance.kernel_id: + if disk_image_type == ImageType.DISK_RAW: + #Have a look at the VDI and see if it has a PV kernel pv_kernel = VMHelper.lookup_image(self._session, instance.id, vdi_ref) + elif disk_image_type == ImageType.DISK_VHD: + # TODO(sirp): Assuming PV for now; this will need to be + # configurable as Windows will use HVM. + pv_kernel = True + kernel = None if instance.kernel_id: kernel = VMHelper.fetch_image(self._session, instance.id, instance.kernel_id, user, project, ImageType.KERNEL_RAMDISK) + ramdisk = None if instance.ramdisk_id: ramdisk = VMHelper.fetch_image(self._session, instance.id, instance.ramdisk_id, user, project, ImageType.KERNEL_RAMDISK) + vm_ref = VMHelper.create_vm(self._session, instance, kernel, ramdisk, pv_kernel) VMHelper.create_vbd(self._session, vm_ref, vdi_ref, 0, True) @@ -102,6 +109,7 @@ class VMOps(object): if network_ref: VMHelper.create_vif(self._session, vm_ref, network_ref, instance.mac_address) + LOG.debug(_('Starting VM %s...'), vm_ref) self._session.call_xenapi('VM.start', vm_ref, False, False) instance_name = instance.name -- cgit From 15cdeef7820aacd0b1ff95da48816cba9f2544ba Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 18:01:13 +0000 Subject: Adding more documentation, code-cleanup --- nova/virt/xenapi/vm_utils.py | 52 ++++++++++++++++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 12 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index a6312d00c..5eab2a38f 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -24,6 +24,7 @@ import pickle import re import time import urllib +import uuid from xml.dom import minidom from eventlet import event @@ -318,9 +319,15 @@ class VMHelper(HelperBase): if sr_ref is None: raise exception.NotFound('Cannot find SR to write VDI to') + # NOTE(sirp): The Glance plugin runs under Python 2.4 which does not + # have the `uuid` module. To work around this, we generate the uuids + # here (under Python 2.6+) and pass them as arguments + uuid_stack = [str(uuid.uuid4()) for i in xrange(2)] + params = {'image_id': image, 'glance_host': FLAGS.glance_host, - 'glance_port': FLAGS.glance_port} + 'glance_port': FLAGS.glance_port, + 'uuid_stack': uuid_stack} kwargs = {'params': pickle.dumps(params)} task = session.async_call_plugin('glance', 'get_vdi', kwargs) @@ -372,14 +379,35 @@ class VMHelper(HelperBase): @classmethod def determine_disk_image_type(cls, instance): - instance_id = instance.id + """Disk Image Types are used to determine where the kernel will reside + within an image. To figure out which type we're dealing with, we use + the following rules: + + 1. If the instance is specifying a kernel explicitly, we must be using + a 'disk' image (kernel outside of the image) + + 2. If the kernel isn't specified, then we have two different + scenarios: + + a) If the image is in Glance, then we can use the 'disk_format' + property to determine if the image is really a VHD-style image + or if it's a RAW image + + b) If the image is not in Glance, then it must be a RAW image + (since we don't have a way of identifying VHD images...yet) + """ + def log_disk_format(disk_format): + disk_format = disk_format.upper() + image_id = instance.image_id + instance_id = instance.id + LOG.debug(_("Detected %(disk_format)s format for image " + "%(image_id)s, instance %(instance_id)s") % locals()) + if instance.kernel_id: - #if kernel is not present we must download a raw disk - LOG.debug(_("Instance %(instance_id)s will use DISK format") % - locals()) + # 1. DISK + log_disk_format('disk') return ImageType.DISK - - if FLAGS.xenapi_image_service == 'glance': + elif FLAGS.xenapi_image_service == 'glance': # if using glance, then we could be VHD format client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) meta = client.get_image_meta(instance.image_id) @@ -388,12 +416,12 @@ class VMHelper(HelperBase): # TODO(sirp): When Glance treats disk_format as a first class # attribute, we should start using that rather than an image-property if disk_format == 'vhd': - LOG.debug(_("Instance %(instance_id)s will use DISK_VHD format") % - locals()) + # 2a. DISK_VHD + log_disk_format('disk_vhd') return ImageType.DISK_VHD - - LOG.debug(_("Instance %(instance_id)s will use DISK_RAW format") % - locals()) + + # 2b. DISK_RAW + log_disk_format('disk_raw') return ImageType.DISK_RAW @classmethod -- cgit From 0fc3a184230c479254b9f713ea61de2f24f680ab Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 18:23:14 +0000 Subject: Moving SR path code outside of glance plugin --- nova/virt/xenapi/vm_utils.py | 21 +++++++++++++++++++-- nova/virt/xenapi_conn.py | 2 ++ 2 files changed, 21 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 5eab2a38f..e73bc7f2b 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -285,7 +285,8 @@ class VMHelper(HelperBase): params = {'vdi_uuids': vdi_uuids, 'image_id': image_id, 'glance_host': FLAGS.glance_host, - 'glance_port': FLAGS.glance_port} + 'glance_port': FLAGS.glance_port, + 'sr_path': get_sr_path(session)} kwargs = {'params': pickle.dumps(params)} task = session.async_call_plugin('glance', 'put_vdis', kwargs) @@ -327,7 +328,8 @@ class VMHelper(HelperBase): params = {'image_id': image, 'glance_host': FLAGS.glance_host, 'glance_port': FLAGS.glance_port, - 'uuid_stack': uuid_stack} + 'uuid_stack': uuid_stack, + 'sr_path': get_sr_path(session)} kwargs = {'params': pickle.dumps(params)} task = session.async_call_plugin('glance', 'get_vdi', kwargs) @@ -685,6 +687,21 @@ def find_sr(session): return None +def get_sr_path(session): + """Return the path to our Storage Repository + + This is used when we're dealing with VHDs directly, either by taking + snapshots or by restoring an image in the DISK_VHD format. + """ + # TODO(sirp): add safe_find_sr + sr_ref = find_sr(session) + if sr_ref is None: + raise Exception('Cannot find SR to read VDI from') + sr_rec = session.get_xenapi().SR.get_record(sr_ref) + sr_uuid = sr_rec["uuid"] + return os.path.join(FLAGS.xenapi_sr_base_path, sr_uuid) + + def remap_vbd_dev(dev): """Return the appropriate location for a plugged-in VBD device diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index a0b0499b8..8ae5684b0 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -100,6 +100,8 @@ flags.DEFINE_integer('xenapi_vhd_coalesce_max_attempts', 5, 'Max number of times to poll for VHD to coalesce.' ' Used only if connection_type=xenapi.') +flags.DEFINE_string('xenapi_sr_base_path', '/var/run/sr-mount', + 'Base path to the storage repository') flags.DEFINE_string('target_host', None, 'iSCSI Target Host') -- cgit From b4b1a7fbd55784157b3084016d4dfe2bd0120e51 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 18:36:17 +0000 Subject: Adding safe_find_sr --- nova/virt/xenapi/vm_utils.py | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index e73bc7f2b..37ce86885 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -316,9 +316,7 @@ class VMHelper(HelperBase): LOG.debug(_("Asking xapi to fetch vhd image %(image)s") % locals()) - sr_ref = find_sr(session) - if sr_ref is None: - raise exception.NotFound('Cannot find SR to write VDI to') + sr_ref = safe_find_sr(session) # NOTE(sirp): The Glance plugin runs under Python 2.4 which does not # have the `uuid` module. To work around this, we generate the uuids @@ -340,16 +338,14 @@ class VMHelper(HelperBase): @classmethod def _fetch_image_glance_disk(cls, session, instance_id, image, access, type): - sr = find_sr(session) - if sr is None: - raise exception.NotFound('Cannot find SR to write VDI to') + sr_ref = safe_find_sr(session) client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) - meta, image_file = client.get_image(image) virtual_size = int(meta['size']) vdi_size = virtual_size LOG.debug(_("Size for image %(image)s:%(virtual_size)d") % locals()) + if type == ImageType.DISK: # Make room for MBR. vdi_size += MBR_SIZE_BYTES @@ -672,7 +668,18 @@ def get_vdi_for_vm_safely(session, vm_ref): return vdi_ref, vdi_rec +def safe_find_sr(session): + """Same as find_sr except raises a NotFound exception if SR cannot be + determined + """ + sr_ref = find_sr(session) + if sr_ref is None: + raise exception.NotFound(_('Cannot find SR to read/write VDI')) + return sr_ref + + def find_sr(session): + """Return the storage repository to hold VM images""" host = session.get_xenapi_host() srs = session.get_xenapi().SR.get_all() for sr in srs: @@ -688,15 +695,12 @@ def find_sr(session): def get_sr_path(session): - """Return the path to our Storage Repository + """Return the path to our storage repository This is used when we're dealing with VHDs directly, either by taking snapshots or by restoring an image in the DISK_VHD format. """ - # TODO(sirp): add safe_find_sr - sr_ref = find_sr(session) - if sr_ref is None: - raise Exception('Cannot find SR to read VDI from') + sr_ref = safe_find_sr(session) sr_rec = session.get_xenapi().SR.get_record(sr_ref) sr_uuid = sr_rec["uuid"] return os.path.join(FLAGS.xenapi_sr_base_path, sr_uuid) -- cgit From acf95a640cfeb0812a55577b6a08bff972ad523b Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 19:17:27 +0000 Subject: Regrouping methods so they make sense --- nova/virt/xenapi/vm_utils.py | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 37ce86885..ba3e5e423 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -289,7 +289,7 @@ class VMHelper(HelperBase): 'sr_path': get_sr_path(session)} kwargs = {'params': pickle.dumps(params)} - task = session.async_call_plugin('glance', 'put_vdis', kwargs) + task = session.async_call_plugin('glance', 'upload_image', kwargs) session.wait_for_task(instance_id, task) @classmethod @@ -310,7 +310,6 @@ class VMHelper(HelperBase): return cls._fetch_image_objectstore(session, instance_id, image, access, user.secret, type) - @classmethod def _fetch_image_glance_vhd(cls, session, instance_id, image, access, type): LOG.debug(_("Asking xapi to fetch vhd image %(image)s") @@ -330,10 +329,10 @@ class VMHelper(HelperBase): 'sr_path': get_sr_path(session)} kwargs = {'params': pickle.dumps(params)} - task = session.async_call_plugin('glance', 'get_vdi', kwargs) + task = session.async_call_plugin('glance', 'download_image', kwargs) vdi_uuid = session.wait_for_task(instance_id, task) scan_sr(session, instance_id, sr_ref) - LOG.debug(_("Xapi 'get_vdi' returned VDI UUID %(vdi_uuid)s") % locals()) + LOG.debug(_("xapi 'download_image' returned VDI UUID %(vdi_uuid)s") % locals()) return vdi_uuid @classmethod -- cgit From c33378fbbe0fd76e807530522715ba4175af18d8 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 21:54:42 +0000 Subject: Fixing typo --- nova/virt/xenapi/vm_utils.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index ba3e5e423..6fa03ee68 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -331,12 +331,24 @@ class VMHelper(HelperBase): kwargs = {'params': pickle.dumps(params)} task = session.async_call_plugin('glance', 'download_image', kwargs) vdi_uuid = session.wait_for_task(instance_id, task) + # TODO(sirp): set name-label on VDI scan_sr(session, instance_id, sr_ref) LOG.debug(_("xapi 'download_image' returned VDI UUID %(vdi_uuid)s") % locals()) return vdi_uuid @classmethod def _fetch_image_glance_disk(cls, session, instance_id, image, access, type): + """Fetch the image from Glance + + NOTE: + Unlike _fetch_image_glance_vhd, this method does not use the Glance + plugin; instead, it streams the disks through domU to the VDI + directly. + + """ + # FIXME(sirp): Since the Glance plugin seems to be required for the VHD disk, + # it may be worth using the plugin for both VHD and RAW and DISK + # restores sr_ref = safe_find_sr(session) client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) @@ -349,7 +361,7 @@ class VMHelper(HelperBase): # Make room for MBR. vdi_size += MBR_SIZE_BYTES - vdi = cls.create_vdi(session, sr, _('Glance image %s') % image, + vdi = cls.create_vdi(session, sr_ref, _('Glance image %s') % image, vdi_size, False) with_vdi_attached_here(session, vdi, False, -- cgit From 24d988263324c9136a1cd9aa5a3a3c4fdf229651 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 22:19:58 +0000 Subject: Set name-label on VDI --- nova/virt/xenapi/vm_utils.py | 17 ++++++++++++++--- 1 file changed, 14 insertions(+), 3 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 6fa03ee68..738372da0 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -331,8 +331,14 @@ class VMHelper(HelperBase): kwargs = {'params': pickle.dumps(params)} task = session.async_call_plugin('glance', 'download_image', kwargs) vdi_uuid = session.wait_for_task(instance_id, task) - # TODO(sirp): set name-label on VDI + scan_sr(session, instance_id, sr_ref) + + # Set the name-label to ease debugging + vdi_ref = session.get_xenapi().VDI.get_by_uuid(vdi_uuid) + name_label = get_name_label_for_image(image) + session.get_xenapi().VDI.set_name_label(vdi_ref, name_label) + LOG.debug(_("xapi 'download_image' returned VDI UUID %(vdi_uuid)s") % locals()) return vdi_uuid @@ -361,8 +367,8 @@ class VMHelper(HelperBase): # Make room for MBR. vdi_size += MBR_SIZE_BYTES - vdi = cls.create_vdi(session, sr_ref, _('Glance image %s') % image, - vdi_size, False) + name_label = get_name_label_for_image(image) + vdi = cls.create_vdi(session, sr_ref, name_label, vdi_size, False) with_vdi_attached_here(session, vdi, False, lambda dev: @@ -848,3 +854,8 @@ def _write_partition(virtual_size, dev): (dest, primary_first, primary_last)) LOG.debug(_('Writing partition table %s done.'), dest) + + +def get_name_label_for_image(image): + # TODO(sirp): This should eventually be the URI for the Glance image + return _('Glance image %s') % image -- cgit From 28ba475d9c32a384570ce6eb0e2f9cfc3dc79a08 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Tue, 15 Feb 2011 22:24:48 +0000 Subject: Pep8 fixes --- nova/virt/xenapi/vm_utils.py | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 738372da0..93009b408 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -311,7 +311,8 @@ class VMHelper(HelperBase): access, user.secret, type) @classmethod - def _fetch_image_glance_vhd(cls, session, instance_id, image, access, type): + def _fetch_image_glance_vhd(cls, session, instance_id, image, access, + type): LOG.debug(_("Asking xapi to fetch vhd image %(image)s") % locals()) @@ -339,11 +340,13 @@ class VMHelper(HelperBase): name_label = get_name_label_for_image(image) session.get_xenapi().VDI.set_name_label(vdi_ref, name_label) - LOG.debug(_("xapi 'download_image' returned VDI UUID %(vdi_uuid)s") % locals()) + LOG.debug(_("xapi 'download_image' returned VDI UUID %(vdi_uuid)s") + % locals()) return vdi_uuid @classmethod - def _fetch_image_glance_disk(cls, session, instance_id, image, access, type): + def _fetch_image_glance_disk(cls, session, instance_id, image, access, + type): """Fetch the image from Glance NOTE: @@ -352,9 +355,9 @@ class VMHelper(HelperBase): directly. """ - # FIXME(sirp): Since the Glance plugin seems to be required for the VHD disk, - # it may be worth using the plugin for both VHD and RAW and DISK - # restores + # FIXME(sirp): Since the Glance plugin seems to be required for the + # VHD disk, it may be worth using the plugin for both VHD and RAW and + # DISK restores sr_ref = safe_find_sr(session) client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) @@ -429,12 +432,13 @@ class VMHelper(HelperBase): properties = meta['properties'] disk_format = properties.get('disk_format', None) # TODO(sirp): When Glance treats disk_format as a first class - # attribute, we should start using that rather than an image-property + # attribute, we should start using that rather than an + # image-property if disk_format == 'vhd': # 2a. DISK_VHD log_disk_format('disk_vhd') return ImageType.DISK_VHD - + # 2b. DISK_RAW log_disk_format('disk_raw') return ImageType.DISK_RAW -- cgit From c56b1814cfae7a9c814b2d37388aff5e772771b6 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Wed, 16 Feb 2011 23:39:12 +0000 Subject: Pep8 fixes --- nova/virt/xenapi/vm_utils.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index d77db2ddb..33945aca3 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -289,6 +289,8 @@ class VMHelper(HelperBase): """ Requests that the Glance plugin bundle the specified VDIs and push them into Glance using the specified human-friendly name. """ + # NOTE(sirp): Currently we only support uploading images as VHD, there + # is no RAW equivalent (yet) logging.debug(_("Asking xapi to upload %(vdi_uuids)s as" " ID %(image_id)s") % locals()) @@ -299,7 +301,7 @@ class VMHelper(HelperBase): 'sr_path': get_sr_path(session)} kwargs = {'params': pickle.dumps(params)} - task = session.async_call_plugin('glance', 'upload_image', kwargs) + task = session.async_call_plugin('glance', 'upload_vhd', kwargs) session.wait_for_task(instance_id, task) @classmethod @@ -340,7 +342,7 @@ class VMHelper(HelperBase): 'sr_path': get_sr_path(session)} kwargs = {'params': pickle.dumps(params)} - task = session.async_call_plugin('glance', 'download_image', kwargs) + task = session.async_call_plugin('glance', 'download_vhd', kwargs) vdi_uuid = session.wait_for_task(instance_id, task) scan_sr(session, instance_id, sr_ref) @@ -350,7 +352,7 @@ class VMHelper(HelperBase): name_label = get_name_label_for_image(image) session.get_xenapi().VDI.set_name_label(vdi_ref, name_label) - LOG.debug(_("xapi 'download_image' returned VDI UUID %(vdi_uuid)s") + LOG.debug(_("xapi 'download_vhd' returned VDI UUID %(vdi_uuid)s") % locals()) return vdi_uuid -- cgit From 04e29f6dc4b13b6fd0cbe5013cf241a727eb56ac Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Thu, 17 Feb 2011 01:24:31 +0000 Subject: Use glance image type to determine disk type --- nova/virt/xenapi/vm_utils.py | 68 +++++++++++++++++++++++--------------------- nova/virt/xenapi/vmops.py | 9 ++++-- 2 files changed, 42 insertions(+), 35 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 33945aca3..278e52211 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -413,47 +413,51 @@ class VMHelper(HelperBase): within an image. To figure out which type we're dealing with, we use the following rules: - 1. If the instance is specifying a kernel explicitly, we must be using - a 'disk' image (kernel outside of the image) + 1. If we're using Glance, we can use the image_type field to + determine the image_type - 2. If the kernel isn't specified, then we have two different - scenarios: - - a) If the image is in Glance, then we can use the 'disk_format' - property to determine if the image is really a VHD-style image - or if it's a RAW image - - b) If the image is not in Glance, then it must be a RAW image - (since we don't have a way of identifying VHD images...yet) + 2. If we're not using Glance, then we need to deduce this based on + whether a kernel_id is specified. """ - def log_disk_format(disk_format): - disk_format = disk_format.upper() + def log_disk_format(image_type): + pretty_format = {ImageType.KERNEL_RAMDISK: 'KERNEL_RAMDISK', + ImageType.DISK: 'DISK', + ImageType.DISK_RAW: 'DISK_RAW', + ImageType.DISK_VHD: 'DISK_VHD'} + disk_format = pretty_format[image_type] image_id = instance.image_id instance_id = instance.id LOG.debug(_("Detected %(disk_format)s format for image " "%(image_id)s, instance %(instance_id)s") % locals()) - if instance.kernel_id: - # 1. DISK - log_disk_format('disk') - return ImageType.DISK - elif FLAGS.xenapi_image_service == 'glance': - # if using glance, then we could be VHD format + def determine_from_glance(): + glance_type2nova_type = {'machine': ImageType.DISK, + 'raw': ImageType.DISK_RAW, + 'vhd': ImageType.DISK_VHD, + 'kernel': ImageType.KERNEL_RAMDISK, + 'ramdisk': ImageType.KERNEL_RAMDISK} client = glance.client.Client(FLAGS.glance_host, FLAGS.glance_port) meta = client.get_image_meta(instance.image_id) - properties = meta['properties'] - disk_format = properties.get('disk_format', None) - # TODO(sirp): When Glance treats disk_format as a first class - # attribute, we should start using that rather than an - # image-property - if disk_format == 'vhd': - # 2a. DISK_VHD - log_disk_format('disk_vhd') - return ImageType.DISK_VHD - - # 2b. DISK_RAW - log_disk_format('disk_raw') - return ImageType.DISK_RAW + type_ = meta['type'] + try: + return glance_type2nova_type[type_] + except KeyError: + raise exception.NotFound( + _("Unrecognized image type '%(type_)s'") % locals()) + + def determine_from_instance(): + if instance.kernel_id: + return ImageType.DISK + else: + return ImageType.DISK_RAW + + if FLAGS.xenapi_image_service == 'glance': + image_type = determine_from_glance() + else: + image_type = determine_from_instance() + + log_disk_format(image_type) + return image_type @classmethod def _fetch_image_glance(cls, session, instance_id, image, access, type): diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 943d74da3..961d589d5 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -224,7 +224,8 @@ class VMOps(object): VMHelper.upload_image( self._session, instance.id, template_vdi_uuids, image_id) finally: - self._destroy(instance, template_vm_ref, shutdown=False) + self._destroy(instance, template_vm_ref, shutdown=False, + destroy_kernel_ramdisk=False) logging.debug(_("Finished snapshot and upload for VM %s"), instance) @@ -368,7 +369,8 @@ class VMOps(object): vm = VMHelper.lookup(self._session, instance.name) return self._destroy(instance, vm, shutdown=True) - def _destroy(self, instance, vm, shutdown=True): + def _destroy(self, instance, vm, shutdown=True, + destroy_kernel_ramdisk=True): """ Destroys VM instance by performing: @@ -385,7 +387,8 @@ class VMOps(object): self._shutdown(instance, vm) self._destroy_vdis(instance, vm) - self._destroy_kernel_ramdisk(instance, vm) + if destroy_kernel_ramdisk: + self._destroy_kernel_ramdisk(instance, vm) self._destroy_vm(instance, vm) def _wait_with_callback(self, instance_id, task, callback): -- cgit From 923a4938b73b84aa8a31f08a7c7b983cc82959fe Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Thu, 17 Feb 2011 07:29:50 +0000 Subject: Adding tests --- nova/virt/xenapi/vm_utils.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 278e52211..9027d58c4 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -490,6 +490,9 @@ class VMHelper(HelperBase): @classmethod def lookup_image(cls, session, instance_id, vdi_ref): + """ + Determine if VDI is using a PV kernel + """ if FLAGS.xenapi_image_service == 'glance': return cls._lookup_image_glance(session, vdi_ref) else: @@ -517,6 +520,7 @@ class VMHelper(HelperBase): def is_vdi_pv(dev): LOG.debug(_("Running pygrub against %s"), dev) + # TODO(sirp): use subprocess here output = os.popen('pygrub -qn /dev/%s' % dev) for line in output.readlines(): #try to find kernel string -- cgit From f0d58ea141116ccfd1c977b0f3e5fc669c0ea8a9 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 17 Feb 2011 18:06:34 -0600 Subject: moved inject network info to a function which accepts only instance, and call it from reset network --- nova/virt/xenapi/vmops.py | 96 +++++++++++++++++++++++++++-------------------- 1 file changed, 55 insertions(+), 41 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 842e08f22..d1ef95c6c 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -104,46 +104,6 @@ class VMOps(object): instance, kernel, ramdisk, pv_kernel) VMHelper.create_vbd(self._session, vm_ref, vdi_ref, 0, True) - # write network info - admin_context = context.get_admin_context() - - # TODO(tr3buchet) - remove comment in multi-nic - # I've decided to go ahead and consider multiple IPs and networks - # at this stage even though they aren't implemented because these will - # be needed for multi-nic and there was no sense writing it for single - # network/single IP and then having to turn around and re-write it - IPs = db.fixed_ip_get_all_by_instance(admin_context, instance['id']) - for network in db.network_get_all_by_instance(admin_context, - instance['id']): - network_IPs = [ip for ip in IPs if ip.network_id == network.id] - - def ip_dict(ip): - return {'netmask': network['netmask'], - 'enabled': '1', - 'ip': ip.address} - - mac_id = instance.mac_address.replace(':', '') - location = 'vm-data/networking/%s' % mac_id - mapping = {'label': network['label'], - 'gateway': network['gateway'], - 'mac': instance.mac_address, - 'dns': [network['dns']], - 'ips': [ip_dict(ip) for ip in network_IPs]} - self.write_to_param_xenstore(vm_ref, {location: mapping}) - - # TODO(tr3buchet) - remove comment in multi-nic - # this bit here about creating the vifs will be updated - # in multi-nic to handle multiple IPs on the same network - # and multiple networks - # for now it works as there is only one of each - bridge = network['bridge'] - network_ref = \ - NetworkHelper.find_network_with_bridge(self._session, bridge) - - if network_ref: - VMHelper.create_vif(self._session, vm_ref, - network_ref, instance.mac_address) - LOG.debug(_('Starting VM %s...'), vm_ref) self._session.call_xenapi('VM.start', vm_ref, False, False) instance_name = instance.name @@ -174,7 +134,7 @@ class VMOps(object): timer.f = _wait_for_boot - # call reset networking + # call to reset network to inject network info and configure self.reset_network(instance) return timer.start(interval=0.5, now=True) @@ -438,11 +398,65 @@ class VMOps(object): # TODO: implement this! return 'http://fakeajaxconsole/fake_url' + def inject_network_info(self, instance): + """ + Generate the network info and make calls to place it into the + xenstore and the xenstore param list + + """ + # TODO(tr3buchet) - remove comment in multi-nic + # I've decided to go ahead and consider multiple IPs and networks + # at this stage even though they aren't implemented because these will + # be needed for multi-nic and there was no sense writing it for single + # network/single IP and then having to turn around and re-write it + vm_opaque_ref = self._get_vm_opaque_ref(instance.id) + logging.debug(_("injecting network info to xenstore for vm: |%s|"), + vm_opaque_ref) + admin_context = context.get_admin_context() + IPs = db.fixed_ip_get_all_by_instance(admin_context, instance['id']) + for network in db.network_get_all_by_instance(admin_context, + instance['id']): + network_IPs = [ip for ip in IPs if ip.network_id == network.id] + + def ip_dict(ip): + return {'netmask': network['netmask'], + 'enabled': '1', + 'ip': ip.address} + + mac_id = instance.mac_address.replace(':', '') + location = 'vm-data/networking/%s' % mac_id + mapping = {'label': network['label'], + 'gateway': network['gateway'], + 'mac': instance.mac_address, + 'dns': [network['dns']], + 'ips': [ip_dict(ip) for ip in network_IPs]} + self.write_to_param_xenstore(vm_opaque_ref, {location: mapping}) + try: + self.write_to_xenstore(vm_opaque_ref, location, + mapping['location']) + except KeyError: + # catch KeyError for domid if instance isn't running + pass + + # TODO(tr3buchet) - remove comment in multi-nic + # this bit here about creating the vifs will be updated + # in multi-nic to handle multiple IPs on the same network + # and multiple networks + # for now it works as there is only one of each + bridge = network['bridge'] + network_ref = \ + NetworkHelper.find_network_with_bridge(self._session, bridge) + + if network_ref: + VMHelper.create_vif(self._session, vm_opaque_ref, + network_ref, instance.mac_address) + def reset_network(self, instance): """ Creates uuid arg to pass to make_agent_call and calls it. """ + self.inject_network_info(instance) args = {'id': str(uuid.uuid4())} resp = self._make_agent_call('resetnetwork', instance, '', args) -- cgit From 8916442e7f2920938a317777de71f75faf463005 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Fri, 18 Feb 2011 21:42:04 +0000 Subject: Typo fix --- nova/virt/xenapi/vm_utils.py | 2 ++ nova/virt/xenapi/vmops.py | 2 +- 2 files changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 9027d58c4..88a205d2f 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -451,6 +451,8 @@ class VMHelper(HelperBase): else: return ImageType.DISK_RAW + # FIXME(sirp): can we unify the ImageService and xenapi_image_service + # abstractions? if FLAGS.xenapi_image_service == 'glance': image_type = determine_from_glance() else: diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 8d1c79c0b..09abd5861 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -394,7 +394,7 @@ class VMOps(object): """ Three situations can occur: - 1. We have netiher a ramdisk or a kernel, in which case we are a + 1. We have neither a ramdisk nor a kernel, in which case we are a RAW image and can omit this step 2. We have one or the other, in which case, we should flag as an -- cgit From fa29dc0433384d5aa47f5ac069a8dc650e23ccae Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Fri, 18 Feb 2011 15:48:49 -0600 Subject: moved creating vifs to its own function, moved inject network to its own function --- nova/virt/xenapi/vmops.py | 30 ++++++++++++++++++++++-------- 1 file changed, 22 insertions(+), 8 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index d1ef95c6c..76b88a8bd 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -135,6 +135,8 @@ class VMOps(object): timer.f = _wait_for_boot # call to reset network to inject network info and configure + networks = self.inject_network_info(instance) + self.create_vifs(instance, networks) self.reset_network(instance) return timer.start(interval=0.5, now=True) @@ -414,8 +416,9 @@ class VMOps(object): vm_opaque_ref) admin_context = context.get_admin_context() IPs = db.fixed_ip_get_all_by_instance(admin_context, instance['id']) - for network in db.network_get_all_by_instance(admin_context, - instance['id']): + networks = db.network_get_all_by_instance(admin_context, + instance['id']) + for network in networks: network_IPs = [ip for ip in IPs if ip.network_id == network.id] def ip_dict(ip): @@ -438,11 +441,23 @@ class VMOps(object): # catch KeyError for domid if instance isn't running pass - # TODO(tr3buchet) - remove comment in multi-nic - # this bit here about creating the vifs will be updated - # in multi-nic to handle multiple IPs on the same network - # and multiple networks - # for now it works as there is only one of each + return networks + + def create_vifs(self, instance, networks=None): + """ + Creates vifs for an instance + + """ + logging.debug(_("creating vif(s) for vm: |%s|"), vm_opaque_ref) + if networks is None: + networks = db.network_get_all_by_instance(admin_context, + instance['id']) + # TODO(tr3buchet) - remove comment in multi-nic + # this bit here about creating the vifs will be updated + # in multi-nic to handle multiple IPs on the same network + # and multiple networks + # for now it works as there is only one of each + for network in networks: bridge = network['bridge'] network_ref = \ NetworkHelper.find_network_with_bridge(self._session, bridge) @@ -456,7 +471,6 @@ class VMOps(object): Creates uuid arg to pass to make_agent_call and calls it. """ - self.inject_network_info(instance) args = {'id': str(uuid.uuid4())} resp = self._make_agent_call('resetnetwork', instance, '', args) -- cgit From eefc8938d8a8010052affab9a5c0d010778d9780 Mon Sep 17 00:00:00 2001 From: Rick Harris Date: Fri, 18 Feb 2011 22:25:19 +0000 Subject: Changing type -> image_type --- nova/virt/xenapi/vm_utils.py | 44 +++++++++++++++++++++++++------------------- 1 file changed, 25 insertions(+), 19 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 88a205d2f..2114bfa42 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -305,9 +305,10 @@ class VMHelper(HelperBase): session.wait_for_task(instance_id, task) @classmethod - def fetch_image(cls, session, instance_id, image, user, project, type): + def fetch_image(cls, session, instance_id, image, user, project, + image_type): """ - type is interpreted as an ImageType instance + image_type is interpreted as an ImageType instance Related flags: xenapi_image_service = ['glance', 'objectstore'] glance_address = 'address for glance services' @@ -317,14 +318,15 @@ class VMHelper(HelperBase): if FLAGS.xenapi_image_service == 'glance': return cls._fetch_image_glance(session, instance_id, image, - access, type) + access, image_type) else: return cls._fetch_image_objectstore(session, instance_id, image, - access, user.secret, type) + access, user.secret, + image_type) @classmethod def _fetch_image_glance_vhd(cls, session, instance_id, image, access, - type): + image_type): LOG.debug(_("Asking xapi to fetch vhd image %(image)s") % locals()) @@ -358,7 +360,7 @@ class VMHelper(HelperBase): @classmethod def _fetch_image_glance_disk(cls, session, instance_id, image, access, - type): + image_type): """Fetch the image from Glance NOTE: @@ -378,7 +380,7 @@ class VMHelper(HelperBase): vdi_size = virtual_size LOG.debug(_("Size for image %(image)s:%(virtual_size)d") % locals()) - if type == ImageType.DISK: + if image_type == ImageType.DISK: # Make room for MBR. vdi_size += MBR_SIZE_BYTES @@ -387,9 +389,9 @@ class VMHelper(HelperBase): with_vdi_attached_here(session, vdi, False, lambda dev: - _stream_disk(dev, type, + _stream_disk(dev, image_type, virtual_size, image_file)) - if (type == ImageType.KERNEL_RAMDISK): + if image_type == ImageType.KERNEL_RAMDISK: #we need to invoke a plugin for copying VDI's #content into proper path LOG.debug(_("Copying VDI %s to /boot/guest on dom0"), vdi) @@ -462,29 +464,33 @@ class VMHelper(HelperBase): return image_type @classmethod - def _fetch_image_glance(cls, session, instance_id, image, access, type): - if type == ImageType.DISK_VHD: + def _fetch_image_glance(cls, session, instance_id, image, access, + image_type): + if image_type == ImageType.DISK_VHD: return cls._fetch_image_glance_vhd( - session, instance_id, image, access, type) + session, instance_id, image, access, image_type) else: return cls._fetch_image_glance_disk( - session, instance_id, image, access, type) + session, instance_id, image, access, image_type) @classmethod def _fetch_image_objectstore(cls, session, instance_id, image, access, - secret, type): + secret, image_type): url = images.image_url(image) LOG.debug(_("Asking xapi to fetch %(url)s as %(access)s") % locals()) - fn = (type != ImageType.KERNEL_RAMDISK) and 'get_vdi' or 'get_kernel' + if image_type == ImageType.KERNEL_RAMDISK: + fn = 'get_kernel' + else: + fn = 'get_vdi' args = {} args['src_url'] = url args['username'] = access args['password'] = secret args['add_partition'] = 'false' args['raw'] = 'false' - if type != ImageType.KERNEL_RAMDISK: + if image_type != ImageType.KERNEL_RAMDISK: args['add_partition'] = 'true' - if type == ImageType.DISK_RAW: + if image_type == ImageType.DISK_RAW: args['raw'] = 'true' task = session.async_call_plugin('objectstore', fn, args) uuid = session.wait_for_task(instance_id, task) @@ -857,9 +863,9 @@ def get_this_vm_ref(session): return session.get_xenapi().VM.get_by_uuid(get_this_vm_uuid()) -def _stream_disk(dev, type, virtual_size, image_file): +def _stream_disk(dev, image_type, virtual_size, image_file): offset = 0 - if type == ImageType.DISK: + if image_type == ImageType.DISK: offset = MBR_SIZE_BYTES _write_partition(virtual_size, dev) -- cgit From e369f2842446876505ce528c5bb56a3d41215f8f Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Fri, 18 Feb 2011 16:42:26 -0600 Subject: added admin api call for injecting network info, added api test for inject network info --- nova/virt/xenapi_conn.py | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'nova/virt') diff --git a/nova/virt/xenapi_conn.py b/nova/virt/xenapi_conn.py index 2720d175f..f72a12380 100644 --- a/nova/virt/xenapi_conn.py +++ b/nova/virt/xenapi_conn.py @@ -192,6 +192,10 @@ class XenAPIConnection(object): """reset networking for specified instance""" self._vmops.reset_network(instance) + def inject_network_info(self, instance): + """inject network info for specified instance""" + self._vmops.inject_network_info(instance) + def get_info(self, instance_id): """Return data about VM instance""" return self._vmops.get_info(instance_id) -- cgit From 8e2ebb1a963f58514d8fb6aab4a75627e72484b9 Mon Sep 17 00:00:00 2001 From: Salvatore Orlando Date: Thu, 24 Feb 2011 16:04:13 +0000 Subject: stubbing out _is_vdi_pv for test purposes --- nova/virt/xenapi/vm_utils.py | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vm_utils.py b/nova/virt/xenapi/vm_utils.py index 80cc3035d..564a25057 100644 --- a/nova/virt/xenapi/vm_utils.py +++ b/nova/virt/xenapi/vm_utils.py @@ -400,19 +400,7 @@ class VMHelper(HelperBase): @classmethod def _lookup_image_glance(cls, session, vdi_ref): LOG.debug(_("Looking up vdi %s for PV kernel"), vdi_ref) - - def is_vdi_pv(dev): - LOG.debug(_("Running pygrub against %s"), dev) - output = os.popen('pygrub -qn /dev/%s' % dev) - for line in output.readlines(): - #try to find kernel string - m = re.search('(?<=kernel:)/.*(?:>)', line) - if m and m.group(0).find('xen') != -1: - LOG.debug(_("Found Xen kernel %s") % m.group(0)) - return True - LOG.debug(_("No Xen kernel found. Booting HVM.")) - return False - return with_vdi_attached_here(session, vdi_ref, True, is_vdi_pv) + return with_vdi_attached_here(session, vdi_ref, True, _is_vdi_pv) @classmethod def lookup(cls, session, i): @@ -714,6 +702,19 @@ def get_this_vm_ref(session): return session.get_xenapi().VM.get_by_uuid(get_this_vm_uuid()) +def _is_vdi_pv(dev): + LOG.debug(_("Running pygrub against %s"), dev) + output = os.popen('pygrub -qn /dev/%s' % dev) + for line in output.readlines(): + #try to find kernel string + m = re.search('(?<=kernel:)/.*(?:>)', line) + if m and m.group(0).find('xen') != -1: + LOG.debug(_("Found Xen kernel %s") % m.group(0)) + return True + LOG.debug(_("No Xen kernel found. Booting HVM.")) + return False + + def _stream_disk(dev, type, virtual_size, image_file): offset = 0 if type == ImageType.DISK: -- cgit From 8635f7a306e4cfa41ad09a18602efa7793f6da95 Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 24 Feb 2011 15:04:07 -0600 Subject: moved network injection and vif creation to above vm start in vmops spawn --- nova/virt/xenapi/vmops.py | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 76b88a8bd..3aa5a23e5 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -104,6 +104,10 @@ class VMOps(object): instance, kernel, ramdisk, pv_kernel) VMHelper.create_vbd(self._session, vm_ref, vdi_ref, 0, True) + # inject_network_info and create vifs + networks = self.inject_network_info(instance) + self.create_vifs(instance, networks) + LOG.debug(_('Starting VM %s...'), vm_ref) self._session.call_xenapi('VM.start', vm_ref, False, False) instance_name = instance.name @@ -134,9 +138,7 @@ class VMOps(object): timer.f = _wait_for_boot - # call to reset network to inject network info and configure - networks = self.inject_network_info(instance) - self.create_vifs(instance, networks) + # call to reset network to configure network from xenstore self.reset_network(instance) return timer.start(interval=0.5, now=True) -- cgit From f4221346418ef103635b104fc152a2507d60a8dc Mon Sep 17 00:00:00 2001 From: Trey Morris Date: Thu, 24 Feb 2011 17:25:00 -0600 Subject: forgot to get vm_opaque_ref --- nova/virt/xenapi/vmops.py | 1 + 1 file changed, 1 insertion(+) (limited to 'nova/virt') diff --git a/nova/virt/xenapi/vmops.py b/nova/virt/xenapi/vmops.py index 3aa5a23e5..8abaa14fa 100644 --- a/nova/virt/xenapi/vmops.py +++ b/nova/virt/xenapi/vmops.py @@ -450,6 +450,7 @@ class VMOps(object): Creates vifs for an instance """ + vm_opaque_ref = self._get_vm_opaque_ref(instance.id) logging.debug(_("creating vif(s) for vm: |%s|"), vm_opaque_ref) if networks is None: networks = db.network_get_all_by_instance(admin_context, -- cgit From 4c83130464c88650df7dfc7974f2fd088a733fec Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Sat, 26 Feb 2011 17:26:38 +0100 Subject: introduced new flag "maximum_nbd_devices" to set the number of possible NBD devices --- nova/virt/disk.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'nova/virt') diff --git a/nova/virt/disk.py b/nova/virt/disk.py index cb639a102..8789d8123 100644 --- a/nova/virt/disk.py +++ b/nova/virt/disk.py @@ -40,6 +40,8 @@ flags.DEFINE_integer('block_size', 1024 * 1024 * 256, 'block_size to use for dd') flags.DEFINE_integer('timeout_nbd', 10, 'time to wait for a NBD device coming up') +flags.DEFINE_integer('maximum_nbd_devices', 16, + 'maximum number of possible nbd devices') def extend(image, size): @@ -141,7 +143,7 @@ def _unlink_device(device, nbd): utils.execute('sudo losetup --detach %s' % device) -_DEVICES = ['/dev/nbd%s' % i for i in xrange(16)] +_DEVICES = ['/dev/nbd%s' % i for i in xrange(FLAGS.maximum_nbd_devices)] def _allocate_device(): -- cgit From dcfa9670a669ff881865750b2f96f62195dce2df Mon Sep 17 00:00:00 2001 From: Christian Berendt Date: Sat, 26 Feb 2011 19:19:02 +0100 Subject: renamed flag from maximum_... to max_... --- nova/virt/disk.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'nova/virt') diff --git a/nova/virt/disk.py b/nova/virt/disk.py index 8789d8123..2bded07a4 100644 --- a/nova/virt/disk.py +++ b/nova/virt/disk.py @@ -40,7 +40,7 @@ flags.DEFINE_integer('block_size', 1024 * 1024 * 256, 'block_size to use for dd') flags.DEFINE_integer('timeout_nbd', 10, 'time to wait for a NBD device coming up') -flags.DEFINE_integer('maximum_nbd_devices', 16, +flags.DEFINE_integer('max_nbd_devices', 16, 'maximum number of possible nbd devices') @@ -143,7 +143,7 @@ def _unlink_device(device, nbd): utils.execute('sudo losetup --detach %s' % device) -_DEVICES = ['/dev/nbd%s' % i for i in xrange(FLAGS.maximum_nbd_devices)] +_DEVICES = ['/dev/nbd%s' % i for i in xrange(FLAGS.max_nbd_devices)] def _allocate_device(): -- cgit