Add configuration option 'hardware-enablement-options'

This new config option allows operators to pass custom configuration
options to the ironic-conductor service.

Usage example:

    cat << EOF > ./config.txt
    [DEFAULT]
    enabled_hardware_types = intel-ipmi, ipmi, idrac
    enabled_power_interfaces = ipmitool, idrac-wsman
    EOF
    juju config ironic-conductor \
        hardware-enablement-options=@./config.txt

Closes-Bug: #2002151
Change-Id: I3e2ca81b272e61e4069d80b52902b243a5f0ba19
(cherry picked from commit 41efb85ef6)
(cherry picked from commit 0ec212e237)
(cherry picked from commit e377181d42)
(cherry picked from commit 166be64d1f)
(cherry picked from commit e495f42d6d)
(cherry picked from commit 07fe82be4b)
This commit is contained in:
Felipe Reyes
2023-02-28 12:34:56 -03:00
parent 0b7c9304f9
commit b61503d6d0
8 changed files with 110 additions and 1 deletions

View File

@@ -176,3 +176,9 @@ options:
for. Defaults to 20 minutes. If some deploys get a 401 response code
when trying to download from the temporary URL, try raising this
duration.
hardware-enablement-options:
default:
type: string
description: |
Options passed to the managed service to set configuration keys that
enable the use of specific hardware.

View File

