Use DiskPartitioner

Use the new DiskPartitioner class to create the partition layout.

This commit also moves the sleep() workaround to avoid the "device is
busy" problem into the DiskPartitioner wrapper.

Change-Id: I28bb17c7ce2262d3088f58ab4421145e8d9baa1f
Closes-Bug: #1297925
This commit is contained in:
Lucas Alvares Gomes 2014-03-27 14:35:24 +00:00 committed by Devananda van der Veen
parent 14c61d69a2
commit 8be126631b
5 changed files with 27 additions and 31 deletions

View File

@ -4,10 +4,12 @@
[Filters] [Filters]
# ironic/drivers/modules/deploy_utils.py # ironic/drivers/modules/deploy_utils.py
iscsiadm: CommandFilter, iscsiadm, root iscsiadm: CommandFilter, iscsiadm, root
parted: CommandFilter, parted, root
dd: CommandFilter, dd, root dd: CommandFilter, dd, root
blkid: CommandFilter, blkid, root blkid: CommandFilter, blkid, root
# ironic/common/utils.py # ironic/common/utils.py
mkswap: CommandFilter, mkswap, root mkswap: CommandFilter, mkswap, root
mkfs: CommandFilter, mkfs, root mkfs: CommandFilter, mkfs, root
# ironic/common/disk_partitioner.py
parted: CommandFilter, parted, root

View File

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import time
from ironic.common import utils from ironic.common import utils
@ -90,3 +92,7 @@ class DiskPartitioner(object):
start = end start = end
self._exec(*cmd_args) self._exec(*cmd_args)
# TODO(lucasagomes): Do not sleep, use another mechanism to avoid
# the "device is busy" problem. lsof, fuser...
# avoid "device is busy"
time.sleep(3)

View File

@ -20,6 +20,7 @@ import socket
import stat import stat
import time import time
from ironic.common import disk_partitioner
from ironic.common import exception from ironic.common import exception
from ironic.common import utils from ironic.common import utils
from ironic.openstack.common import excutils from ironic.openstack.common import excutils
@ -80,27 +81,15 @@ def delete_iscsi(portal_address, portal_port, target_iqn):
def make_partitions(dev, root_mb, swap_mb, ephemeral_mb): def make_partitions(dev, root_mb, swap_mb, ephemeral_mb):
"""Create partitions for root and swap on a disk device.""" """Create partitions for root and swap on a disk device."""
cmd = [] dp = disk_partitioner.DiskPartitioner(dev)
def add_partition(start, size, fs_type=''):
end = start + size
cmd.extend(['mkpart', 'primary', fs_type, str(start), str(end)])
return end
offset = 1
if ephemeral_mb: if ephemeral_mb:
offset = add_partition(offset, ephemeral_mb) dp.add_partition(ephemeral_mb)
offset = add_partition(offset, swap_mb, fs_type='linux-swap') dp.add_partition(swap_mb, fs_type='linux-swap')
offset = add_partition(offset, root_mb) dp.add_partition(root_mb)
else: else:
offset = add_partition(offset, root_mb) dp.add_partition(root_mb)
offset = add_partition(offset, swap_mb, fs_type='linux-swap') dp.add_partition(swap_mb, fs_type='linux-swap')
dp.commit()
utils.execute('parted', '-a', 'optimal', '-s', dev, '--', 'mklabel',
'msdos', 'unit', 'MiB', *cmd, run_as_root=True, attempts=3,
check_exit_code=[0])
# avoid "device is busy"
time.sleep(3)
def is_block_device(dev): def is_block_device(dev):

View File

@ -14,6 +14,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import time
import fixtures import fixtures
import mock import mock
import os import os
@ -403,6 +405,7 @@ class WorkOnDiskTestCase(tests_base.TestCase):
self.swap_mb, ephemeral_mb) self.swap_mb, ephemeral_mb)
@mock.patch.object(time, 'sleep', lambda _: None)
@mock.patch.object(common_utils, 'execute') @mock.patch.object(common_utils, 'execute')
class MakePartitionsTestCase(tests_base.TestCase): class MakePartitionsTestCase(tests_base.TestCase):
@ -413,7 +416,7 @@ class MakePartitionsTestCase(tests_base.TestCase):
self.swap_mb = 512 self.swap_mb = 512
self.ephemeral_mb = 0 self.ephemeral_mb = 0
self.parted_static_cmd = ['parted', '-a', 'optimal', '-s', self.dev, self.parted_static_cmd = ['parted', '-a', 'optimal', '-s', self.dev,
'--', 'mklabel', 'msdos', 'unit', 'MiB'] '--', 'unit', 'MiB', 'mklabel', 'msdos']
def test_make_partitions(self, mock_exc): def test_make_partitions(self, mock_exc):
expected_mkpart = ['mkpart', 'primary', '', '1', '1025', expected_mkpart = ['mkpart', 'primary', '', '1', '1025',
@ -421,8 +424,7 @@ class MakePartitionsTestCase(tests_base.TestCase):
cmd = self.parted_static_cmd + expected_mkpart cmd = self.parted_static_cmd + expected_mkpart
utils.make_partitions(self.dev, self.root_mb, self.swap_mb, utils.make_partitions(self.dev, self.root_mb, self.swap_mb,
self.ephemeral_mb) self.ephemeral_mb)
mock_exc.assert_called_once_with(*cmd, mock_exc.assert_called_once_with(*cmd, run_as_root=True,
run_as_root=True, attempts=3,
check_exit_code=[0]) check_exit_code=[0])
def test_make_partitions_with_ephemeral(self, mock_exc): def test_make_partitions_with_ephemeral(self, mock_exc):
@ -433,6 +435,5 @@ class MakePartitionsTestCase(tests_base.TestCase):
cmd = self.parted_static_cmd + expected_mkpart cmd = self.parted_static_cmd + expected_mkpart
utils.make_partitions(self.dev, self.root_mb, self.swap_mb, utils.make_partitions(self.dev, self.root_mb, self.swap_mb,
self.ephemeral_mb) self.ephemeral_mb)
mock_exc.assert_called_once_with(*cmd, mock_exc.assert_called_once_with(*cmd, run_as_root=True,
run_as_root=True, attempts=3,
check_exit_code=[0]) check_exit_code=[0])

View File

@ -13,6 +13,8 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
import time
import mock import mock
from testtools.matchers import HasLength from testtools.matchers import HasLength
@ -21,14 +23,10 @@ from ironic.common import utils
from ironic.tests import base from ironic.tests import base
@mock.patch.object(time, 'sleep', lambda _: None)
@mock.patch.object(utils, 'execute', lambda _: None)
class DiskPartitionerTestCase(base.TestCase): class DiskPartitionerTestCase(base.TestCase):
def setUp(self):
super(DiskPartitionerTestCase, self).setUp()
self.mock_exc = mock.patch.object(utils, 'execute')
self.mock_exc.start()
self.addCleanup(self.mock_exc.stop)
def test_add_partition(self): def test_add_partition(self):
dp = disk_partitioner.DiskPartitioner('/dev/fake') dp = disk_partitioner.DiskPartitioner('/dev/fake')
dp.add_partition(1024) dp.add_partition(1024)