XenAPI: fix the ephemeral disk failure on XS7.x

In XS7.x, sfdisk V2.23 is installed. But there is a bug which
causing it complaining wrong cylinder number is specified for
the partition's end. And that bug has been fixed since 2.26.
At here the solution is to use the option of '--force" before
V2.26.

Change-Id: I5f1a3c182ee1874383bd5f0cecbad18d96e8b58f
Closes-Bug: #1701153
This commit is contained in:
Jianghua Wang 2017-08-02 07:17:42 +00:00
parent 755876c19f
commit e7a915be9f
2 changed files with 79 additions and 3 deletions

View File

@ -16,8 +16,10 @@
# NOTE: XenServer still only supports Python 2.4 in it's dom0 userspace
# which means the Nova xenapi plugins must use only Python 2.4 features
from distutils.version import StrictVersion
import logging
import os
import re
import time
import dom0_pluginlib as pluginlib
@ -35,14 +37,39 @@ def wait_for_dev(session, dev_path, max_seconds):
return ""
def _get_sfdisk_version():
out = utils.run_command(['/sbin/sfdisk', '-v'])
if out:
# Return the first two numbers from the version.
# In XS6.5, it's 2.13-pre7. Just return 2.13 for this case.
pattern = re.compile("(\d+)\.(\d+)")
match = pattern.search(out.split('\n')[0])
if match:
return match.group(0)
def make_partition(session, dev, partition_start, partition_end):
# Since XS7.0 which has sfdisk V2.23, we observe sfdisk has a bug
# that sfdisk will wrongly calculate cylinders when specify Sector
# as unit (-uS). That bug will cause the partition operation failed.
# And that's fixed in 2.26. So as a workaround, let's use the option
# of '--force' for version <=2.25 and >=2.23. '--force' will ignore
# the wrong cylinder value but works as expected.
VER_FORCE_MIN = '2.23'
VER_FORCE_MAX = '2.25'
dev_path = utils.make_dev_path(dev)
if partition_end != "-":
raise pluginlib.PluginError("Can only create unbounded partitions")
utils.run_command(['sfdisk', '-uS', dev_path],
'%s,;\n' % (partition_start))
sfdisk_ver = _get_sfdisk_version()
cmd_list = ['sfdisk', '-uS', dev_path]
if sfdisk_ver:
if StrictVersion(sfdisk_ver) >= StrictVersion(VER_FORCE_MIN) and \
StrictVersion(sfdisk_ver) <= StrictVersion(VER_FORCE_MAX):
cmd_list = ['sfdisk', '--force', '-uS', dev_path]
utils.run_command(cmd_list, '%s,;\n' % (partition_start))
def _mkfs(fs, path, label):

View File

@ -100,10 +100,59 @@ class PartitionUtils(plugin_test.PluginTestBase):
self.partition_utils._mkfs('swap', '/dev/sda1', 'ignored')
mock_run.assert_called_with(['mkswap', '/dev/sda1'])
def test_make_partition(self):
def test_make_partition_sfdisk_v213(self):
mock_run = self.mock_patch_object(self.partition_utils.utils,
'run_command')
mock_get_version = self.mock_patch_object(
self.partition_utils, '_get_sfdisk_version')
mock_get_version.return_value = '2.13'
self.partition_utils.make_partition('session', 'dev', 'start', '-')
mock_get_version.assert_called_with()
mock_run.assert_called_with(['sfdisk', '-uS', '/dev/dev'], 'start,;\n')
def test_make_partition_sfdisk_v223(self):
mock_run = self.mock_patch_object(self.partition_utils.utils,
'run_command')
mock_get_version = self.mock_patch_object(
self.partition_utils, '_get_sfdisk_version')
mock_get_version.return_value = '2.23'
self.partition_utils.make_partition('session', 'dev', 'start', '-')
mock_get_version.assert_called_with()
mock_run.assert_called_with(['sfdisk', '--force', '-uS', '/dev/dev'],
'start,;\n')
def test_make_partition_sfdisk_v226(self):
mock_run = self.mock_patch_object(self.partition_utils.utils,
'run_command')
mock_get_version = self.mock_patch_object(
self.partition_utils, '_get_sfdisk_version')
mock_get_version.return_value = '2.26'
self.partition_utils.make_partition('session', 'dev', 'start', '-')
mock_get_version.assert_called_with()
mock_run.assert_called_with(['sfdisk', '-uS', '/dev/dev'], 'start,;\n')
def test_get_sfdisk_version_213pre7(self):
mock_run = self.mock_patch_object(
self.partition_utils.utils, 'run_command')
mock_run.return_value = 'sfdisk (util-linux 2.13-pre7)'
version = self.partition_utils._get_sfdisk_version()
mock_run.assert_called_with(['/sbin/sfdisk', '-v'])
self.assertEqual(version, '2.13')
def test_get_sfdisk_version_223(self):
mock_run = self.mock_patch_object(
self.partition_utils.utils, 'run_command')
mock_run.return_value = 'sfdisk from util-linux 2.23.2\n'
version = self.partition_utils._get_sfdisk_version()
mock_run.assert_called_with(['/sbin/sfdisk', '-v'])
self.assertEqual(version, '2.23')