@@ -11,10 +11,13 @@ from charms_openstack.adapters import (
OpenStackRelationAdapters,
)
from charmhelpers.contrib.openstack.utils import os_release
from charmhelpers.contrib.openstack import templating
from charmhelpers.core import host
import charm.openstack.ironic.controller_utils as controller_utils
import charms_openstack.adapters as adapters
import charmhelpers.contrib.network.ip as ch_ip
import charmhelpers.contrib.openstack.utils as ch_utils
import charms.leadership as leadership
import charms.reactive as reactive
@@ -37,6 +40,10 @@ PACKAGES = [
IRONIC_DIR = "/etc/ironic/"
IRONIC_CONF = os.path.join(IRONIC_DIR, "ironic.conf")
IRONIC_CONF_D = os.path.join(IRONIC_DIR, "conf.d")
IRONIC_CONF_HW_ENABLEMENT = os.path.join(IRONIC_CONF_D,
"90-hardware-enablement.conf")
IRONIC_DEFAULT = "/etc/default/ironic-conductor"
ROOTWRAP_CONF = os.path.join(IRONIC_DIR, "rootwrap.conf")
FILTERS_DIR = os.path.join(IRONIC_DIR, "rootwrap.d")
IRONIC_LIB_FILTERS = os.path.join(
@@ -194,6 +201,8 @@ class IronicConductorCharm(charms_openstack.charm.OpenStackCharm):
restart_map = {
IRONIC_CONF: ['ironic-conductor', ],
IRONIC_DEFAULT: ['ironic-conductor', ],
IRONIC_CONF_HW_ENABLEMENT: ['ironic-conductor', ],
IRONIC_UTILS_FILTERS: ['ironic-conductor', ],
IRONIC_LIB_FILTERS: ['ironic-conductor', ],
ROOTWRAP_CONF: ['ironic-conductor', ],
@@ -313,6 +322,7 @@ class IronicConductorCharm(charms_openstack.charm.OpenStackCharm):
def install(self):
self.configure_source()
super().install()
self._reconfigure_ironic_conductor()
self.pxe_config._copy_resources()
self.assess_status()
@@ -434,3 +444,29 @@ class IronicConductorCharm(charms_openstack.charm.OpenStackCharm):
return ('blocked', msg)
return (None, None)
def upgrade_charm(self):
"""Custom upgrade charm.
Side effects:
- Create /etc/ironic/conf.d/ directory.
- Reconfigure ironic-conductor service to use the previously created
directory.
"""
self._reconfigure_ironic_conductor()
super().upgrade_charm()
def _reconfigure_ironic_conductor(self):
"""Reconfigure ironic-conductor daemon.
Set /etc/default/ironic-conductor to pass --config-dir in DAEMON_ARGS.
"""
if not os.path.isdir(IRONIC_CONF_D):
host.mkdir(IRONIC_CONF_D)
# reconfigure ironic-conductor to run it with --conf-dir
release = ch_utils.os_release('ironic-common')
configs = templating.OSConfigRenderer(templates_dir='templates/',
openstack_release=release)
configs.register(config_file=IRONIC_DEFAULT, contexts=[])
configs.write_all()

View File

@@ -0,0 +1,7 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
###############################################################################
{%- if options.hardware_enablement_options %}
{{ options.hardware_enablement_options }}
{%- endif %}

View File

@@ -0,0 +1,5 @@
###############################################################################
# [ WARNING ]
# Configuration file maintained by Juju. Local changes may be overwritten.
###############################################################################
DAEMON_ARGS="--config-dir=/etc/ironic/conf.d/"

View File

@@ -248,6 +248,9 @@ services:
disable-secure-erase: true
use-ipxe: true
enabled-network-interfaces: "flat, noop"
hardware-enablement-options: |
[ipmi]
debug = true
neutron-ironic-agent:
charm: ch:neutron-api-plugin-ironic
num_units: 0

View File

@@ -248,6 +248,9 @@ services:
disable-secure-erase: true
use-ipxe: true
enabled-network-interfaces: "flat, noop"
hardware-enablement-options: |
[ipmi]
debug = true
neutron-ironic-agent:
charm: ch:neutron-api-plugin-ironic
num_units: 0

View File

@@ -291,6 +291,9 @@ services:
disable-secure-erase: true
use-ipxe: true
enabled-network-interfaces: "flat, noop"
hardware-enablement-options: |
[ipmi]
debug = true
neutron-ironic-agent:
charm: ch:neutron-api-plugin-ironic
num_units: 0

View File

@@ -12,8 +12,9 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
from unittest import mock
import charms_openstack.test_mocks
import charms_openstack.test_utils as test_utils
import charms.leadership as leadership
import charmhelpers.core.hookenv as hookenv
@@ -440,3 +441,48 @@ class TestIronicCharm(test_utils.PatchHelper):
' (bogus) is not enabled in enabled-deploy-interfaces: direct, '
'iscsi')
self.assertEqual(target.custom_assess_status_check(), expected_status)
@mock.patch('charms_openstack.charm.OpenStackCharm.upgrade_charm')
def test_upgrade_charm(self, upgrade_charm):
os_release.return_value = "ussuri"
cfg_data = {
"openstack-origin": "distro",
}
hookenv.config.return_value = cfg_data
target = ironic.IronicConductorCharm()
target.upgrade_charm()
# check the parent's upgrade_charm was called
upgrade_charm.assert_called()
os_module = charms_openstack.test_mocks.charmhelpers.contrib.openstack
templating = os_module.templating
templating.OSConfigRenderer.assert_called_with(
templates_dir='templates/', openstack_release='ussuri')
configs = templating.OSConfigRenderer()
configs.register.assert_called_with(config_file=ironic.IRONIC_DEFAULT,
contexts=[])
configs.write_all.assert_called_with()
@mock.patch('charms_openstack.charm.OpenStackCharm.install')
def test_install(self, install):
os_release.return_value = "ussuri"
cfg_data = {
"openstack-origin": "distro",
}
charmhelpers = charms_openstack.test_mocks.charmhelpers
os_utils = charmhelpers.contrib.openstack.utils
os_utils.get_source_and_pgp_key.return_value = (None, None)
hookenv.config.return_value = cfg_data
target = ironic.IronicConductorCharm()
target.install()
install.assert_called_with()
os_module = charms_openstack.test_mocks.charmhelpers.contrib.openstack
templating = os_module.templating
templating.OSConfigRenderer.assert_called_with(
templates_dir='templates/', openstack_release='ussuri')
configs = templating.OSConfigRenderer(templates_dir='templates/',
openstack_release='ussuri')
configs.register.assert_called_with(config_file=ironic.IRONIC_DEFAULT,
contexts=[])
configs.write_all.assert_called_with()