iscsi: wipe the disk before deployment

If the remote disk has already a partition table, it must be clean up
before the disk is exposed through iscsi. Otherwise this disk
partition can create a conflict during the grub installation.

start_iscsi_target() has now a new paramter wipe_disk_metadata to
request the agent to wipe the disk before exposing it.

Now, disk without preserve_ephemeral are cleaned up before new
deployment.

References:
- IPA: Ie68cb6296c782e904d40f6e9de0faa52ab2af2bf
- ironic-lib: 042aa9ab5a27e251c8fb2f1855695cf5e791ecf5
- https://bugzilla.redhat.com/show_bug.cgi?id=1310883

Change-Id: I4f2f754ab0ff01046768e73fff789807d307b829
Closes-Bug: 1550604
This commit is contained in:
Gonéri Le Bouder 2016-04-08 16:26:17 -04:00 committed by Julia Kreger
parent 20ae1e2e73
commit 1a4bf23ce5
5 changed files with 60 additions and 10 deletions

View File

@ -130,9 +130,20 @@ class AgentClient(object):
params=params, params=params,
wait=wait) wait=wait)
def start_iscsi_target(self, node, iqn, portal_port=3260): def start_iscsi_target(self, node, iqn,
"""Expose the node's disk as an ISCSI target.""" portal_port=3260, wipe_disk_metadata=False):
params = {'iqn': iqn, 'portal_port': portal_port} """Expose the node's disk as an ISCSI target.
:param node: an Ironic node object
:param iqn: iSCSI target IQN
:param portal_port: iSCSI portal port
:param wipe_disk_metadata: True if the agent should wipe first the
disk magic strings like the partition table, RAID or filesystem
signature.
"""
params = {'iqn': iqn,
'portal_port': portal_port,
'wipe_disk_metadata': wipe_disk_metadata}
return self._command(node=node, return self._command(node=node,
method='iscsi.start_iscsi_target', method='iscsi.start_iscsi_target',
params=params, params=params,

View File

@ -339,13 +339,15 @@ def do_agent_iscsi_deploy(task, agent_client):
""" """
node = task.node node = task.node
iscsi_options = build_deploy_ramdisk_options(node) iscsi_options = build_deploy_ramdisk_options(node)
i_info = deploy_utils.parse_instance_info(node)
wipe_disk_metadata = not i_info['preserve_ephemeral']
iqn = iscsi_options['iscsi_target_iqn'] iqn = iscsi_options['iscsi_target_iqn']
portal_port = iscsi_options['iscsi_portal_port'] portal_port = iscsi_options['iscsi_portal_port']
result = agent_client.start_iscsi_target(
result = agent_client.start_iscsi_target(node, iqn, node, iqn,
portal_port) portal_port,
wipe_disk_metadata=wipe_disk_metadata)
if result['command_status'] == 'FAILED': if result['command_status'] == 'FAILED':
msg = (_("Failed to start the iSCSI target to deploy the " msg = (_("Failed to start the iSCSI target to deploy the "
"node %(node)s. Error: %(error)s") % "node %(node)s. Error: %(error)s") %

View File

@ -179,7 +179,7 @@ class TestAgentClient(base.TestCase):
self.client._command = mock.MagicMock(spec_set=[]) self.client._command = mock.MagicMock(spec_set=[])
iqn = 'fake-iqn' iqn = 'fake-iqn'
port = 3260 port = 3260
params = {'iqn': iqn, 'portal_port': port} params = {'iqn': iqn, 'portal_port': port, 'wipe_disk_metadata': False}
self.client.start_iscsi_target(self.node, iqn, port) self.client.start_iscsi_target(self.node, iqn, port)
self.client._command.assert_called_once_with( self.client._command.assert_called_once_with(

View File

@ -522,7 +522,7 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
task, agent_client_mock) task, agent_client_mock)
build_options_mock.assert_called_once_with(task.node) build_options_mock.assert_called_once_with(task.node)
agent_client_mock.start_iscsi_target.assert_called_once_with( agent_client_mock.start_iscsi_target.assert_called_once_with(
task.node, 'iqn-qweqwe', 3260) task.node, 'iqn-qweqwe', 3260, wipe_disk_metadata=True)
continue_deploy_mock.assert_called_once_with( continue_deploy_mock.assert_called_once_with(
task, error=None, iqn='iqn-qweqwe', key='abcdef', task, error=None, iqn='iqn-qweqwe', key='abcdef',
address='1.2.3.4') address='1.2.3.4')
@ -531,6 +531,34 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
task.node.driver_internal_info['root_uuid_or_disk_id']) task.node.driver_internal_info['root_uuid_or_disk_id'])
self.assertEqual(ret_val, uuid_dict_returned) self.assertEqual(ret_val, uuid_dict_returned)
@mock.patch.object(iscsi_deploy, 'continue_deploy', autospec=True)
@mock.patch.object(iscsi_deploy, 'build_deploy_ramdisk_options',
autospec=True)
def test_do_agent_iscsi_deploy_preserve_ephemeral(self, build_options_mock,
continue_deploy_mock):
"""Ensure the disk is not wiped if preserve_ephemeral is True."""
build_options_mock.return_value = {'deployment_key': 'abcdef',
'iscsi_target_iqn': 'iqn-qweqwe',
'iscsi_portal_port': 3260}
agent_client_mock = mock.MagicMock(spec_set=agent_client.AgentClient)
agent_client_mock.start_iscsi_target.return_value = {
'command_status': 'SUCCESS', 'command_error': None}
driver_internal_info = {
'agent_url': 'http://1.2.3.4:1234'}
self.node.driver_internal_info = driver_internal_info
self.node.save()
uuid_dict_returned = {'root uuid': 'some-root-uuid'}
continue_deploy_mock.return_value = uuid_dict_returned
with task_manager.acquire(self.context, self.node.uuid,
shared=False) as task:
task.node.instance_info['preserve_ephemeral'] = True
iscsi_deploy.do_agent_iscsi_deploy(
task, agent_client_mock)
build_options_mock.assert_called_once_with(task.node)
agent_client_mock.start_iscsi_target.assert_called_once_with(
task.node, 'iqn-qweqwe', 3260, wipe_disk_metadata=False)
@mock.patch.object(iscsi_deploy, 'build_deploy_ramdisk_options', @mock.patch.object(iscsi_deploy, 'build_deploy_ramdisk_options',
autospec=True) autospec=True)
def test_do_agent_iscsi_deploy_start_iscsi_failure(self, def test_do_agent_iscsi_deploy_start_iscsi_failure(self,
@ -552,7 +580,7 @@ class IscsiDeployMethodsTestCase(db_base.DbTestCase):
task, agent_client_mock) task, agent_client_mock)
build_options_mock.assert_called_once_with(task.node) build_options_mock.assert_called_once_with(task.node)
agent_client_mock.start_iscsi_target.assert_called_once_with( agent_client_mock.start_iscsi_target.assert_called_once_with(
task.node, 'iqn-qweqwe', 3260) task.node, 'iqn-qweqwe', 3260, wipe_disk_metadata=True)
self.node.refresh() self.node.refresh()
self.assertEqual(states.DEPLOYFAIL, self.node.provision_state) self.assertEqual(states.DEPLOYFAIL, self.node.provision_state)
self.assertEqual(states.ACTIVE, self.node.target_provision_state) self.assertEqual(states.ACTIVE, self.node.target_provision_state)

View File

@ -0,0 +1,9 @@
---
fixes:
- Fixed a bug that was causing grub installation failure. If the disk
was already coming with a partition table, the conductor was not able
to wipe it properly and the new partition table would conflict with
the old one. The issue was only impacting new nodes and installations
with automated_clean disabled in the configuration.
A disk instance without preserve_ephemeral is now purged before new deployment.
See https://bugs.launchpad.net/ironic-lib/+bug/1550604