Merge "Generate iPXE boot script when deploying with boot from volume"

This commit is contained in:
Jenkins 2017-07-14 23:41:49 +00:00 committed by Gerrit Code Review
commit 4035eb7942
4 changed files with 105 additions and 37 deletions

View File

@ -452,16 +452,18 @@ class AgentDeploy(AgentDeployMixin, base.DeployInterface):
if node.provision_state == states.ACTIVE: if node.provision_state == states.ACTIVE:
# Call is due to conductor takeover # Call is due to conductor takeover
task.driver.boot.prepare_instance(task) task.driver.boot.prepare_instance(task)
elif not task.driver.storage.should_write_image(task):
# We have nothing else to do as this is handled in the
# backend storage system.
return
elif node.provision_state != states.ADOPTING: elif node.provision_state != states.ADOPTING:
node.instance_info = deploy_utils.build_instance_info_for_deploy(
task) if task.driver.storage.should_write_image(task):
node.save() instance_info = deploy_utils.build_instance_info_for_deploy(
task)
node.instance_info = instance_info
node.save()
if CONF.agent.manage_agent_boot: if CONF.agent.manage_agent_boot:
deploy_opts = deploy_utils.build_agent_options(node) if task.driver.storage.should_write_image(task):
deploy_opts = deploy_utils.build_agent_options(node)
else:
deploy_opts = None
task.driver.boot.prepare_ramdisk(task, deploy_opts) task.driver.boot.prepare_ramdisk(task, deploy_opts)
@METRICS.timer('AgentDeploy.clean_up') @METRICS.timer('AgentDeploy.clean_up')

View File

@ -472,6 +472,8 @@ class PXEBoot(base.BootInterface):
if (not os.path.isfile(bootfile_path) or if (not os.path.isfile(bootfile_path) or
not utils.file_has_content(bootfile_path, boot_script)): not utils.file_has_content(bootfile_path, boot_script)):
utils.write_to_file(bootfile_path, boot_script) utils.write_to_file(bootfile_path, boot_script)
if not task.driver.storage.should_write_image(task):
return
dhcp_opts = pxe_utils.dhcp_options_for_instance(task) dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
provider = dhcp_factory.DHCPFactory() provider = dhcp_factory.DHCPFactory()

View File

@ -426,6 +426,30 @@ class TestAgentDeploy(db_base.DbTestCase):
self.assertFalse(pxe_prepare_ramdisk_mock.called) self.assertFalse(pxe_prepare_ramdisk_mock.called)
self.assertFalse(add_provisioning_net_mock.called) self.assertFalse(add_provisioning_net_mock.called)
@mock.patch('ironic.drivers.modules.network.flat.FlatNetwork.'
'add_provisioning_network', autospec=True)
@mock.patch.object(pxe.PXEBoot, 'prepare_ramdisk')
@mock.patch.object(deploy_utils, 'build_agent_options')
@mock.patch.object(deploy_utils, 'build_instance_info_for_deploy')
@mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
autospec=True)
def test_prepare_boot_from_volume(self, mock_write,
build_instance_info_mock,
build_options_mock,
pxe_prepare_ramdisk_mock,
add_provisioning_net_mock):
mock_write.return_value = False
with task_manager.acquire(
self.context, self.node['uuid'], shared=False) as task:
task.node.provision_state = states.DEPLOYING
build_instance_info_mock.return_value = {'foo': 'bar'}
build_options_mock.return_value = {'a': 'b'}
self.driver.prepare(task)
build_instance_info_mock.assert_not_called()
build_options_mock.assert_not_called()
pxe_prepare_ramdisk_mock.assert_called_once_with(task, None)
@mock.patch('ironic.common.dhcp_factory.DHCPFactory._set_dhcp_provider') @mock.patch('ironic.common.dhcp_factory.DHCPFactory._set_dhcp_provider')
@mock.patch('ironic.common.dhcp_factory.DHCPFactory.clean_dhcp') @mock.patch('ironic.common.dhcp_factory.DHCPFactory.clean_dhcp')
@mock.patch.object(pxe.PXEBoot, 'clean_up_instance') @mock.patch.object(pxe.PXEBoot, 'clean_up_instance')

View File

