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)
This commit is contained in:
Felipe Reyes 2023-02-28 12:34:56 -03:00
parent f5787906ac
commit 166be64d1f
7 changed files with 107 additions and 1 deletions

View File

@ -180,3 +180,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

@ -15,10 +15,13 @@ from charmhelpers.contrib.openstack.utils import (
CompareOpenStackReleases,
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
@ -41,6 +44,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(
@ -198,6 +205,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', ],
@ -317,6 +326,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()
@ -443,6 +453,32 @@ class IronicConductorCharm(charms_openstack.charm.OpenStackCharm):
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()
class IronicConductorXenaCharm(IronicConductorCharm):

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

@ -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

@ -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,9 +12,10 @@
# See the License for the specific language governing permissions and
# limitations under the License.
import mock
from copy import deepcopy
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
@ -474,3 +475,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()