diff options
-rw-r--r-- | nova/compute/manager.py | 15 | ||||
-rw-r--r-- | nova/compute/utils.py | 38 | ||||
-rw-r--r-- | nova/tests/compute/test_compute_utils.py | 11 |
3 files changed, 38 insertions, 26 deletions
diff --git a/nova/compute/manager.py b/nova/compute/manager.py index 0ad5c1dc8..39e68e9f8 100644 --- a/nova/compute/manager.py +++ b/nova/compute/manager.py @@ -2438,16 +2438,19 @@ class ComputeManager(manager.SchedulerDependentManager): def do_reserve(): bdms = self.conductor_api.block_device_mapping_get_all_by_instance( context, instance) - result = compute_utils.get_device_name_for_instance(context, - instance, - bdms, - device) + + device_name = compute_utils.get_device_name_for_instance( + context, instance, bdms, device) + # NOTE(vish): create bdm here to avoid race condition values = {'instance_uuid': instance['uuid'], 'volume_id': volume_id or 'reserved', - 'device_name': result} + 'device_name': device_name} + self.conductor_api.block_device_mapping_create(context, values) - return result + + return device_name + return do_reserve() @exception.wrap_exception(notifier=notifier, publisher_id=publisher_id()) diff --git a/nova/compute/utils.py b/nova/compute/utils.py index 8d363fa1c..bdec9acec 100644 --- a/nova/compute/utils.py +++ b/nova/compute/utils.py @@ -75,49 +75,59 @@ def get_device_name_for_instance(context, instance, bdms, device): appropriate format. """ req_prefix = None - req_letters = None + req_letter = None + if device: try: - req_prefix, req_letters = block_device.match_device(device) + req_prefix, req_letter = block_device.match_device(device) except (TypeError, AttributeError, ValueError): raise exception.InvalidDevicePath(path=device) + mappings = block_device.instance_block_mapping(instance, bdms) + try: prefix = block_device.match_device(mappings['root'])[0] except (TypeError, AttributeError, ValueError): raise exception.InvalidDevicePath(path=mappings['root']) + # NOTE(vish): remove this when xenapi is setting default_root_device if driver.compute_driver_matches('xenapi.XenAPIDriver'): prefix = '/dev/xvd' + if req_prefix != prefix: LOG.debug(_("Using %(prefix)s instead of %(req_prefix)s") % locals()) - letters_list = [] - for _name, device in mappings.iteritems(): - letter = block_device.strip_prefix(device) + + used_letters = set() + for device_path in mappings.itervalues(): + letter = block_device.strip_prefix(device_path) # NOTE(vish): delete numbers in case we have something like # /dev/sda1 letter = re.sub("\d+", "", letter) - letters_list.append(letter) - used_letters = set(letters_list) + used_letters.add(letter) # NOTE(vish): remove this when xenapi is properly setting # default_ephemeral_device and default_swap_device if driver.compute_driver_matches('xenapi.XenAPIDriver'): instance_type_id = instance['instance_type_id'] instance_type = instance_types.get_instance_type(instance_type_id) + if instance_type['ephemeral_gb']: - used_letters.update('b') + used_letters.add('b') + if instance_type['swap']: - used_letters.update('c') + used_letters.add('c') - if not req_letters: - req_letters = _get_unused_letters(used_letters) - if req_letters in used_letters: + if not req_letter: + req_letter = _get_unused_letter(used_letters) + + if req_letter in used_letters: raise exception.DevicePathInUse(path=device) - return prefix + req_letters + + device_name = prefix + req_letter + return device_name -def _get_unused_letters(used_letters): +def _get_unused_letter(used_letters): doubles = [first + second for second in string.ascii_lowercase for first in string.ascii_lowercase] all_letters = set(list(string.ascii_lowercase) + doubles) diff --git a/nova/tests/compute/test_compute_utils.py b/nova/tests/compute/test_compute_utils.py index 4372039e0..e7763a1c3 100644 --- a/nova/tests/compute/test_compute_utils.py +++ b/nova/tests/compute/test_compute_utils.py @@ -71,10 +71,8 @@ class ComputeValidateDeviceTestCase(test.TestCase): def _validate_device(self, device=None): bdms = db.block_device_mapping_get_all_by_instance( self.context, self.instance['uuid']) - return compute_utils.get_device_name_for_instance(self.context, - self.instance, - bdms, - device) + return compute_utils.get_device_name_for_instance( + self.context, self.instance, bdms, device) @staticmethod def _fake_bdm(device): @@ -148,8 +146,9 @@ class ComputeValidateDeviceTestCase(test.TestCase): self._validate_device, '/baddata/vdc') def test_device_in_use(self): - self.assertRaises(exception.DevicePathInUse, - self._validate_device, '/dev/vdb') + exc = self.assertRaises(exception.DevicePathInUse, + self._validate_device, '/dev/vda') + self.assertIn('/dev/vda', str(exc)) def test_swap(self): self.instance['default_swap_device'] = "/dev/vdc" |