summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--doc/source/admin/console.rst18
-rw-r--r--doc/source/install/configure-cleaning.rst2
-rw-r--r--doc/source/install/configure-compute.rst4
-rw-r--r--doc/source/install/configure-pxe.rst38
-rw-r--r--doc/source/install/configure-tenant-networks.rst2
-rw-r--r--doc/source/install/enabling-https.rst4
-rw-r--r--doc/source/install/include/configure-ironic-api-mod_wsgi.inc10
-rw-r--r--doc/source/install/include/configure-ironic-api.inc2
-rw-r--r--doc/source/install/install-obs.rst2
-rw-r--r--doc/source/install/install-rdo.rst16
-rw-r--r--doc/source/install/install-ubuntu.rst2
-rw-r--r--ironic/common/pxe_utils.py14
-rw-r--r--ironic/drivers/modules/drac/management.py2
-rw-r--r--ironic/drivers/modules/redfish/management.py44
-rw-r--r--ironic/tests/unit/common/test_pxe_utils.py32
-rw-r--r--ironic/tests/unit/drivers/modules/drac/test_management.py4
-rw-r--r--ironic/tests/unit/drivers/modules/redfish/test_management.py77
-rw-r--r--ironic/tests/unit/drivers/third_party_driver_mocks.py2
-rw-r--r--releasenotes/notes/fix-grub2-config-file-name-88e689a982a21684.yaml7
-rw-r--r--releasenotes/notes/redfish-boot-mode-override-not-present-handling-92e7263617e467c4.yaml9
-rw-r--r--releasenotes/notes/restrict-sync-mode-after-device-to-supermicro-218e8cb57735c685.yaml11
-rw-r--r--releasenotes/notes/supermicro-redfish-override-enabled-aa51686ed33d3061.yaml15
-rw-r--r--releasenotes/notes/update-clear-job-id-constant-fix-c69cf96c55364bb3.yaml7
-rwxr-xr-xtools/test-setup.sh4
24 files changed, 235 insertions, 93 deletions
diff --git a/doc/source/admin/console.rst b/doc/source/admin/console.rst
index 618954799..b8821248e 100644
--- a/doc/source/admin/console.rst
+++ b/doc/source/admin/console.rst
@@ -33,11 +33,7 @@ The web console can be configured in Bare Metal service in the following way:
sudo apt-get install shellinabox
- RHEL7/CentOS7::
-
- sudo yum install shellinabox
-
- Fedora::
+ RHEL8/CentOS8/Fedora::
sudo dnf install shellinabox
@@ -52,11 +48,7 @@ The web console can be configured in Bare Metal service in the following way:
sudo apt-get install openssl
- RHEL7/CentOS7::
-
- sudo yum install openssl
-
- Fedora::
+ RHEL8/CentOS8/Fedora::
sudo dnf install openssl
@@ -182,11 +174,7 @@ Serial consoles can be configured in the Bare Metal service as follows:
sudo apt-get install socat
- RHEL7/CentOS7::
-
- sudo yum install socat
-
- Fedora::
+ RHEL8/CentOS8/Fedora::
sudo dnf install socat
diff --git a/doc/source/install/configure-cleaning.rst b/doc/source/install/configure-cleaning.rst
index 8579f53b0..b7a29e320 100644
--- a/doc/source/install/configure-cleaning.rst
+++ b/doc/source/install/configure-cleaning.rst
@@ -29,7 +29,7 @@ Configure the Bare Metal service for cleaning
.. code-block:: console
- Fedora/RHEL7/CentOS7/SUSE:
+ Fedora/RHEL8/CentOS8/SUSE:
sudo systemctl restart openstack-ironic-conductor
Ubuntu:
diff --git a/doc/source/install/configure-compute.rst b/doc/source/install/configure-compute.rst
index 631cb0b6e..299b4a5ea 100644
--- a/doc/source/install/configure-compute.rst
+++ b/doc/source/install/configure-compute.rst
@@ -137,7 +137,7 @@ service's controller nodes and compute nodes.
.. code-block:: console
- Fedora/RHEL7/CentOS7/SUSE:
+ Fedora/RHEL8/CentOS8/SUSE:
sudo systemctl restart openstack-nova-scheduler
Ubuntu:
@@ -148,7 +148,7 @@ service's controller nodes and compute nodes.
.. code-block:: console
- Fedora/RHEL7/CentOS7/SUSE:
+ Fedora/RHEL8/CentOS8/SUSE:
sudo systemctl restart openstack-nova-compute
Ubuntu:
diff --git a/doc/source/install/configure-pxe.rst b/doc/source/install/configure-pxe.rst
index 56f345eff..8769375f4 100644
--- a/doc/source/install/configure-pxe.rst
+++ b/doc/source/install/configure-pxe.rst
@@ -58,11 +58,7 @@ set up on the Bare Metal service nodes which run the ``ironic-conductor``.
sudo apt-get install xinetd tftpd-hpa
- RHEL7/CentOS7::
-
- sudo yum install tftp-server xinetd
-
- Fedora::
+ RHEL8/CentOS8/Fedora::
sudo dnf install tftp-server xinetd
@@ -94,7 +90,7 @@ set up on the Bare Metal service nodes which run the ``ironic-conductor``.
sudo service xinetd restart
- Fedora/RHEL7/CentOS7/SUSE::
+ Fedora/RHEL8/CentOS8/SUSE::
sudo systemctl restart xinetd
@@ -130,11 +126,7 @@ the PXE UEFI environment.
sudo apt-get install grub-efi-amd64-signed shim-signed
- RHEL7/CentOS7::
-
- sudo yum install grub2-efi shim
-
- Fedora::
+ RHEL8/CentOS8/Fedora::
sudo dnf install grub2-efi shim
@@ -154,7 +146,7 @@ the PXE UEFI environment.
sudo cp /boot/efi/EFI/fedora/shim.efi /tftpboot/bootx64.efi
sudo cp /boot/efi/EFI/fedora/grubx64.efi /tftpboot/grubx64.efi
- RHEL7/CentOS7::
+ RHEL8/CentOS8::
sudo cp /boot/efi/EFI/centos/shim.efi /tftpboot/bootx64.efi
sudo cp /boot/efi/EFI/centos/grubx64.efi /tftpboot/grubx64.efi
@@ -174,7 +166,7 @@ the PXE UEFI environment.
GRUB_DIR=/tftpboot/EFI/fedora
- RHEL7/CentOS7: Create grub.cfg under ``/tftpboot/EFI/centos`` directory::
+ RHEL8/CentOS8: Create grub.cfg under ``/tftpboot/EFI/centos`` directory::
GRUB_DIR=/tftpboot/EFI/centos
@@ -221,11 +213,7 @@ mode, perform these additional steps on the ironic conductor node.
sudo apt-get install syslinux-common pxelinux
- RHEL7/CentOS7::
-
- sudo yum install syslinux-tftpboot
-
- Fedora::
+ RHEL8/CentOS8/Fedora::
sudo dnf install syslinux-tftpboot
@@ -239,7 +227,7 @@ mode, perform these additional steps on the ironic conductor node.
sudo cp /usr/lib/PXELINUX/pxelinux.0 /tftpboot
- RHEL7/CentOS7/SUSE::
+ RHEL8/CentOS8/SUSE::
sudo cp /usr/share/syslinux/pxelinux.0 /tftpboot
@@ -254,7 +242,7 @@ mode, perform these additional steps on the ironic conductor node.
sudo cp /boot/extlinux/chain.c32 /tftpboot
- RHEL7/CentOS7/SUSE::
+ RHEL8/CentOS8/SUSE::
sudo cp /usr/share/syslinux/chain.c32 /tftpboot/
@@ -337,11 +325,7 @@ on the Bare Metal service node(s) where ``ironic-conductor`` is running.
apt-get install ipxe
- RHEL7/CentOS7::
-
- yum install ipxe-bootimgs
-
- Fedora::
+ RHEL8/CentOS8/Fedora::
dnf install ipxe-bootimgs
@@ -359,7 +343,7 @@ on the Bare Metal service node(s) where ``ironic-conductor`` is running.
cp /usr/lib/ipxe/{undionly.kpxe,ipxe.efi} /tftpboot
- Fedora/RHEL7/CentOS7::
+ Fedora/RHEL8/CentOS8::
cp /usr/share/ipxe/{undionly.kpxe,ipxe.efi} /tftpboot
@@ -434,7 +418,7 @@ on the Bare Metal service node(s) where ``ironic-conductor`` is running.
#. Restart the ``ironic-conductor`` process:
- Fedora/RHEL7/CentOS7/SUSE::
+ Fedora/RHEL8/CentOS8/SUSE::
sudo systemctl restart openstack-ironic-conductor
diff --git a/doc/source/install/configure-tenant-networks.rst b/doc/source/install/configure-tenant-networks.rst
index 37656483b..aa4bf44ae 100644
--- a/doc/source/install/configure-tenant-networks.rst
+++ b/doc/source/install/configure-tenant-networks.rst
@@ -141,7 +141,7 @@ provisioning will happen in a multi-tenant environment (which means using the
#. Restart the ironic-conductor and ironic-api services after the
modifications:
- - Fedora/RHEL7/CentOS7::
+ - Fedora/RHEL8/CentOS8::
sudo systemctl restart openstack-ironic-api
sudo systemctl restart openstack-ironic-conductor
diff --git a/doc/source/install/enabling-https.rst b/doc/source/install/enabling-https.rst
index 81abbc121..3b49ffd58 100644
--- a/doc/source/install/enabling-https.rst
+++ b/doc/source/install/enabling-https.rst
@@ -34,7 +34,7 @@ It can be enabled by making the following changes to ``/etc/glance/glance-api.co
#. Restart the glance-api service::
- Fedora/RHEL7/CentOS7/SUSE:
+ Fedora/RHEL8/CentOS8/SUSE:
sudo systemctl restart openstack-glance-api
Debian/Ubuntu:
@@ -86,7 +86,7 @@ To enable secure HTTPS communication between Bare Metal service and Image servic
#. Restart ironic-conductor service::
- Fedora/RHEL7/CentOS7/SUSE:
+ Fedora/RHEL8/CentOS8/SUSE:
sudo systemctl restart openstack-ironic-conductor
Debian/Ubuntu:
diff --git a/doc/source/install/include/configure-ironic-api-mod_wsgi.inc b/doc/source/install/include/configure-ironic-api-mod_wsgi.inc
index e881a0769..235cf1baa 100644
--- a/doc/source/install/include/configure-ironic-api-mod_wsgi.inc
+++ b/doc/source/install/include/configure-ironic-api-mod_wsgi.inc
@@ -6,11 +6,7 @@ Bare Metal service comes with an example file for configuring the
#. Install the apache service:
- RHEL7/CentOS7::
-
- sudo yum install httpd
-
- Fedora::
+ Fedora/RHEL8/CentOS8::
sudo dnf install httpd
@@ -27,7 +23,7 @@ Bare Metal service comes with an example file for configuring the
`Ironic project tree <https://opendev.org/openstack/ironic/raw/branch/master/etc/apache2/ironic>`_
and copy it to the apache sites:
- Fedora/RHEL7/CentOS7::
+ Fedora/RHEL8/CentOS8::
sudo cp etc/apache2/ironic /etc/httpd/conf.d/ironic.conf
@@ -58,7 +54,7 @@ Bare Metal service comes with an example file for configuring the
#. Enable the apache ``ironic`` in site and reload:
- Fedora/RHEL7/CentOS7::
+ Fedora/RHEL8/CentOS8::
sudo systemctl reload httpd
diff --git a/doc/source/install/include/configure-ironic-api.inc b/doc/source/install/include/configure-ironic-api.inc
index 301558a4b..713ef2b9c 100644
--- a/doc/source/install/include/configure-ironic-api.inc
+++ b/doc/source/install/include/configure-ironic-api.inc
@@ -120,7 +120,7 @@ Configuring ironic-api service
#. Restart the ironic-api service:
- Fedora/RHEL7/CentOS7/SUSE::
+ Fedora/RHEL8/CentOS8/SUSE::
sudo systemctl restart openstack-ironic-api
diff --git a/doc/source/install/install-obs.rst b/doc/source/install/install-obs.rst
index be50d39ca..8dcef32cb 100644
--- a/doc/source/install/install-obs.rst
+++ b/doc/source/install/install-obs.rst
@@ -21,7 +21,7 @@ Install and configure components
.. code-block:: console
- # zypper install openstack-ironic-api openstack-ironic-conductor python-ironicclient
+ # zypper install openstack-ironic-api openstack-ironic-conductor python3-ironicclient
#. Enable services
diff --git a/doc/source/install/install-rdo.rst b/doc/source/install/install-rdo.rst
index ccf3fc133..e1e53beed 100644
--- a/doc/source/install/install-rdo.rst
+++ b/doc/source/install/install-rdo.rst
@@ -6,26 +6,18 @@ Install and configure for Red Hat Enterprise Linux and CentOS
This section describes how to install and configure the Bare Metal service
-for Red Hat Enterprise Linux 7 and CentOS 7.
+for Red Hat Enterprise Linux 8 and CentOS 8.
.. include:: include/common-prerequisites.inc
Install and configure components
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
-#. Install from packages
+#. Install from packages (using dnf)
- - Using ``dnf``
-
- .. code-block:: console
-
- # dnf install openstack-ironic-api openstack-ironic-conductor python-ironicclient
-
- - Using ``yum``
-
- .. code-block:: console
+ .. code-block:: console
- # yum install openstack-ironic-api openstack-ironic-conductor python-ironicclient
+ # dnf install openstack-ironic-api openstack-ironic-conductor python3-ironicclient
#. Enable services
diff --git a/doc/source/install/install-ubuntu.rst b/doc/source/install/install-ubuntu.rst
index 92c8fc6d3..2d7e6faf2 100644
--- a/doc/source/install/install-ubuntu.rst
+++ b/doc/source/install/install-ubuntu.rst
@@ -16,7 +16,7 @@ Install and configure components
.. code-block:: console
- # apt-get install ironic-api ironic-conductor python-ironicclient
+ # apt-get install ironic-api ironic-conductor python3-ironicclient
#. Enable services
diff --git a/ironic/common/pxe_utils.py b/ironic/common/pxe_utils.py
index 5e27107d6..6f7a666c7 100644
--- a/ironic/common/pxe_utils.py
+++ b/ironic/common/pxe_utils.py
@@ -112,8 +112,9 @@ def _link_mac_pxe_configs(task, ipxe_enabled=False):
create_link(_get_pxe_mac_path(port.address, client_id=client_id,
ipxe_enabled=ipxe_enabled))
# Grub2 MAC address only
- create_link(_get_pxe_grub_mac_path(port.address,
- ipxe_enabled=ipxe_enabled))
+ for path in _get_pxe_grub_mac_path(port.address,
+ ipxe_enabled=ipxe_enabled):
+ create_link(path)
def _link_ip_address_pxe_configs(task, ipxe_enabled=False):
@@ -156,7 +157,9 @@ def _link_ip_address_pxe_configs(task, ipxe_enabled=False):
def _get_pxe_grub_mac_path(mac, ipxe_enabled=False):
root_dir = get_ipxe_root_dir() if ipxe_enabled else get_root_dir()
- return os.path.join(root_dir, mac + '.conf')
+ yield os.path.join(root_dir, "%s-%s-%s" %
+ ("grub.cfg", "01", mac.replace(':', "-").lower()))
+ yield os.path.join(root_dir, mac + '.conf')
def _get_pxe_mac_path(mac, delimiter='-', client_id=None,
@@ -361,8 +364,9 @@ def clean_up_pxe_config(task, ipxe_enabled=False):
_get_pxe_mac_path(port.address, client_id=client_id,
ipxe_enabled=ipxe_enabled))
# Grub2 MAC address based confiuration
- ironic_utils.unlink_without_raise(
- _get_pxe_grub_mac_path(port.address, ipxe_enabled=ipxe_enabled))
+ for path in _get_pxe_grub_mac_path(port.address,
+ ipxe_enabled=ipxe_enabled):
+ ironic_utils.unlink_without_raise(path)
if ipxe_enabled:
utils.rmtree_without_raise(os.path.join(get_ipxe_root_dir(),
task.node.uuid))
diff --git a/ironic/drivers/modules/drac/management.py b/ironic/drivers/modules/drac/management.py
index f595bea3b..ce864b79c 100644
--- a/ironic/drivers/modules/drac/management.py
+++ b/ironic/drivers/modules/drac/management.py
@@ -79,7 +79,7 @@ _DRAC_BOOT_MODES = ['Bios', 'Uefi']
_NON_PERSISTENT_BOOT_MODE = 'OneTime'
# Clear job id's constant
-_CLEAR_JOB_IDS = 'JID_CLEARALL_FORCE'
+_CLEAR_JOB_IDS = 'JID_CLEARALL'
# Clean steps constant
_CLEAR_JOBS_CLEAN_STEPS = ['clear_job_queue', 'known_good_state']
diff --git a/ironic/drivers/modules/redfish/management.py b/ironic/drivers/modules/redfish/management.py
index 69ad88673..676749ad0 100644
--- a/ironic/drivers/modules/redfish/management.py
+++ b/ironic/drivers/modules/redfish/management.py
@@ -81,12 +81,26 @@ def _set_boot_device(task, system, device, persistent=False):
Default: False.
:raises: SushyError on an error from the Sushy library
"""
- desired_enabled = BOOT_DEVICE_PERSISTENT_MAP_REV[persistent]
- current_enabled = system.boot.get('enabled')
- # NOTE(etingof): this can be racy, esp if BMC is not RESTful
- enabled = (desired_enabled
- if desired_enabled != current_enabled else None)
+ # The BMC handling of the persistent setting is vendor specific.
+ # Some vendors require that it not be set if currently equal to
+ # desired state (see https://storyboard.openstack.org/#!/story/2007355).
+ # Supermicro BMCs handle it in the opposite manner - the
+ # persistent setting must be set when setting the boot device
+ # (see https://storyboard.openstack.org/#!/story/2008547).
+ vendor = task.node.properties.get('vendor', None)
+ if vendor and vendor.lower() == 'supermicro':
+ enabled = BOOT_DEVICE_PERSISTENT_MAP_REV[persistent]
+ LOG.debug('Setting BootSourceOverrideEnable to %(enable)s '
+ 'on Supermicro BMC, node %(node)s',
+ {'enable': enabled, 'node': task.node.uuid})
+ else:
+ desired_enabled = BOOT_DEVICE_PERSISTENT_MAP_REV[persistent]
+ current_enabled = system.boot.get('enabled')
+
+ # NOTE(etingof): this can be racy, esp if BMC is not RESTful
+ enabled = (desired_enabled
+ if desired_enabled != current_enabled else None)
try:
system.set_system_boot_options(device, enabled=enabled)
@@ -217,7 +231,12 @@ class RedfishManagement(base.ManagementInterface):
# Ensure that boot mode is synced with what is set.
# Some BMCs reset it to default (BIOS) when changing the boot device.
- boot_mode_utils.sync_boot_mode(task)
+ # It should only be synced on these vendors as other vendor
+ # implementations will result in an error
+ # (see https://storyboard.openstack.org/#!/story/2008712)
+ vendor = task.node.properties.get('vendor', None)
+ if vendor and vendor.lower() == 'supermicro':
+ boot_mode_utils.sync_boot_mode(task)
def get_boot_device(self, task):
"""Get the current boot device for a node.
@@ -281,6 +300,19 @@ class RedfishManagement(base.ManagementInterface):
{'node': task.node.uuid, 'mode': mode,
'error': e})
LOG.error(error_msg)
+
+ # NOTE(sbaker): Some systems such as HPE Gen9 do not support
+ # getting or setting the boot mode. When setting failed and the
+ # mode attribute is missing from the boot field, raising
+ # UnsupportedDriverExtension will allow the deploy to continue.
+ if system.boot.get('mode') is None:
+ LOG.info(_('Attempt to set boot mode on node %(node)s '
+ 'failed to set boot mode as the node does not '
+ 'appear to support overriding the boot mode. '
+ 'Possibly partial Redfish implementation?'),
+ {'node': task.node.uuid})
+ raise exception.UnsupportedDriverExtension(
+ driver=task.node.driver, extension='set_boot_mode')
raise exception.RedfishError(error=error_msg)
def get_boot_mode(self, task):
diff --git a/ironic/tests/unit/common/test_pxe_utils.py b/ironic/tests/unit/common/test_pxe_utils.py
index 6a338267f..25847a325 100644
--- a/ironic/tests/unit/common/test_pxe_utils.py
+++ b/ironic/tests/unit/common/test_pxe_utils.py
@@ -247,16 +247,22 @@ class TestPXEUtils(db_base.DbTestCase):
mock.call(u'../1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/tftpboot/pxelinux.cfg/01-11-22-33-44-55-66'),
mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
+ '/tftpboot/grub.cfg-01-11-22-33-44-55-66'),
+ mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/tftpboot/11:22:33:44:55:66.conf'),
mock.call(u'../1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/tftpboot/pxelinux.cfg/01-11-22-33-44-55-67'),
mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
+ '/tftpboot/grub.cfg-01-11-22-33-44-55-67'),
+ mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/tftpboot/11:22:33:44:55:67.conf')
]
unlink_calls = [
mock.call('/tftpboot/pxelinux.cfg/01-11-22-33-44-55-66'),
+ mock.call('/tftpboot/grub.cfg-01-11-22-33-44-55-66'),
mock.call('/tftpboot/11:22:33:44:55:66.conf'),
mock.call('/tftpboot/pxelinux.cfg/01-11-22-33-44-55-67'),
+ mock.call('/tftpboot/grub.cfg-01-11-22-33-44-55-67'),
mock.call('/tftpboot/11:22:33:44:55:67.conf')
]
with task_manager.acquire(self.context, self.node.uuid) as task:
@@ -286,16 +292,22 @@ class TestPXEUtils(db_base.DbTestCase):
mock.call(u'../1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/tftpboot/pxelinux.cfg/20-11-22-33-44-55-66'),
mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
+ '/tftpboot/grub.cfg-01-11-22-33-44-55-66'),
+ mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/tftpboot/11:22:33:44:55:66.conf'),
mock.call(u'../1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/tftpboot/pxelinux.cfg/20-11-22-33-44-55-67'),
mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
+ '/tftpboot/grub.cfg-01-11-22-33-44-55-67'),
+ mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/tftpboot/11:22:33:44:55:67.conf')
]
unlink_calls = [
mock.call('/tftpboot/pxelinux.cfg/20-11-22-33-44-55-66'),
+ mock.call('/tftpboot/grub.cfg-01-11-22-33-44-55-66'),
mock.call('/tftpboot/11:22:33:44:55:66.conf'),
mock.call('/tftpboot/pxelinux.cfg/20-11-22-33-44-55-67'),
+ mock.call('/tftpboot/grub.cfg-01-11-22-33-44-55-67'),
mock.call('/tftpboot/11:22:33:44:55:67.conf')
]
with task_manager.acquire(self.context, self.node.uuid) as task:
@@ -318,16 +330,22 @@ class TestPXEUtils(db_base.DbTestCase):
mock.call(u'../1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/httpboot/pxelinux.cfg/11-22-33-44-55-66'),
mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
+ '/httpboot/grub.cfg-01-11-22-33-44-55-66'),
+ mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/httpboot/11:22:33:44:55:66.conf'),
mock.call(u'../1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/httpboot/pxelinux.cfg/11-22-33-44-55-67'),
mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
+ '/httpboot/grub.cfg-01-11-22-33-44-55-67'),
+ mock.call(u'1be26c0b-03f2-4d2e-ae87-c02d7f33c123/config',
'/httpboot/11:22:33:44:55:67.conf')
]
unlink_calls = [
mock.call('/httpboot/pxelinux.cfg/11-22-33-44-55-66'),
+ mock.call('/httpboot/grub.cfg-01-11-22-33-44-55-66'),
mock.call('/httpboot/11:22:33:44:55:66.conf'),
mock.call('/httpboot/pxelinux.cfg/11-22-33-44-55-67'),
+ mock.call('/httpboot/grub.cfg-01-11-22-33-44-55-67'),
mock.call('/httpboot/11:22:33:44:55:67.conf'),
]
with task_manager.acquire(self.context, self.node.uuid) as task:
@@ -562,6 +580,7 @@ class TestPXEUtils(db_base.DbTestCase):
ensure_calls = [
mock.call("/tftpboot/pxelinux.cfg/01-%s"
% address.replace(':', '-')),
+ mock.call("/tftpboot/grub.cfg-01-aa-aa-aa-aa-aa-aa"),
mock.call("/tftpboot/%s.conf" % address)
]
@@ -759,6 +778,7 @@ class TestPXEUtils(db_base.DbTestCase):
unlink_calls = [
mock.call('/tftpboot/10.10.0.1.conf'),
mock.call('/tftpboot/pxelinux.cfg/01-aa-aa-aa-aa-aa-aa'),
+ mock.call('/tftpboot/grub.cfg-01-aa-aa-aa-aa-aa-aa'),
mock.call('/tftpboot/' + address + '.conf')
]
unlink_mock.assert_has_calls(unlink_calls)
@@ -787,6 +807,7 @@ class TestPXEUtils(db_base.DbTestCase):
mock.call('/tftpboot/10.10.0.1.conf'),
mock.call('/tftpboot/pxelinux.cfg/01-%s' %
address.replace(':', '-')),
+ mock.call('/tftpboot/grub.cfg-01-aa-aa-aa-aa-aa-aa'),
mock.call('/tftpboot/' + address + '.conf')
]
@@ -815,6 +836,7 @@ class TestPXEUtils(db_base.DbTestCase):
unlink_calls = [
mock.call('/tftpboot/10.10.0.1.conf'),
mock.call('/tftpboot/pxelinux.cfg/01-aa-aa-aa-aa-aa-aa'),
+ mock.call('/tftpboot/grub.cfg-01-aa-aa-aa-aa-aa-aa'),
mock.call('/tftpboot/' + address + ".conf")
]
unlink_mock.assert_has_calls(unlink_calls)
@@ -864,12 +886,21 @@ class TestPXEUtils(db_base.DbTestCase):
unlink_calls = [
mock.call('/tftpboot/pxelinux.cfg/01-%s' %
address.replace(':', '-')),
+ mock.call('/tftpboot/grub.cfg-01-aa-aa-aa-aa-aa-aa'),
mock.call('/tftpboot/aa:aa:aa:aa:aa:aa.conf')
]
unlink_mock.assert_has_calls(unlink_calls)
rmtree_mock.assert_called_once_with(
os.path.join(CONF.pxe.tftp_root, self.node.uuid))
+ def test__get_pxe_grub_mac_path(self):
+ self.config(tftp_root='/tftpboot-path/', group='pxe')
+ address = "aa:aa:aa:aa:aa:aa"
+ actual = pxe_utils._get_pxe_grub_mac_path(address)
+ self.assertEqual('/tftpboot-path/grub.cfg-01-aa-aa-aa-aa-aa-aa',
+ next(actual))
+ self.assertEqual('/tftpboot-path/' + address + '.conf', next(actual))
+
@mock.patch.object(ipxe.iPXEBoot, '__init__', lambda self: None)
@mock.patch.object(pxe.PXEBoot, '__init__', lambda self: None)
@@ -1751,6 +1782,7 @@ class iPXEBuildConfigOptionsTestCase(db_base.DbTestCase):
ensure_calls = [
mock.call("/httpboot/pxelinux.cfg/%s"
% address.replace(':', '-')),
+ mock.call("/httpboot/grub.cfg-01-aa-aa-aa-aa-aa-aa"),
mock.call("/httpboot/%s.conf" % address)
]
diff --git a/ironic/tests/unit/drivers/modules/drac/test_management.py b/ironic/tests/unit/drivers/modules/drac/test_management.py
index 74f2ea372..4d9c791c2 100644
--- a/ironic/tests/unit/drivers/modules/drac/test_management.py
+++ b/ironic/tests/unit/drivers/modules/drac/test_management.py
@@ -806,7 +806,7 @@ class DracManagementTestCase(test_utils.BaseDracTest):
mock_client.reset_idrac.assert_called_once_with(
force=True, wait=True)
mock_client.delete_jobs.assert_called_once_with(
- job_ids=['JID_CLEARALL_FORCE'])
+ job_ids=['JID_CLEARALL'])
self.assertIsNone(return_value)
@@ -818,6 +818,6 @@ class DracManagementTestCase(test_utils.BaseDracTest):
shared=False) as task:
return_value = task.driver.management.clear_job_queue(task)
mock_client.delete_jobs.assert_called_once_with(
- job_ids=['JID_CLEARALL_FORCE'])
+ job_ids=['JID_CLEARALL'])
self.assertIsNone(return_value)
diff --git a/ironic/tests/unit/drivers/modules/redfish/test_management.py b/ironic/tests/unit/drivers/modules/redfish/test_management.py
index fd2bdcd4b..d81fbc56f 100644
--- a/ironic/tests/unit/drivers/modules/redfish/test_management.py
+++ b/ironic/tests/unit/drivers/modules/redfish/test_management.py
@@ -98,8 +98,7 @@ class RedfishManagementTestCase(db_base.DbTestCase):
# Asserts
fake_system.set_system_boot_options.assert_has_calls(
[mock.call(expected,
- enabled=sushy.BOOT_SOURCE_ENABLED_ONCE),
- mock.call(mode=sushy.BOOT_SOURCE_MODE_BIOS)])
+ enabled=sushy.BOOT_SOURCE_ENABLED_ONCE)])
mock_get_system.assert_called_with(task.node)
self.assertNotIn('redfish_boot_device',
task.node.driver_internal_info)
@@ -125,8 +124,7 @@ class RedfishManagementTestCase(db_base.DbTestCase):
fake_system.set_system_boot_options.assert_has_calls(
[mock.call(sushy.BOOT_SOURCE_TARGET_PXE,
- enabled=expected),
- mock.call(mode=sushy.BOOT_SOURCE_MODE_BIOS)])
+ enabled=expected)])
mock_get_system.assert_called_with(task.node)
self.assertNotIn('redfish_boot_device',
task.node.driver_internal_info)
@@ -153,8 +151,7 @@ class RedfishManagementTestCase(db_base.DbTestCase):
task, boot_devices.PXE, persistent=target)
fake_system.set_system_boot_options.assert_has_calls(
- [mock.call(sushy.BOOT_SOURCE_TARGET_PXE, enabled=None),
- mock.call(mode=sushy.BOOT_SOURCE_MODE_BIOS)])
+ [mock.call(sushy.BOOT_SOURCE_TARGET_PXE, enabled=None)])
mock_get_system.assert_called_with(task.node)
# Reset mocks
@@ -240,6 +237,40 @@ class RedfishManagementTestCase(db_base.DbTestCase):
sushy.BOOT_SOURCE_TARGET_PXE,
task.node.driver_internal_info['redfish_boot_device'])
+ @mock.patch.object(redfish_utils, 'get_system', autospec=True)
+ def test_set_boot_device_persistency_vendor(self, mock_get_system):
+ fake_system = mock_get_system.return_value
+ fake_system.boot.get.return_value = \
+ sushy.BOOT_SOURCE_ENABLED_CONTINUOUS
+
+ values = [
+ ('SuperMicro', sushy.BOOT_SOURCE_ENABLED_CONTINUOUS),
+ ('SomeVendor', None)
+ ]
+
+ for vendor, expected in values:
+ properties = self.node.properties
+ properties['vendor'] = vendor
+ self.node.properties = properties
+ self.node.save()
+ with task_manager.acquire(self.context, self.node.uuid,
+ shared=False) as task:
+ task.driver.management.set_boot_device(
+ task, boot_devices.PXE, persistent=True)
+ if vendor == 'SuperMicro':
+ fake_system.set_system_boot_options.assert_has_calls(
+ [mock.call(sushy.BOOT_SOURCE_TARGET_PXE,
+ enabled=expected),
+ mock.call(mode=sushy.BOOT_SOURCE_MODE_BIOS)])
+ else:
+ fake_system.set_system_boot_options.assert_has_calls(
+ [mock.call(sushy.BOOT_SOURCE_TARGET_PXE,
+ enabled=expected)])
+
+ # Reset mocks
+ fake_system.set_system_boot_options.reset_mock()
+ mock_get_system.reset_mock()
+
def test_restore_boot_device(self):
fake_system = mock.Mock()
with task_manager.acquire(self.context, self.node.uuid,
@@ -314,6 +345,12 @@ class RedfishManagementTestCase(db_base.DbTestCase):
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_set_boot_mode(self, mock_get_system):
+ boot_attribute = {
+ 'target': sushy.BOOT_SOURCE_TARGET_PXE,
+ 'enabled': sushy.BOOT_SOURCE_ENABLED_CONTINUOUS,
+ 'mode': sushy.BOOT_SOURCE_MODE_BIOS,
+ }
+ fake_system = mock.Mock(boot=boot_attribute)
fake_system = mock.Mock()
mock_get_system.return_value = fake_system
with task_manager.acquire(self.context, self.node.uuid,
@@ -338,7 +375,12 @@ class RedfishManagementTestCase(db_base.DbTestCase):
@mock.patch.object(sushy, 'Sushy', autospec=True)
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_set_boot_mode_fail(self, mock_get_system, mock_sushy):
- fake_system = mock.Mock()
+ boot_attribute = {
+ 'target': sushy.BOOT_SOURCE_TARGET_PXE,
+ 'enabled': sushy.BOOT_SOURCE_ENABLED_CONTINUOUS,
+ 'mode': sushy.BOOT_SOURCE_MODE_BIOS,
+ }
+ fake_system = mock.Mock(boot=boot_attribute)
fake_system.set_system_boot_options.side_effect = (
sushy.exceptions.SushyError)
mock_get_system.return_value = fake_system
@@ -351,6 +393,27 @@ class RedfishManagementTestCase(db_base.DbTestCase):
mode=boot_modes.UEFI)
mock_get_system.assert_called_once_with(task.node)
+ @mock.patch.object(sushy, 'Sushy', autospec=True)
+ @mock.patch.object(redfish_utils, 'get_system', autospec=True)
+ def test_set_boot_mode_unsupported(self, mock_get_system, mock_sushy):
+ boot_attribute = {
+ 'target': sushy.BOOT_SOURCE_TARGET_PXE,
+ 'enabled': sushy.BOOT_SOURCE_ENABLED_CONTINUOUS,
+ }
+ fake_system = mock.Mock(boot=boot_attribute)
+ error = sushy.exceptions.BadRequestError('PATCH', '/', mock.Mock())
+ fake_system.set_system_boot_options.side_effect = error
+ mock_get_system.return_value = fake_system
+ with task_manager.acquire(self.context, self.node.uuid,
+ shared=False) as task:
+ self.assertRaisesRegex(
+ exception.UnsupportedDriverExtension,
+ 'does not support set_boot_mode',
+ task.driver.management.set_boot_mode, task, boot_modes.UEFI)
+ fake_system.set_system_boot_options.assert_called_once_with(
+ mode=boot_modes.UEFI)
+ mock_get_system.assert_called_once_with(task.node)
+
@mock.patch.object(redfish_utils, 'get_system', autospec=True)
def test_get_boot_mode(self, mock_get_system):
boot_attribute = {
diff --git a/ironic/tests/unit/drivers/third_party_driver_mocks.py b/ironic/tests/unit/drivers/third_party_driver_mocks.py
index 62c3b4b89..8a76d87f3 100644
--- a/ironic/tests/unit/drivers/third_party_driver_mocks.py
+++ b/ironic/tests/unit/drivers/third_party_driver_mocks.py
@@ -234,6 +234,8 @@ if not sushy:
type('MissingAttributeError', (sushy.exceptions.SushyError,), {}))
sushy.exceptions.OEMExtensionNotFoundError = (
type('OEMExtensionNotFoundError', (sushy.exceptions.SushyError,), {}))
+ sushy.exceptions.BadRequestError = (
+ type('BadRequestError', (sushy.exceptions.SushyError,), {}))
sushy.auth = mock.MagicMock(spec_set=mock_specs.SUSHY_AUTH_SPEC)
sys.modules['sushy.auth'] = sushy.auth
diff --git a/releasenotes/notes/fix-grub2-config-file-name-88e689a982a21684.yaml b/releasenotes/notes/fix-grub2-config-file-name-88e689a982a21684.yaml
new file mode 100644
index 000000000..df17585d1
--- /dev/null
+++ b/releasenotes/notes/fix-grub2-config-file-name-88e689a982a21684.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Fixes the problem about grub2 config file. Some higher versions of
+ grub2 (e.g. 2.05 or 2.06-rc1) use grub.cfg-01-MAC, while another
+ lower versions of grub2 (e.g. 2.04) use MAC.conf, so we generate
+ both paths in order to be compatible with both.
diff --git a/releasenotes/notes/redfish-boot-mode-override-not-present-handling-92e7263617e467c4.yaml b/releasenotes/notes/redfish-boot-mode-override-not-present-handling-92e7263617e467c4.yaml
new file mode 100644
index 000000000..79f20e439
--- /dev/null
+++ b/releasenotes/notes/redfish-boot-mode-override-not-present-handling-92e7263617e467c4.yaml
@@ -0,0 +1,9 @@
+---
+fixes:
+ - |
+ Adds handling of Redfish BMC's which lack a ``BootSourceOverrideMode``
+ flag, such that it is no longer a fatal error for a deployment if the BMC
+ does not support this field. This most common on BMCs which feature only
+ a partial implementation of the ``ComputerSystem`` resource ``boot``,
+ but may also be observable on some older generations of BMCs which
+ recieved updates to have partial Redfish support.
diff --git a/releasenotes/notes/restrict-sync-mode-after-device-to-supermicro-218e8cb57735c685.yaml b/releasenotes/notes/restrict-sync-mode-after-device-to-supermicro-218e8cb57735c685.yaml
new file mode 100644
index 000000000..0436b81e6
--- /dev/null
+++ b/releasenotes/notes/restrict-sync-mode-after-device-to-supermicro-218e8cb57735c685.yaml
@@ -0,0 +1,11 @@
+---
+fixes:
+ - |
+ The fix for story
+ `2008252 <https://storyboard.openstack.org/#!/story/2008252>`_ synced
+ the boot mode after changing the boot device because Supermicro nodes
+ reset the boot mode if not included in the boot device set. However this
+ can cause a problem on Dell nodes when changing the mode uefi->bios or
+ bios->uefi, see `story 2008712
+ <https://storyboard.openstack.org/#!/story/2008712>`_ for details.
+ Restrict the syncing of the boot mode to Supermicro.
diff --git a/releasenotes/notes/supermicro-redfish-override-enabled-aa51686ed33d3061.yaml b/releasenotes/notes/supermicro-redfish-override-enabled-aa51686ed33d3061.yaml
new file mode 100644
index 000000000..f3af2a169
--- /dev/null
+++ b/releasenotes/notes/supermicro-redfish-override-enabled-aa51686ed33d3061.yaml
@@ -0,0 +1,15 @@
+---
+fixes:
+ - |
+ When Ironic configures the BootSourceOverrideTarget setting via Redfish,
+ on Supermicro BMCs it must always configure BootSourceOverrideEnabled or
+ that will revert to default (Once) on the BMC, see `story 2008547
+ <https://storyboard.openstack.org/#!/story/2008547>`_ for details.
+ This is different than what is currently implemented for other BMCs in
+ which the BootSourceOverrideEnabled is not configured if it matches the
+ current setting (see `story 2007355
+ <https://storyboard.openstack.org/#!/story/2007355>`_).
+
+ This requires that node.properties['vendor'] be 'supermicro' which will
+ be set by Ironic from the Redfish system response or can be set
+ manually.
diff --git a/releasenotes/notes/update-clear-job-id-constant-fix-c69cf96c55364bb3.yaml b/releasenotes/notes/update-clear-job-id-constant-fix-c69cf96c55364bb3.yaml
new file mode 100644
index 000000000..9ecaac9f2
--- /dev/null
+++ b/releasenotes/notes/update-clear-job-id-constant-fix-c69cf96c55364bb3.yaml
@@ -0,0 +1,7 @@
+---
+fixes:
+ - |
+ Fixes an issue of powering off with the ``idrac-wsman`` management
+ interface while the execution of a clear job queue cleaning step is
+ proceeding.
+ Prior to this fix, the clean step would fail when powering off a node.
diff --git a/tools/test-setup.sh b/tools/test-setup.sh
index 186507e1d..c82f4716a 100755
--- a/tools/test-setup.sh
+++ b/tools/test-setup.sh
@@ -23,8 +23,8 @@ sudo -H mysqladmin -u root password $DB_ROOT_PW
sudo -H mysql -u root -p$DB_ROOT_PW -h localhost -e "
DELETE FROM mysql.user WHERE User='';
FLUSH PRIVILEGES;
- GRANT ALL PRIVILEGES ON *.*
- TO '$DB_USER'@'%' identified by '$DB_PW' WITH GRANT OPTION;"
+ CREATE USER '$DB_USER'@'%' IDENTIFIED BY '$DB_PW';
+ GRANT ALL PRIVILEGES ON *.* TO '$DB_USER'@'%' WITH GRANT OPTION;"
# Now create our database.
mysql -u $DB_USER -p$DB_PW -h 127.0.0.1 -e "