Copy iPXE script over only when needed
currently the iPXE boot script is overwritten on every `prepare_ramdisk` call, which is inefficient. Instead, copy it over only when it is missing from HTTPROOT or is different from the one specified in the config. The comparison is performed using `filecmp` from Python standard lib, which in turn uses `os.stat()`, so although being not very strict, comparison does not call to any extra utilities and is fast. Change-Id: I1213fc9a9945e11f963d10f0581a7d69ef13ee53
This commit is contained in:
parent
8783e8d036
commit
4a0767a14c
@ -15,6 +15,7 @@
|
||||
PXE Boot Interface
|
||||
"""
|
||||
|
||||
import filecmp
|
||||
import os
|
||||
import shutil
|
||||
|
||||
@ -413,13 +414,14 @@ class PXEBoot(base.BootInterface):
|
||||
"""
|
||||
node = task.node
|
||||
|
||||
# TODO(deva): optimize this if rerun on existing files
|
||||
if CONF.pxe.ipxe_enabled:
|
||||
# Copy the iPXE boot script to HTTP root directory
|
||||
bootfile_path = os.path.join(
|
||||
CONF.deploy.http_root,
|
||||
os.path.basename(CONF.pxe.ipxe_boot_script))
|
||||
shutil.copyfile(CONF.pxe.ipxe_boot_script, bootfile_path)
|
||||
if (not os.path.isfile(bootfile_path) or
|
||||
not filecmp.cmp(CONF.pxe.ipxe_boot_script, bootfile_path)):
|
||||
shutil.copyfile(CONF.pxe.ipxe_boot_script, bootfile_path)
|
||||
|
||||
dhcp_opts = pxe_utils.dhcp_options_for_instance(task)
|
||||
provider = dhcp_factory.DHCPFactory()
|
||||
|
@ -15,6 +15,7 @@
|
||||
|
||||
"""Test class for PXE driver."""
|
||||
|
||||
import filecmp
|
||||
import os
|
||||
import shutil
|
||||
import tempfile
|
||||
@ -698,12 +699,17 @@ class PXEBootTestCase(db_base.DbTestCase):
|
||||
self.node.save()
|
||||
self._test_prepare_ramdisk(uefi=True)
|
||||
|
||||
@mock.patch.object(os.path, 'isfile', autospec=True)
|
||||
@mock.patch.object(filecmp, 'cmp', autospec=True)
|
||||
@mock.patch.object(shutil, 'copyfile', autospec=True)
|
||||
def test_prepare_ramdisk_ipxe(self, copyfile_mock):
|
||||
def test_prepare_ramdisk_ipxe_with_copy_file_different(
|
||||
self, copyfile_mock, cmp_mock, isfile_mock):
|
||||
self.node.provision_state = states.DEPLOYING
|
||||
self.node.save()
|
||||
self.config(group='pxe', ipxe_enabled=True)
|
||||
self.config(group='deploy', http_url='http://myserver')
|
||||
isfile_mock.return_value = True
|
||||
cmp_mock.return_value = False
|
||||
self._test_prepare_ramdisk()
|
||||
copyfile_mock.assert_called_once_with(
|
||||
CONF.pxe.ipxe_boot_script,
|
||||
@ -711,6 +717,38 @@ class PXEBootTestCase(db_base.DbTestCase):
|
||||
CONF.deploy.http_root,
|
||||
os.path.basename(CONF.pxe.ipxe_boot_script)))
|
||||
|
||||
@mock.patch.object(os.path, 'isfile', autospec=True)
|
||||
@mock.patch.object(filecmp, 'cmp', autospec=True)
|
||||
@mock.patch.object(shutil, 'copyfile', autospec=True)
|
||||
def test_prepare_ramdisk_ipxe_with_copy_no_file(
|
||||
self, copyfile_mock, cmp_mock, isfile_mock):
|
||||
self.node.provision_state = states.DEPLOYING
|
||||
self.node.save()
|
||||
self.config(group='pxe', ipxe_enabled=True)
|
||||
self.config(group='deploy', http_url='http://myserver')
|
||||
isfile_mock.return_value = False
|
||||
self._test_prepare_ramdisk()
|
||||
self.assertFalse(cmp_mock.called)
|
||||
copyfile_mock.assert_called_once_with(
|
||||
CONF.pxe.ipxe_boot_script,
|
||||
os.path.join(
|
||||
CONF.deploy.http_root,
|
||||
os.path.basename(CONF.pxe.ipxe_boot_script)))
|
||||
|
||||
@mock.patch.object(os.path, 'isfile', autospec=True)
|
||||
@mock.patch.object(filecmp, 'cmp', autospec=True)
|
||||
@mock.patch.object(shutil, 'copyfile', autospec=True)
|
||||
def test_prepare_ramdisk_ipxe_without_copy(
|
||||
self, copyfile_mock, cmp_mock, isfile_mock):
|
||||
self.node.provision_state = states.DEPLOYING
|
||||
self.node.save()
|
||||
self.config(group='pxe', ipxe_enabled=True)
|
||||
self.config(group='deploy', http_url='http://myserver')
|
||||
isfile_mock.return_value = True
|
||||
cmp_mock.return_value = True
|
||||
self._test_prepare_ramdisk()
|
||||
self.assertFalse(copyfile_mock.called)
|
||||
|
||||
def test_prepare_ramdisk_cleaning(self):
|
||||
self.node.provision_state = states.CLEANING
|
||||
self.node.save()
|
||||
|
Loading…
Reference in New Issue
Block a user