summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/admin/anaconda-deploy-interface.rst8
-rw-r--r--doc/source/admin/dhcp-less.rst11
-rw-r--r--doc/source/contributor/webapi-version-history.rst5
-rw-r--r--ironic/common/release_mappings.py20
-rw-r--r--ironic/drivers/modules/image_utils.py13
-rw-r--r--ironic/drivers/modules/redfish/boot.py6
-rw-r--r--ironic/tests/unit/drivers/modules/test_image_utils.py89
-rw-r--r--releasenotes/notes/deprecate-syslinux-support-98d327c67607fc8e.yaml2
-rw-r--r--releasenotes/notes/fix-pxe-glance-lookup-anaconda-86fe616c6286ec08.yaml2
-rw-r--r--releasenotes/notes/override-external_http_url-per-node-f5423b00b373e528.yaml8
-rw-r--r--releasenotes/notes/prevent-pxe-retry-when-token-exists-a4f38f7da56c1397.yaml2
11 files changed, 151 insertions, 15 deletions
diff --git a/doc/source/admin/anaconda-deploy-interface.rst b/doc/source/admin/anaconda-deploy-interface.rst
index e715a1b23..2c686506a 100644
--- a/doc/source/admin/anaconda-deploy-interface.rst
+++ b/doc/source/admin/anaconda-deploy-interface.rst
@@ -187,7 +187,8 @@ as it accounts for the particular stages and appropriate callbacks to
Ironic.
.. warning::
- The default template expects a ``instance_info\liveimg_url`` setting to
+ The default template (for the kickstart 'liveimg' command) expects an
+ ``instance_info\image_info`` setting to
be provided by the user, which serves as a base operating system image.
In the context of the anaconda driver, it should be thought of almost
like "stage3". If you're using a custom template, it may not be required,
@@ -201,12 +202,13 @@ Ironic.
--instance_info ks_template=<URL>
If you do choose to use a liveimg with a customized template, or if you wish
-to use the stock template with a liveimg, you will need to provide parameter.
+to use the stock template with a liveimg, you will need to provide this
+setting.
.. code-block:: shell
baremetal node set <node> \
- --instance_info liveimg_url=<URL>
+ --instance_info image_info=<URL>
.. warning::
This is required if you do *not* utilize a customised template. As in use
diff --git a/doc/source/admin/dhcp-less.rst b/doc/source/admin/dhcp-less.rst
index 089829e25..a14c2499d 100644
--- a/doc/source/admin/dhcp-less.rst
+++ b/doc/source/admin/dhcp-less.rst
@@ -127,3 +127,14 @@ the service catalog or configured in the ``[service_catalog]`` section:
[deploy]
external_callback_url = <Bare Metal API URL with a routable IP address>
+
+
+In case you need specific URLs for each node, you can use the
+``driver_info[external_http_url]`` node property. When used it overrides the
+``[deploy]http_url`` and ``[deploy]external_http_url`` settings in the
+configuration file.
+
+.. code-block:: bash
+
+ baremetal node set node-0 \
+ --driver-info external_http_url="<your_node_external_url>"
diff --git a/doc/source/contributor/webapi-version-history.rst b/doc/source/contributor/webapi-version-history.rst
index f90cb3c6c..58c0598eb 100644
--- a/doc/source/contributor/webapi-version-history.rst
+++ b/doc/source/contributor/webapi-version-history.rst
@@ -2,6 +2,11 @@
REST API Version History
========================
+1.79 (Zed, 21.0)
+----------------------
+A node with the same name as the allocation ``name`` is moved to the
+start of the derived candidate list.
+
1.78 (Xena, 18.2)
----------------------
Add endpoints to allow history events for nodes to be retrieved via
diff --git a/ironic/common/release_mappings.py b/ironic/common/release_mappings.py
index aaf423bfe..9dfe864ee 100644
--- a/ironic/common/release_mappings.py
+++ b/ironic/common/release_mappings.py
@@ -470,6 +470,26 @@ RELEASE_MAPPING = {
'VolumeTarget': ['1.0'],
}
},
+ '21.0': {
+ 'api': '1.79',
+ 'rpc': '1.55',
+ 'objects': {
+ 'Allocation': ['1.1'],
+ 'BIOSSetting': ['1.1'],
+ 'Node': ['1.36'],
+ 'NodeHistory': ['1.0'],
+ 'Conductor': ['1.3'],
+ 'Chassis': ['1.3'],
+ 'Deployment': ['1.0'],
+ 'DeployTemplate': ['1.1'],
+ 'Port': ['1.10'],
+ 'Portgroup': ['1.4'],
+ 'Trait': ['1.0'],
+ 'TraitList': ['1.0'],
+ 'VolumeConnector': ['1.0'],
+ 'VolumeTarget': ['1.0'],
+ }
+ },
'master': {
'api': '1.79',
'rpc': '1.55',
diff --git a/ironic/drivers/modules/image_utils.py b/ironic/drivers/modules/image_utils.py
index bb0dfa166..304c199bf 100644
--- a/ironic/drivers/modules/image_utils.py
+++ b/ironic/drivers/modules/image_utils.py
@@ -169,7 +169,7 @@ class ImageHandler(object):
return urlparse.urlunparse(parsed_url)
- def publish_image(self, image_file, object_name):
+ def publish_image(self, image_file, object_name, node_http_url=None):
"""Make image file downloadable.
Depending on ironic settings, pushes given file into Swift or copies
@@ -178,6 +178,9 @@ class ImageHandler(object):
:param image_file: path to file to publish
:param object_name: name of the published file
+ :param node_http_url: a url to be used to publish the image. If set,
+ the values from external_http_url and http_url
+ from CONF.deploy won't be used.
:return: a URL to download published file
"""
@@ -220,7 +223,8 @@ class ImageHandler(object):
shutil.copyfile(image_file, published_file)
os.chmod(published_file, self._file_permission)
- http_url = CONF.deploy.external_http_url or CONF.deploy.http_url
+ http_url = (node_http_url or CONF.deploy.external_http_url
+ or CONF.deploy.http_url)
image_url = os.path.join(http_url, self._image_subdir, object_name)
return image_url
@@ -302,8 +306,9 @@ def prepare_floppy_image(task, params=None):
images.create_vfat_image(vfat_image_tmpfile, parameters=params)
img_handler = ImageHandler(task.node.driver)
-
- image_url = img_handler.publish_image(vfat_image_tmpfile, object_name)
+ node_http_url = task.node.driver_info.get("external_http_url")
+ image_url = img_handler.publish_image(vfat_image_tmpfile, object_name,
+ node_http_url)
LOG.debug("Created floppy image %(name)s in Swift for node %(node)s, "
"exposed as temporary URL "
diff --git a/ironic/drivers/modules/redfish/boot.py b/ironic/drivers/modules/redfish/boot.py
index 164425eee..a321c08ec 100644
--- a/ironic/drivers/modules/redfish/boot.py
+++ b/ironic/drivers/modules/redfish/boot.py
@@ -53,7 +53,11 @@ OPTIONAL_PROPERTIES = {
"used by ironic when building UEFI-bootable ISO "
"out of kernel and ramdisk. Required for UEFI "
"when deploy_iso is not provided."),
-
+ 'external_http_url': _("External URL that is used when the image could "
+ "be served outside of the provisioning network. "
+ "If set it will have priority over the following "
+ "configs: CONF.deploy.external_http_url and "
+ "CONF.deploy.http_url. Defaults to None.")
}
RESCUE_PROPERTIES = {
diff --git a/ironic/tests/unit/drivers/modules/test_image_utils.py b/ironic/tests/unit/drivers/modules/test_image_utils.py
index 6d79629d9..753452f5d 100644
--- a/ironic/tests/unit/drivers/modules/test_image_utils.py
+++ b/ironic/tests/unit/drivers/modules/test_image_utils.py
@@ -151,6 +151,32 @@ class RedfishImageHandlerTestCase(db_base.DbTestCase):
@mock.patch.object(image_utils, 'shutil', autospec=True)
@mock.patch.object(os, 'link', autospec=True)
@mock.patch.object(os, 'mkdir', autospec=True)
+ def test_publish_image_external_ip_node_override(
+ self, mock_mkdir, mock_link, mock_shutil, mock_chmod):
+ self.config(use_swift=False, group='redfish')
+ self.config(http_url='http://localhost',
+ external_http_url='http://non-local.host',
+ group='deploy')
+ img_handler_obj = image_utils.ImageHandler(self.node.driver)
+ self.node.driver_info["external_http_url"] = "http://node.override.url"
+
+ override_url = self.node.driver_info.get("external_http_url")
+
+ url = img_handler_obj.publish_image('file.iso', 'boot.iso',
+ override_url)
+
+ self.assertEqual(
+ 'http://node.override.url/redfish/boot.iso', url)
+
+ mock_mkdir.assert_called_once_with('/httpboot/redfish', 0o755)
+ mock_link.assert_called_once_with(
+ 'file.iso', '/httpboot/redfish/boot.iso')
+ mock_chmod.assert_called_once_with('file.iso', 0o644)
+
+ @mock.patch.object(os, 'chmod', autospec=True)
+ @mock.patch.object(image_utils, 'shutil', autospec=True)
+ @mock.patch.object(os, 'link', autospec=True)
+ @mock.patch.object(os, 'mkdir', autospec=True)
def test_publish_image_local_copy(self, mock_mkdir, mock_link,
mock_shutil, mock_chmod):
self.config(use_swift=False, group='redfish')
@@ -271,8 +297,8 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
object_name = 'image-%s' % task.node.uuid
- mock_publish_image.assert_called_once_with(mock.ANY,
- mock.ANY, object_name)
+ mock_publish_image.assert_called_once_with(mock.ANY, mock.ANY,
+ object_name, None)
mock_create_vfat_image.assert_called_once_with(
mock.ANY, parameters=None)
@@ -295,8 +321,63 @@ class RedfishImageUtilsTestCase(db_base.DbTestCase):
object_name = 'image-%s' % task.node.uuid
- mock_publish_image.assert_called_once_with(mock.ANY,
- mock.ANY, object_name)
+ mock_publish_image.assert_called_once_with(mock.ANY, mock.ANY,
+ object_name, None)
+
+ mock_create_vfat_image.assert_called_once_with(
+ mock.ANY, parameters={"ipa-api-url": "http://callback"})
+
+ self.assertEqual(expected_url, url)
+
+ @mock.patch.object(image_utils.ImageHandler, 'publish_image',
+ autospec=True)
+ @mock.patch.object(images, 'create_vfat_image', autospec=True)
+ def test_prepare_floppy_image_publish_with_config_external_http_url(
+ self, mock_create_vfat_image, mock_publish_image):
+ self.config(external_callback_url='http://callback/',
+ external_http_url='http://config.external.url',
+ group='deploy')
+ with task_manager.acquire(self.context, self.node.uuid,
+ shared=True) as task:
+ expected_url = 'https://config.external.url/c.f?e=f'
+
+ mock_publish_image.return_value = expected_url
+
+ url = image_utils.prepare_floppy_image(task)
+
+ object_name = 'image-%s' % task.node.uuid
+
+ mock_publish_image.assert_called_once_with(mock.ANY, mock.ANY,
+ object_name, None)
+
+ mock_create_vfat_image.assert_called_once_with(
+ mock.ANY, parameters={"ipa-api-url": "http://callback"})
+
+ self.assertEqual(expected_url, url)
+
+ @mock.patch.object(image_utils.ImageHandler, 'publish_image',
+ autospec=True)
+ @mock.patch.object(images, 'create_vfat_image', autospec=True)
+ def test_prepare_floppy_image_publish_with_node_external_http_url(
+ self, mock_create_vfat_image, mock_publish_image):
+ self.config(external_callback_url='http://callback/',
+ external_http_url='http://config.external.url',
+ group='deploy')
+ with task_manager.acquire(self.context, self.node.uuid,
+ shared=True) as task:
+ task.node.driver_info["external_http_url"] = \
+ "https://node.external"
+ override_url = task.node.driver_info.get("external_http_url")
+ expected_url = '"https://node.external/c.f?e=f'
+
+ mock_publish_image.return_value = expected_url
+
+ url = image_utils.prepare_floppy_image(task)
+
+ object_name = 'image-%s' % task.node.uuid
+
+ mock_publish_image.assert_called_once_with(
+ mock.ANY, mock.ANY, object_name, override_url)
mock_create_vfat_image.assert_called_once_with(
mock.ANY, parameters={"ipa-api-url": "http://callback"})
diff --git a/releasenotes/notes/deprecate-syslinux-support-98d327c67607fc8e.yaml b/releasenotes/notes/deprecate-syslinux-support-98d327c67607fc8e.yaml
index 670047a82..9543f9d84 100644
--- a/releasenotes/notes/deprecate-syslinux-support-98d327c67607fc8e.yaml
+++ b/releasenotes/notes/deprecate-syslinux-support-98d327c67607fc8e.yaml
@@ -23,4 +23,4 @@ deprecations:
- Deprecation of ``pxelinux``, as a result of the deprecation of ``syslinux``,
does ultimately mean the default for the ``pxe`` boot_interface to carry
defaults for the use of grub based network booting, specifically for
- for operators who are unable to use iPXE.
+ operators who are unable to use iPXE.
diff --git a/releasenotes/notes/fix-pxe-glance-lookup-anaconda-86fe616c6286ec08.yaml b/releasenotes/notes/fix-pxe-glance-lookup-anaconda-86fe616c6286ec08.yaml
index bf6b8ea85..961b49cb0 100644
--- a/releasenotes/notes/fix-pxe-glance-lookup-anaconda-86fe616c6286ec08.yaml
+++ b/releasenotes/notes/fix-pxe-glance-lookup-anaconda-86fe616c6286ec08.yaml
@@ -2,5 +2,5 @@
fixes:
- |
Fixes an issue in the ``anaconda`` deployment interface where PXE argument
- processing and preparation was erroniously directly connecting to Glance,
+ processing and preparation was erroneously directly connecting to Glance,
potentially leading to an exception in the standalone use case.
diff --git a/releasenotes/notes/override-external_http_url-per-node-f5423b00b373e528.yaml b/releasenotes/notes/override-external_http_url-per-node-f5423b00b373e528.yaml
new file mode 100644
index 000000000..93e661ba7
--- /dev/null
+++ b/releasenotes/notes/override-external_http_url-per-node-f5423b00b373e528.yaml
@@ -0,0 +1,8 @@
+---
+features:
+ - |
+ Nodes using virtual media can now specify their own external URL.
+ This setting can be leveraged via the ``driver_info\external_http_url``
+ node setting.
+ When used, this setting overrides the ``[deploy]http_url`` and
+ ``[deploy]external_http_url`` settings in the configuration file.
diff --git a/releasenotes/notes/prevent-pxe-retry-when-token-exists-a4f38f7da56c1397.yaml b/releasenotes/notes/prevent-pxe-retry-when-token-exists-a4f38f7da56c1397.yaml
index 5db6db6ec..62e7ae9ca 100644
--- a/releasenotes/notes/prevent-pxe-retry-when-token-exists-a4f38f7da56c1397.yaml
+++ b/releasenotes/notes/prevent-pxe-retry-when-token-exists-a4f38f7da56c1397.yaml
@@ -1,7 +1,7 @@
---
fixes:
- |
- Fixes a race condition in PXE initialization where logic to retry
+ Fixes a race condition in PXE initialization where the logic to retry
what we suspect as potentially failed PXE boot operations was not
consulting if an ``agent token`` had been established, which is the
very first step in agent initialization.