@ -808,7 +808,10 @@ class PXEBootTestCase(db_base.DbTestCase):
@mock.patch.object(pxe, '_cache_ramdisk_kernel', autospec=True) @mock.patch.object(pxe, '_cache_ramdisk_kernel', autospec=True)
@mock.patch.object(pxe, '_build_pxe_config_options', autospec=True) @mock.patch.object(pxe, '_build_pxe_config_options', autospec=True)
@mock.patch.object(pxe_utils, 'create_pxe_config', autospec=True) @mock.patch.object(pxe_utils, 'create_pxe_config', autospec=True)
def _test_prepare_ramdisk(self, mock_pxe_config, @mock.patch.object(noop_storage.NoopStorage, 'should_write_image',
autospec=True)
def _test_prepare_ramdisk(self, mock_should_write_image,
mock_pxe_config,
mock_build_pxe, mock_cache_r_k, mock_build_pxe, mock_cache_r_k,
mock_deploy_img_info, mock_deploy_img_info,
mock_instance_img_info, mock_instance_img_info,
@ -817,7 +820,9 @@ class PXEBootTestCase(db_base.DbTestCase):
uefi=False, uefi=False,
cleaning=False, cleaning=False,
ipxe_use_swift=False, ipxe_use_swift=False,
whole_disk_image=False): whole_disk_image=False,
should_write_image=True):
mock_should_write_image.return_value = should_write_image
mock_build_pxe.return_value = {} mock_build_pxe.return_value = {}
mock_deploy_img_info.return_value = {'deploy_kernel': 'a'} mock_deploy_img_info.return_value = {'deploy_kernel': 'a'}
if whole_disk_image: if whole_disk_image:
@ -833,38 +838,51 @@ class PXEBootTestCase(db_base.DbTestCase):
self.node.driver_internal_info = driver_internal_info self.node.driver_internal_info = driver_internal_info
self.node.save() self.node.save()
with task_manager.acquire(self.context, self.node.uuid) as task: with task_manager.acquire(self.context, self.node.uuid) as task:
dhcp_opts = pxe_utils.dhcp_options_for_instance(task) if should_write_image:
dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
task.driver.boot.prepare_ramdisk(task, {'foo': 'bar'}) task.driver.boot.prepare_ramdisk(task, {'foo': 'bar'})
mock_deploy_img_info.assert_called_once_with(task.node) if should_write_image:
provider_mock.update_dhcp.assert_called_once_with(task, dhcp_opts) mock_deploy_img_info.assert_called_once_with(task.node)
set_boot_device_mock.assert_called_once_with(task, provider_mock.update_dhcp.assert_called_once_with(task,
boot_devices.PXE, dhcp_opts)
persistent=False) set_boot_device_mock.assert_called_once_with(task,
if ipxe_use_swift: boot_devices.PXE,
if whole_disk_image: persistent=False)
self.assertFalse(mock_cache_r_k.called) if ipxe_use_swift:
if whole_disk_image:
self.assertFalse(mock_cache_r_k.called)
else:
mock_cache_r_k.assert_called_once_with(
self.context, task.node,
{'kernel': 'b'})
mock_instance_img_info.assert_called_once_with(
task.node, self.context)
elif cleaning is False:
mock_cache_r_k.assert_called_once_with(
self.context, task.node,
{'deploy_kernel': 'a', 'kernel': 'b'})
mock_instance_img_info.assert_called_once_with(
task.node, self.context)
else: else:
mock_cache_r_k.assert_called_once_with( mock_cache_r_k.assert_called_once_with(
self.context, task.node, self.context, task.node,
{'kernel': 'b'}) {'deploy_kernel': 'a'})
mock_instance_img_info.assert_called_once_with(task.node, if uefi:
self.context) mock_pxe_config.assert_called_once_with(
elif cleaning is False: task, {'foo': 'bar'},
mock_cache_r_k.assert_called_once_with( CONF.pxe.uefi_pxe_config_template)
self.context, task.node, else:
{'deploy_kernel': 'a', 'kernel': 'b'}) mock_pxe_config.assert_called_once_with(
mock_instance_img_info.assert_called_once_with(task.node, task, {'foo': 'bar'}, CONF.pxe.pxe_config_template)
self.context)
else: else:
mock_cache_r_k.assert_called_once_with( # When booting from volume we return early.
self.context, task.node, # Check that nothing was called
{'deploy_kernel': 'a'}) self.assertFalse(mock_pxe_config.called)
if uefi: self.assertFalse(mock_build_pxe.called)
mock_pxe_config.assert_called_once_with( self.assertFalse(mock_cache_r_k.called)
task, {'foo': 'bar'}, CONF.pxe.uefi_pxe_config_template) self.assertFalse(mock_deploy_img_info.called)
else: self.assertFalse(mock_instance_img_info.called)
mock_pxe_config.assert_called_once_with( self.assertFalse(dhcp_factory_mock.called)
task, {'foo': 'bar'}, CONF.pxe.pxe_config_template)
def test_prepare_ramdisk(self): def test_prepare_ramdisk(self):
self.node.provision_state = states.DEPLOYING self.node.provision_state = states.DEPLOYING
@ -926,6 +944,28 @@ class PXEBootTestCase(db_base.DbTestCase):
CONF.pxe.ipxe_boot_script, CONF.pxe.ipxe_boot_script,
{'ipxe_for_mac_uri': 'pxelinux.cfg/'}) {'ipxe_for_mac_uri': 'pxelinux.cfg/'})
@mock.patch.object(os.path, 'isfile', autospec=True)
@mock.patch('ironic.common.utils.file_has_content', autospec=True)
@mock.patch('ironic.common.utils.write_to_file', autospec=True)
@mock.patch('ironic.common.utils.render_template', autospec=True)
def test_prepare_ramdisk_ipxe_boot_from_volume(
self, render_mock, write_mock, cmp_mock, isfile_mock):
self.node.provision_state = states.DEPLOYING
self.node.save()
self.config(group='pxe', ipxe_enabled=True)
isfile_mock.return_value = False
render_mock.return_value = 'foo'
self._test_prepare_ramdisk(should_write_image=False)
self.assertFalse(cmp_mock.called)
write_mock.assert_called_once_with(
os.path.join(
CONF.deploy.http_root,
os.path.basename(CONF.pxe.ipxe_boot_script)),
'foo')
render_mock.assert_called_once_with(
CONF.pxe.ipxe_boot_script,
{'ipxe_for_mac_uri': 'pxelinux.cfg/'})
@mock.patch.object(os.path, 'isfile', autospec=True) @mock.patch.object(os.path, 'isfile', autospec=True)
@mock.patch('ironic.common.utils.file_has_content', autospec=True) @mock.patch('ironic.common.utils.file_has_content', autospec=True)
@mock.patch('ironic.common.utils.write_to_file', autospec=True) @mock.patch('ironic.common.utils.write_to_file', autospec=True)