From 36f310f469b91c7de72a8366c7d493e1e7a4fd0f Mon Sep 17 00:00:00 2001 From: Tsuyoshi Nagata Date: Thu, 7 Jun 2018 10:56:27 +0900 Subject: [PATCH] Add method to generate device names universally When attaching block devices, we find the next device name to use by looking at the used device letters in the block device mappings and selecting the next available letter, as long as the letter is within 'a' - 'z' or 'aa' - 'zz'. This allows us to represent 702 devices (and would interestingly hit an IndexError if all 'a' - 'z' and 'aa' - 'zz' letters were in use already. This adds a method for generating device names universally, not limited to any particular maximum, based on a device index. For example: vda(index=0), sdb(index=1), vdaa(index=26), sdabc(index=730), ... This method and its helper method will be used in a subsequent patch. Part of blueprint conf-max-attach-volumes Change-Id: I2699f600a98222a4dc58903ec97ca70e57701c93 --- nova/block_device.py | 26 ++++++++++++++++++++++++++ nova/tests/unit/test_block_device.py | 14 ++++++++++++++ 2 files changed, 40 insertions(+) diff --git a/nova/block_device.py b/nova/block_device.py index c0113a350ad1..89c203b1d774 100644 --- a/nova/block_device.py +++ b/nova/block_device.py @@ -509,6 +509,32 @@ def get_device_letter(device_name): return _nums.sub('', letter) if device_name else device_name +def generate_device_letter(index): + """Returns device letter by index (starts by zero) + i.e. + index = 0, 1,..., 18277 + results = a, b,..., zzz + """ + base = ord('z') - ord('a') + 1 + unit_dev_name = "" + while index >= 0: + letter = chr(ord('a') + (index % base)) + unit_dev_name = letter + unit_dev_name + index = int(index / base) - 1 + + return unit_dev_name + + +def generate_device_name(prefix, index): + """Returns device unit name by index (starts by zero) + i.e. + prefix = vd + index = 0, 1,..., 18277 + results = vda, vdb,..., vdzzz + """ + return prefix + generate_device_letter(index) + + def instance_block_mapping(instance, bdms): root_device_name = instance['root_device_name'] # NOTE(clayg): remove this when xenapi is setting default_root_device diff --git a/nova/tests/unit/test_block_device.py b/nova/tests/unit/test_block_device.py index 52939cd3dd73..abf265818a32 100644 --- a/nova/tests/unit/test_block_device.py +++ b/nova/tests/unit/test_block_device.py @@ -149,6 +149,20 @@ class BlockDeviceTestCase(test.NoDBTestCase): self.assertEqual('c', block_device.get_device_letter('hdc')) self.assertIsNone(block_device.get_device_letter(None)) + def test_generate_device_name(self): + expected = ( + ('vda', ("vd", 0)), + ('vdaa', ("vd", 26)), + ('vdabc', ("vd", 730)), + ('vdidpok', ("vd", 4194304)), + ('sdc', ("sd", 2)), + ('sdaa', ("sd", 26)), + ('sdiw', ("sd", 256)), + ('hdzz', ("hd", 701)) + ) + for res, args in expected: + self.assertEqual(res, block_device.generate_device_name(*args)) + def test_volume_in_mapping(self): swap = {'device_name': '/dev/sdb', 'swap_size': 1}